chef 13.0.118 → 13.1.31

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -27
  3. data/VERSION +1 -1
  4. data/acceptance/.bundle/config +2 -0
  5. data/acceptance/basics/test/integration/chef-current-install/serverspec/chef_client_spec.rb +1 -1
  6. data/acceptance/bin/aws.rb +17 -0
  7. data/acceptance/bin/berks +17 -0
  8. data/acceptance/bin/bundler +17 -0
  9. data/acceptance/bin/chef-acceptance +17 -0
  10. data/acceptance/bin/coderay +17 -0
  11. data/acceptance/bin/erubis +17 -0
  12. data/acceptance/bin/htmldiff +17 -0
  13. data/acceptance/bin/httpclient +17 -0
  14. data/acceptance/bin/inspec +17 -0
  15. data/acceptance/bin/kitchen +17 -0
  16. data/acceptance/bin/ldiff +17 -0
  17. data/acceptance/bin/nokogiri +17 -0
  18. data/acceptance/bin/pry +17 -0
  19. data/acceptance/bin/rake +17 -0
  20. data/acceptance/bin/rspec +17 -0
  21. data/acceptance/bin/rwinrm +17 -0
  22. data/acceptance/bin/rwinrmcp +17 -0
  23. data/acceptance/bin/safe_yaml +17 -0
  24. data/acceptance/bin/thor +17 -0
  25. data/acceptance/fips/.kitchen/fips-unit-functional-centos-6.yml +7 -0
  26. data/acceptance/fips/.kitchen/kitchen-vagrant/kitchen-fips-fips-unit-functional-centos-6/.vagrant/machines/default/virtualbox/action_set_name +1 -0
  27. data/acceptance/fips/.kitchen/kitchen-vagrant/kitchen-fips-fips-unit-functional-centos-6/.vagrant/machines/default/virtualbox/creator_uid +1 -0
  28. data/acceptance/fips/.kitchen/kitchen-vagrant/kitchen-fips-fips-unit-functional-centos-6/.vagrant/machines/default/virtualbox/id +1 -0
  29. data/acceptance/fips/.kitchen/kitchen-vagrant/kitchen-fips-fips-unit-functional-centos-6/.vagrant/machines/default/virtualbox/index_uuid +1 -0
  30. data/acceptance/fips/.kitchen/kitchen-vagrant/kitchen-fips-fips-unit-functional-centos-6/.vagrant/machines/default/virtualbox/private_key +27 -0
  31. data/acceptance/fips/.kitchen/kitchen-vagrant/kitchen-fips-fips-unit-functional-centos-6/.vagrant/machines/default/virtualbox/synced_folders +1 -0
  32. data/acceptance/fips/.kitchen/kitchen-vagrant/kitchen-fips-fips-unit-functional-centos-6/Vagrantfile +11 -0
  33. data/acceptance/fips/.kitchen/logs/fips-integration-centos-6.log +0 -0
  34. data/acceptance/fips/.kitchen/logs/fips-integration-windows-2012r2.log +0 -0
  35. data/acceptance/fips/.kitchen/logs/fips-unit-functional-centos-6.log +80 -0
  36. data/acceptance/fips/.kitchen/logs/kitchen.log +4 -0
  37. data/chef.gemspec +1 -1
  38. data/lib/chef/application/client.rb +1 -1
  39. data/lib/chef/application/knife.rb +1 -1
  40. data/lib/chef/application/solo.rb +1 -0
  41. data/lib/chef/cookbook/remote_file_vendor.rb +1 -1
  42. data/lib/chef/cookbook/synchronizer.rb +20 -7
  43. data/lib/chef/cookbook_manifest.rb +8 -0
  44. data/lib/chef/deprecated.rb +10 -0
  45. data/lib/chef/knife/client_key_create.rb +3 -0
  46. data/lib/chef/knife/client_key_delete.rb +1 -0
  47. data/lib/chef/knife/client_key_edit.rb +1 -0
  48. data/lib/chef/knife/client_key_list.rb +1 -0
  49. data/lib/chef/knife/client_key_show.rb +1 -0
  50. data/lib/chef/knife/user_key_create.rb +1 -0
  51. data/lib/chef/knife/user_key_delete.rb +1 -0
  52. data/lib/chef/knife/user_key_edit.rb +1 -0
  53. data/lib/chef/knife/user_key_list.rb +1 -0
  54. data/lib/chef/knife/user_key_show.rb +1 -0
  55. data/lib/chef/local_mode.rb +1 -0
  56. data/lib/chef/mixin/which.rb +1 -1
  57. data/lib/chef/platform/service_helpers.rb +1 -1
  58. data/lib/chef/provider/apt_repository.rb +7 -4
  59. data/lib/chef/provider/execute.rb +1 -1
  60. data/lib/chef/provider/package/cab.rb +18 -13
  61. data/lib/chef/provider/package/msu.rb +2 -2
  62. data/lib/chef/provider/package/rubygems.rb +3 -5
  63. data/lib/chef/provider/user/aix.rb +1 -1
  64. data/lib/chef/provider/user/windows.rb +1 -1
  65. data/lib/chef/providers.rb +0 -1
  66. data/lib/chef/resource/breakpoint.rb +12 -0
  67. data/lib/chef/resource/env.rb +3 -35
  68. data/lib/chef/resource/route.rb +13 -107
  69. data/lib/chef/resource/service.rb +5 -5
  70. data/lib/chef/resource/user.rb +6 -4
  71. data/lib/chef/resource/windows_task.rb +3 -3
  72. data/lib/chef/run_context.rb +7 -0
  73. data/lib/chef/runner.rb +2 -1
  74. data/lib/chef/version.rb +1 -1
  75. data/spec/functional/resource/chocolatey_package_spec.rb +1 -8
  76. data/spec/functional/resource/registry_spec.rb +1 -1
  77. data/spec/functional/resource/user/useradd_spec.rb +1 -1
  78. data/spec/functional/resource/windows_task_spec.rb +459 -0
  79. data/spec/integration/client/client_spec.rb +32 -0
  80. data/spec/spec_helper.rb +2 -0
  81. data/spec/support/platform_helpers.rb +7 -0
  82. data/spec/support/shared/unit/provider/useradd_based_user_provider.rb +3 -3
  83. data/spec/unit/cookbook/synchronizer_spec.rb +5 -4
  84. data/spec/unit/cookbook_manifest_spec.rb +17 -2
  85. data/spec/unit/provider/env_spec.rb +2 -2
  86. data/spec/unit/provider/group/dscl_spec.rb +2 -2
  87. data/spec/unit/provider/group/pw_spec.rb +3 -3
  88. data/spec/unit/provider/group/usermod_spec.rb +6 -6
  89. data/spec/unit/provider/group/windows_spec.rb +3 -3
  90. data/spec/unit/provider/group_spec.rb +4 -4
  91. data/spec/unit/provider/http_request_spec.rb +1 -1
  92. data/spec/unit/provider/package/aix_spec.rb +2 -2
  93. data/spec/unit/provider/package/apt_spec.rb +2 -2
  94. data/spec/unit/provider/package/ips_spec.rb +2 -2
  95. data/spec/unit/provider/package/macports_spec.rb +4 -4
  96. data/spec/unit/provider/package/pacman_spec.rb +2 -2
  97. data/spec/unit/provider/package/rubygems_spec.rb +14 -11
  98. data/spec/unit/provider/package/yum_spec.rb +10 -10
  99. data/spec/unit/provider/route_spec.rb +7 -7
  100. data/spec/unit/provider/service/arch_service_spec.rb +6 -6
  101. data/spec/unit/provider/service/init_service_spec.rb +2 -2
  102. data/spec/unit/provider/service/invokercd_service_spec.rb +1 -1
  103. data/spec/unit/provider/service/simple_service_spec.rb +1 -1
  104. data/spec/unit/provider/service/upstart_service_spec.rb +5 -5
  105. data/spec/unit/provider/service_spec.rb +1 -1
  106. data/spec/unit/provider/user/aix_spec.rb +97 -0
  107. data/spec/unit/provider/user/pw_spec.rb +5 -5
  108. data/spec/unit/provider/user_spec.rb +1 -1
  109. data/spec/unit/provider_resolver_spec.rb +11 -11
  110. data/spec/unit/resource/breakpoint_spec.rb +28 -11
  111. data/spec/unit/resource/windows_task_spec.rb +2 -2
  112. data/spec/unit/runner_spec.rb +4 -0
  113. data/tasks/bin/run_external_test +20 -42
  114. data/tasks/bundle.rb +0 -8
  115. data/tasks/changelog.rb +5 -1
  116. data/tasks/dependencies.rb +4 -2
  117. metadata +80 -19
  118. data/acceptance/fips/.acceptance/acceptance-cookbook/.gitignore +0 -2
  119. data/acceptance/fips/.acceptance/acceptance-cookbook/metadata.rb +0 -2
  120. data/acceptance/fips/.acceptance/acceptance-cookbook/recipes/destroy.rb +0 -1
  121. data/acceptance/fips/.acceptance/acceptance-cookbook/recipes/provision.rb +0 -1
  122. data/acceptance/fips/.acceptance/acceptance-cookbook/recipes/verify.rb +0 -1
  123. data/acceptance/fips/.kitchen.yml +0 -8
  124. data/acceptance/fips/test/integration/fips-integration/serverspec/Gemfile +0 -9
  125. data/acceptance/fips/test/integration/fips-integration/serverspec/fips-integration_spec.rb +0 -52
  126. data/acceptance/fips/test/integration/fips-unit-functional/serverspec/Gemfile +0 -7
  127. data/acceptance/fips/test/integration/fips-unit-functional/serverspec/fips-unit-functional_spec.rb +0 -56
  128. data/lib/chef/provider/breakpoint.rb +0 -38
  129. data/spec/unit/provider/breakpoint_spec.rb +0 -53
  130. data/tasks/bin/create-override-gemfile +0 -110
  131. data/tasks/gemfile_util.rb +0 -390
@@ -1,52 +0,0 @@
1
- require "mixlib/shellout"
2
- require "bundler"
3
-
4
- describe "Chef Fips Integration Specs" do
5
- def windows?
6
- if RUBY_PLATFORM =~ /mswin|mingw|windows/
7
- true
8
- else
9
- false
10
- end
11
- end
12
-
13
- let(:omnibus_root) do
14
- if windows?
15
- "c:/opscode/chef"
16
- else
17
- "/opt/chef"
18
- end
19
- end
20
-
21
- let(:env) do
22
- {
23
- "PATH" => [ "#{omnibus_root}/embedded/bin", ENV["PATH"] ].join(File::PATH_SEPARATOR),
24
- "BUNDLE_GEMFILE" => "#{omnibus_root}/Gemfile",
25
- "GEM_PATH" => nil, "GEM_CACHE" => nil, "GEM_HOME" => nil,
26
- "BUNDLE_IGNORE_CONFIG" => "true",
27
- "BUNDLE_FROZEN" => "1",
28
- "CHEF_FIPS" => "1"
29
- }
30
- end
31
-
32
- let(:chef_dir) do
33
- cmd = Mixlib::ShellOut.new("bundle show chef", env: env).run_command
34
- cmd.error!
35
- cmd.stdout.chomp
36
- end
37
-
38
- def run_rspec_test(test)
39
- Bundler.with_clean_env do
40
- cmd = Mixlib::ShellOut.new(
41
- "bundle exec rspec -f documentation -t ~requires_git #{test}",
42
- env: env, cwd: chef_dir, timeout: 3600
43
- )
44
- cmd.run_command.error!
45
- end
46
- end
47
-
48
- it "passes the integration specs" do
49
- skip
50
- #run_rspec_test("spec/integration")
51
- end
52
- end
@@ -1,7 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Until https://github.com/test-kitchen/busser-serverspec/pull/42 is merged and
4
- # released, we need to include rake and rspec-core in the Gemfile
5
- gem "rake"
6
- gem "rspec-core"
7
- gem "mixlib-shellout"
@@ -1,56 +0,0 @@
1
- require "mixlib/shellout"
2
- require "bundler"
3
-
4
- describe "Chef Fips Unit/Functional Specs" do
5
- def windows?
6
- if RUBY_PLATFORM =~ /mswin|mingw|windows/
7
- true
8
- else
9
- false
10
- end
11
- end
12
-
13
- let(:omnibus_root) do
14
- if windows?
15
- "c:/opscode/chef"
16
- else
17
- "/opt/chef"
18
- end
19
- end
20
-
21
- let(:env) do
22
- {
23
- "PATH" => [ "#{omnibus_root}/embedded/bin", ENV["PATH"] ].join(File::PATH_SEPARATOR),
24
- "BUNDLE_GEMFILE" => "#{omnibus_root}/Gemfile",
25
- "GEM_PATH" => nil, "GEM_CACHE" => nil, "GEM_HOME" => nil,
26
- "BUNDLE_IGNORE_CONFIG" => "true",
27
- "BUNDLE_FROZEN" => "1",
28
- "CHEF_FIPS" => "1"
29
- }
30
- end
31
-
32
- let(:chef_dir) do
33
- cmd = Mixlib::ShellOut.new("bundle show chef", env: env).run_command
34
- cmd.error!
35
- cmd.stdout.chomp
36
- end
37
-
38
- def run_rspec_test(test)
39
- Bundler.with_clean_env do
40
- cmd = Mixlib::ShellOut.new(
41
- "bundle exec rspec -f documentation -t ~requires_git #{test}",
42
- env: env, cwd: chef_dir, timeout: 3600
43
- )
44
- cmd.run_command.error!
45
- end
46
- end
47
-
48
- it "passes the unit specs" do
49
- run_rspec_test("spec/unit")
50
- end
51
-
52
- it "passes the functional specs" do
53
- run_rspec_test("spec/functional")
54
- end
55
-
56
- end
@@ -1,38 +0,0 @@
1
- #
2
- # Author:: Daniel DeLeo (<dan@kallistec.com>)
3
- # Copyright:: Copyright 2008-2017, Chef Software Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- class Chef
20
- class Provider
21
- class Breakpoint < Chef::Provider
22
-
23
- provides :breakpoint
24
-
25
- def load_current_resource
26
- end
27
-
28
- def action_break
29
- if defined?(Shell) && Shell.running?
30
- run_context.resource_collection.iterator.pause
31
- new_resource.updated_by_last_action(true)
32
- run_context.resource_collection.iterator
33
- end
34
- end
35
-
36
- end
37
- end
38
- end
@@ -1,53 +0,0 @@
1
- #
2
- # Author:: Daniel DeLeo (<dan@kallistec.com>)
3
- # Copyright:: Copyright 2008-2016, Chef Software Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require "spec_helper"
20
- describe Chef::Provider::Breakpoint do
21
-
22
- before do
23
- @resource = Chef::Resource::Breakpoint.new
24
- @node = Chef::Node.new
25
- @events = Chef::EventDispatch::Dispatcher.new
26
- @run_context = Chef::RunContext.new(@node, {}, @events)
27
- @collection = double("resource collection")
28
- allow(@run_context).to receive(:resource_collection).and_return(@collection)
29
- @provider = Chef::Provider::Breakpoint.new(@resource, @run_context)
30
- end
31
-
32
- it "responds to load_current_resource" do
33
- expect(@provider).to respond_to(:load_current_resource)
34
- end
35
-
36
- it "gets the iterator from @collection and pauses it" do
37
- allow(Shell).to receive(:running?).and_return(true)
38
- @iterator = double("stepable_iterator")
39
- allow(@collection).to receive(:iterator).and_return(@iterator)
40
- expect(@iterator).to receive(:pause)
41
- @provider.action_break
42
- expect(@resource).to be_updated
43
- end
44
-
45
- it "doesn't pause the iterator if chef-shell isn't running" do
46
- allow(Shell).to receive(:running?).and_return(false)
47
- @iterator = double("stepable_iterator")
48
- allow(@collection).to receive(:iterator).and_return(@iterator)
49
- expect(@iterator).not_to receive(:pause)
50
- @provider.action_break
51
- end
52
-
53
- end
@@ -1,110 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "rubygems"
4
- require "bundler"
5
-
6
- Bundler.with_clean_env do
7
- require_relative "../gemfile_util"
8
-
9
- options = {}
10
- opts = OptionParser.new do |opts|
11
- opts.banner = "Usage: create-override-gemfile [OPTIONS]"
12
-
13
- opts.on("--gemfile GEMFILE", "The Gemfile to read (default: Gemfile).") { |path| options[:gemfile_path] = path }
14
- opts.on("--lockfile GEMFILE", "The lockfile to read (default: <gemfile>.lock).") { |path| options[:lockfile_path] = path }
15
-
16
- opts.on("--group GROUP", "Groups to include (whitelist).") do |group|
17
- options[:groups] ||= []
18
- options[:groups] << group.to_sym
19
- end
20
-
21
- opts.on("--without GROUP", "Groups to exclude.") do |group|
22
- options[:without_groups] ||= []
23
- options[:without_groups] << group.to_sym
24
- end
25
-
26
- opts.on("--gem GEM", "Gems to include regardless of groups.") do |name|
27
- options[:gems] ||= []
28
- options[:gems] << name
29
- end
30
-
31
- opts.on("--relative-to PATH", "A path to prepend to any relative paths in the Gemfile.") do |path|
32
- unless Pathname.new(path).absolute?
33
- puts opts
34
- raise "--relative-to #{path} was not an absolute path!"
35
- end
36
- options[:relative_to] = path
37
- end
38
-
39
- opts.on("--[no-]copy-groups", "Whether to copy groups over from the original Gemfile or not (default: false).") { |val| options[:copy_groups] = val }
40
-
41
- opts.on("--[no-]override", "Whether to emit override: true on each gem line (default: false).") { |val| options[:override] = val }
42
-
43
- opts.on("-h", "--help", "Print this message.") do
44
- puts opts
45
- exit(0)
46
- end
47
- end
48
-
49
- args = opts.parse(ARGV)
50
-
51
- if args.size > 0
52
- puts opts
53
- raise "Invalid arguments #{args}"
54
- end
55
-
56
- def create_override_gemfile(gemfile_path: "Gemfile", lockfile_path: "#{gemfile_path}.lock", groups: nil, without_groups: nil, gems: [], copy_groups: false, relative_to: ".", override: false)
57
- relative_to = Pathname.new(relative_to).realpath
58
- # Select the gems we want
59
- bundle = GemfileUtil::Bundle.parse(gemfile_path, lockfile_path)
60
- gems_to_include = bundle.select_gems(groups: groups, without_groups: without_groups)
61
- gems.each do |name|
62
- raise "Requested gem #{name} is not in #{gemfile_path}.lock!" if !bundle.gems[name]
63
- gems_to_include[name] ||= bundle.gems[name]
64
- gems_to_include[name][:dependencies].each do |dep|
65
- gems_to_include[name] ||= bundle.gems[dep]
66
- end
67
- end
68
-
69
- # Add the gems to the Gemfile
70
- gem_root = Pathname.new(gemfile_path).dirname.realpath
71
- gems_to_include.sort_by { |name, options| options[:declared_groups].empty? ? 1 : 0 }.each do |name, options|
72
- comment = nil
73
- options = options.dup
74
- version = options.delete(:version)
75
- if copy_groups
76
- # Some dependencies have no groups (are not in the Gemfile--just runtime
77
- # dependencies). If we actually record that they have no groups, they
78
- # will *always* be installed (or perhaps never). We only want them to
79
- # install if their other deps do, so we mark them with the groups of the
80
- # things that brought them in (the gems that depended on them). To do
81
- # this, we just leave :groups intact.
82
- if options[:declared_groups].empty?
83
- options.delete(:declared_groups)
84
- comment = " # Transitive dependency, not actually in original Gemfile"
85
- else
86
- # For other things, we want to copy the actual declared_groups--the
87
- # ones that were in the Gemfile. We want the same --with and --without
88
- # options to include and exclude them as worked with the original
89
- # Gemfile.
90
- options[:groups] = options.delete(:declared_groups)
91
- end
92
- else
93
- options.delete(:groups)
94
- options.delete(:declared_groups)
95
- end
96
- options.delete(:dependencies)
97
- options.delete(:development_dependencies)
98
- options[:override] = true if override
99
- options[:path] = Pathname.new(options[:path]).expand_path(gem_root).relative_path_from(relative_to).to_s if options[:path]
100
- line = "gem #{name.inspect}, #{version.inspect}"
101
- options.each do |name, value|
102
- line << ", #{name}: #{value.inspect}"
103
- end
104
- line << comment if comment
105
- puts line
106
- end
107
- end
108
-
109
- create_override_gemfile(options)
110
- end
@@ -1,390 +0,0 @@
1
- require "rubygems"
2
- require "bundler"
3
- require "shellwords"
4
- require "set"
5
-
6
- module GemfileUtil
7
- #
8
- # Adds `override: true`, which allows your statement to override any other
9
- # gem statement about the same gem in the Gemfile.
10
- #
11
- def gem(name, *args)
12
- options = args[-1].is_a?(Hash) ? args[-1] : {}
13
-
14
- # Unless we're finished with everything, ignore gems that are being overridden
15
- unless overridden_gems == :finished
16
- # If it's a path or override gem, it overrides whatever else is there.
17
- if options[:path] || options[:override]
18
- options.delete(:override)
19
- warn_if_replacing(name, overridden_gems[name], args)
20
- overridden_gems[name] = args
21
- return
22
-
23
- # If there's an override gem, and we're *not* an override gem, don't do anything
24
- elsif overridden_gems[name]
25
- warn_if_replacing(name, args, overridden_gems[name])
26
- return
27
- end
28
- end
29
-
30
- # Otherwise, add the gem normally
31
- super
32
- rescue
33
- puts $!.backtrace
34
- raise
35
- end
36
-
37
- def overridden_gems
38
- @overridden_gems ||= {}
39
- end
40
-
41
- #
42
- # Just before we finish the Gemfile, finish up the override gems
43
- #
44
- def to_definition(*args)
45
- complete_overrides
46
- super
47
- end
48
-
49
- def complete_overrides
50
- to_override = overridden_gems
51
- unless to_override == :finished
52
- @overridden_gems = :finished
53
- to_override.each do |name, args|
54
- gem name, *args
55
- end
56
- end
57
- end
58
-
59
- #
60
- # Include all gems in the locked gemfile.
61
- #
62
- # @param gemfile_path Path to the Gemfile to load (relative to your Gemfile)
63
- # @param lockfile_path Path to the Gemfile to load (relative to your Gemfile).
64
- # Defaults to <gemfile_path>.lock.
65
- # @param groups A list of groups to include (whitelist). If not passed (or set
66
- # to nil), all gems will be selected.
67
- # @param without_groups A list of groups to ignore. Gems will be excluded from
68
- # the results if all groups they belong to are ignored. This matches
69
- # bundler's `without` behavior.
70
- # @param gems A list of gems to include above and beyond the given groups.
71
- # Gems in this list must be explicitly included in the Gemfile
72
- # with a `gem "gem_name", ...` line or they will be silently
73
- # ignored.
74
- # @param copy_groups Whether to copy the groups over from the old lockfile to
75
- # the new. Use this when the new lockfile has the same convention for
76
- # groups as the old. Defaults to `false`.
77
- #
78
- def include_locked_gemfile(gemfile_path, lockfile_path = "#{gemfile_path}.lock", groups: nil, without_groups: nil, gems: [], copy_groups: false)
79
- # Parse the desired lockfile
80
- gemfile_path = Pathname.new(gemfile_path).expand_path(Bundler.default_gemfile.dirname).realpath
81
- lockfile_path = Pathname.new(lockfile_path).expand_path(Bundler.default_gemfile.dirname).realpath
82
-
83
- # Calculate relative_to
84
- relative_to = Bundler.default_gemfile.dirname.realpath
85
-
86
- # Call out to create-override-gemfile to read the Gemfile+Gemfile.lock (bundler does not work well if you do two things in one process)
87
- create_override_gemfile_bin = File.expand_path("../bin/create-override-gemfile", __FILE__)
88
- arguments = [
89
- "--gemfile", gemfile_path,
90
- "--lockfile", lockfile_path,
91
- "--override"
92
- ]
93
- arguments += [ "--relative-to", relative_to ] if relative_to != "."
94
- arguments += Array(groups).flat_map { |group| [ "--group", group ] }
95
- arguments += Array(without_groups).flat_map { |without| [ "--without", without ] }
96
- arguments += Array(gems).flat_map { |name| [ "--gem", name ] }
97
- arguments << "--copy-groups" if copy_groups
98
- cmd = Shellwords.join([ Gem.ruby, "-S", create_override_gemfile_bin, *arguments ])
99
- output = nil
100
- Bundler.ui.info("> #{cmd}")
101
- Bundler.with_clean_env do
102
- output = `#{cmd}`
103
- end
104
- instance_eval(output, cmd, 1)
105
- end
106
-
107
- #
108
- # Include all gems in the locked gemfile.
109
- #
110
- # @param current_gemfile The Gemfile you are currently loading (`self`).
111
- # @param gemfile_path Path to the Gemfile to load (relative to your Gemfile)
112
- # @param lockfile_path Path to the Gemfile to load (relative to your Gemfile).
113
- # Defaults to <gemfile_path>.lock.
114
- # @param groups A list of groups to include (whitelist). If not passed (or set
115
- # to nil), all gems will be selected.
116
- # @param without_groups A list of groups to ignore. Gems will be excluded from
117
- # the results if all groups they belong to are ignored. This matches
118
- # bundler's `without` behavior.
119
- # @param gems A list of gems to include above and beyond the given groups.
120
- # Gems in this list must be explicitly included in the Gemfile
121
- # with a `gem "gem_name", ...` line or they will be silently
122
- # ignored.
123
- # @param copy_groups Whether to copy the groups over from the old lockfile to
124
- # the new. Use this when the new lockfile has the same convention for
125
- # groups as the old. Defaults to `false`.
126
- #
127
- def self.include_locked_gemfile(current_gemfile, gemfile_path, lockfile_path = "#{gemfile_path}.lock", groups: nil, without_groups: nil, gems: [], copy_groups: false)
128
- current_gemfile.instance_eval do
129
- extend GemfileUtil
130
- include_locked_gemfile(gemfile_path, lockfile_path, groups: groups, without_groups: without_groups, gems: gems, copy_groups: copy_groups)
131
- end
132
- end
133
-
134
- def warn_if_replacing(name, old_args, new_args)
135
- return if !old_args || !new_args
136
- if args_to_dep(name, *old_args) =~ args_to_dep(name, *new_args)
137
- Bundler.ui.debug "Replaced Gemfile dependency #{name} (#{old_args}) with (#{new_args})"
138
- else
139
- Bundler.ui.warn "Replaced Gemfile dependency #{name} (#{old_args}) with (#{new_args})"
140
- end
141
- end
142
-
143
- def args_to_dep(name, *version, **options)
144
- version = [">= 0"] if version.empty?
145
- Bundler::Dependency.new(name, version, options)
146
- end
147
-
148
- #
149
- # Reads a bundle, including a gemfile and lockfile.
150
- #
151
- # Does no validation, does not update the lockfile or its gems in any way.
152
- #
153
- class Bundle
154
- #
155
- # Parse the given gemfile/lockfile pair.
156
- #
157
- # @return [Bundle] The parsed bundle.
158
- #
159
- def self.parse(gemfile_path, lockfile_path = "#{gemfile_path}.lock")
160
- result = new(gemfile_path, lockfile_path)
161
- result.gems
162
- result
163
- end
164
-
165
- #
166
- # Create a new Bundle to parse the given gemfile/lockfile pair.
167
- #
168
- def initialize(gemfile_path, lockfile_path = "#{gemfile_path}.lock")
169
- @gemfile_path = gemfile_path
170
- @lockfile_path = lockfile_path
171
- end
172
-
173
- #
174
- # The path to the Gemfile
175
- #
176
- attr_reader :gemfile_path
177
-
178
- #
179
- # The path to the Lockfile
180
- #
181
- attr_reader :lockfile_path
182
-
183
- #
184
- # The list of gems.
185
- #
186
- # @return [Hash<String, Hash>] The resulting gems, where key = gem_name, and the
187
- # hash has:
188
- # - version: version of the gem.
189
- # - source info (:source/:git/:ref/:path) from the lockfile
190
- # - dependencies: A list of gem names this gem has a runtime
191
- # dependency on. Dependencies are transitive: if A depends on B,
192
- # and B depends on C, then A has C in its :dependencies list.
193
- # - development_dependencies: - A list of gem names this gem has a
194
- # development dependency on. Dependencies are transitive: if A
195
- # depends on B, and B depends on C, then A has C in its
196
- # :development_dependencies list. development dependencies *include*
197
- # runtime dependencies.
198
- # - groups: The list of groups (symbols) this gem is in. Groups
199
- # are transitive: if A has a runtime dependency on B, and A is
200
- # in group X, then B is also in group X.
201
- # - declared_groups: The list of groups (symbols) this gem was
202
- # declared in the Gemfile.
203
- #
204
- def gems
205
- @gems ||= begin
206
- gems = locks.dup
207
- gems.each do |name, g|
208
- if gem_declarations.has_key?(name)
209
- g[:declared_groups] = gem_declarations[name][:groups]
210
- else
211
- g[:declared_groups] = []
212
- end
213
- g[:groups] = g[:declared_groups].dup
214
- end
215
- # Transitivize groups (since dependencies are already transitive, this is easy)
216
- gems.each do |name, g|
217
- g[:dependencies].each do |dep|
218
- gems[dep][:groups] |= gems[name][:declared_groups].dup
219
- end
220
- end
221
- gems
222
- end
223
- end
224
-
225
- #
226
- # Get the gems (and their deps) in the given group.
227
- #
228
- # @param groups A list of groups to include (whitelist). If not passed (or set
229
- # to nil), all gems will be selected.
230
- # @param without_groups A list of groups to ignore. Gems will be excluded from
231
- # the results if all groups they belong to are ignored.
232
- # This matches bundler's `without` behavior.
233
- # @param gems A list of gems to include regardless of what groups are included.
234
- #
235
- # @return Hash[String, Hash] The resulting gems, where key = gem_name, and the
236
- # hash has:
237
- # - version: version of the gem.
238
- # - source info (:source/:git/:ref/:path) from the lockfile
239
- # - dependencies: A list of gem names this gem has a runtime
240
- # dependency on. Dependencies are transitive: if A depends on B,
241
- # and B depends on C, then A has C in its :dependencies list.
242
- # - development_dependencies: - A list of gem names this gem has a
243
- # development dependency on. Dependencies are transitive: if A
244
- # depends on B, and B depends on C, then A has C in its
245
- # :development_dependencies list. development dependencies
246
- # *include* runtime dependencies.
247
- # - groups: The list of groups (symbols) this gem is in. Groups
248
- # are transitive: if A has a runtime dependency on B, and A is
249
- # in group X, then B is also in group X.
250
- # - declared_groups: The list of groups (symbols) this gem was
251
- # declared in the Gemfile.
252
- #
253
- def select_gems(groups: nil, without_groups: nil)
254
- # First, select the gems that match
255
- result = {}
256
- gems.each do |name, g|
257
- dep_groups = g[:declared_groups] - [ :only_a_runtime_dependency_of_other_gems ]
258
- dep_groups &= groups if groups
259
- dep_groups -= without_groups if without_groups
260
- if dep_groups.any?
261
- result[name] ||= g
262
- g[:dependencies].each do |dep|
263
- result[dep] ||= gems[dep]
264
- end
265
- end
266
- end
267
- result
268
- end
269
-
270
- #
271
- # Get all locks from the given lockfile.
272
- #
273
- # @return Hash[String, Hash] The resulting gems, where key = gem_name, and the
274
- # hash has:
275
- # - version: version of the gem.
276
- # - source info (:source/:git/:ref/:path)
277
- # - dependencies: A list of gem names this gem has a runtime
278
- # dependency on. Dependencies are transitive: if A depends on B,
279
- # and B depends on C, then A has C in its :dependencies list.
280
- # - development_dependencies: - A list of gem names this gem has a
281
- # development dependency on. Dependencies are transitive: if A
282
- # depends on B, and B depends on C, then A has C in its
283
- # :development_dependencies list. development dependencies *include*
284
- # runtime dependencies.
285
- #
286
- def locks
287
- @locks ||= begin
288
- # Grab all the specs from the lockfile
289
- locks = {}
290
- parsed_lockfile = Bundler::LockfileParser.new(IO.read(lockfile_path))
291
- parsed_lockfile.specs.each do |spec|
292
- # Never include bundler, it can't be bundled and doesn't put itself in
293
- # the lockfile correctly anyway
294
- next if spec.name == "bundler"
295
- # Only the platform-specific locks for now (TODO make it possible to emit all locks)
296
- next if spec.platform && spec.platform != Gem::Platform::RUBY
297
- lock = lock_source_metadata(spec)
298
- lock[:version] = spec.version.to_s
299
- runtime = spec.dependencies.select { |dep| dep.type == :runtime }
300
- lock[:dependencies] = Set.new(runtime.map { |dep| dep.name })
301
- lock[:development_dependencies] = Set.new(spec.dependencies.map { |dep| dep.name })
302
- lock[:dependencies].delete("bundler")
303
- lock[:development_dependencies].delete("bundler")
304
- locks[spec.name] = lock
305
- end
306
-
307
- # Transitivize the deps.
308
- locks.each do |name, lock|
309
- # Not all deps were brought over (platform-specific ones) so weed them out
310
- lock[:dependencies] &= locks.keys
311
- lock[:development_dependencies] &= locks.keys
312
-
313
- lock[:dependencies] = transitive_dependencies(locks, name, :dependencies)
314
- lock[:development_dependencies] = transitive_dependencies(locks, name, :development_dependencies)
315
- end
316
-
317
- locks
318
- end
319
- end
320
-
321
- #
322
- # Get all desired gems, sans dependencies, from the gemfile.
323
- #
324
- # @param gemfile Path to the Gemfile to load
325
- #
326
- # @return Hash<String, Hash> An array of hashes where key = gem name and value
327
- # has :groups (an array of symbols representing the groups the gem
328
- # is in). :groups are not transitive, since we don't know the
329
- # dependency tree yet.
330
- #
331
- def gem_declarations
332
- @gem_declarations ||= begin
333
- Bundler.with_clean_env do
334
- # Set BUNDLE_GEMFILE to the new gemfile temporarily so all bundler's things work
335
- # This works around some issues in bundler 1.11.2.
336
- ENV["BUNDLE_GEMFILE"] = gemfile_path
337
-
338
- parsed_gemfile = Bundler::Dsl.new
339
- parsed_gemfile.eval_gemfile(gemfile_path)
340
- parsed_gemfile.complete_overrides if parsed_gemfile.respond_to?(:complete_overrides)
341
-
342
- result = {}
343
- parsed_gemfile.dependencies.each do |dep|
344
- groups = dep.groups.empty? ? [:default] : dep.groups
345
- result[dep.name] = { groups: groups, platforms: dep.platforms }
346
- end
347
- result
348
- end
349
- end
350
- end
351
-
352
- private
353
-
354
- #
355
- # Given a bunch of locks (name -> { dependencies: [name,name] }) and a
356
- # dependency name, add its dependencies to the result transitively.
357
- #
358
- def transitive_dependencies(locks, name, dep_key, result = Set.new)
359
- locks[name][dep_key].each do |dep|
360
- # Only ever add a dep once, so we don't infinitely recurse
361
- if result.add?(dep)
362
- transitive_dependencies(locks, dep, dep_key, result)
363
- end
364
- end
365
- result
366
- end
367
-
368
- #
369
- # Get source and version metadata for the given Bundler spec (coming from a lockfile).
370
- #
371
- # @return Hash { version: <version>, git: <git>, path: <path>, source: <source>, ref: <ref> }
372
- #
373
- def lock_source_metadata(spec)
374
- # Copy source information from included Gemfile
375
- result = {}
376
- case spec.source
377
- when Bundler::Source::Rubygems
378
- result[:source] = spec.source.remotes.first.to_s
379
- when Bundler::Source::Git
380
- result[:git] = spec.source.uri.to_s
381
- result[:ref] = spec.source.revision
382
- when Bundler::Source::Path
383
- result[:path] = spec.source.path.to_s
384
- else
385
- raise "Unknown source #{spec.source} for gem #{spec.name}"
386
- end
387
- result
388
- end
389
- end
390
- end