chef-dk 1.6.11 → 2.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +25 -38
  3. data/Gemfile.lock +199 -199
  4. data/README.md +4 -2
  5. data/Rakefile +1 -2
  6. data/acceptance/Gemfile +1 -1
  7. data/acceptance/Gemfile.lock +23 -21
  8. data/chef-dk.gemspec +4 -6
  9. data/lib/chef-dk/builtin_commands.rb +1 -1
  10. data/lib/chef-dk/chef_runner.rb +1 -1
  11. data/lib/chef-dk/cli.rb +1 -0
  12. data/lib/chef-dk/command/generate.rb +5 -2
  13. data/lib/chef-dk/command/generator_commands/helpers.rb +36 -0
  14. data/lib/chef-dk/command/generator_commands/{lwrp.rb → resource.rb} +4 -4
  15. data/lib/chef-dk/command/update.rb +11 -18
  16. data/lib/chef-dk/command/verify.rb +1 -16
  17. data/lib/chef-dk/commands_map.rb +3 -3
  18. data/lib/chef-dk/policyfile/artifactory_cookbook_source.rb +102 -0
  19. data/lib/chef-dk/policyfile/cookbook_location_specification.rb +2 -2
  20. data/lib/chef-dk/policyfile/cookbook_sources.rb +1 -0
  21. data/lib/chef-dk/policyfile/dsl.rb +10 -0
  22. data/lib/chef-dk/policyfile/solution_dependencies.rb +15 -1
  23. data/lib/chef-dk/policyfile_lock.rb +1 -1
  24. data/lib/chef-dk/policyfile_services/install.rb +30 -2
  25. data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +1 -0
  26. data/lib/chef-dk/skeletons/code_generator/files/default/build_cookbook/test-fixture-recipe.rb +1 -0
  27. data/lib/chef-dk/skeletons/code_generator/files/default/cookbook_readmes/README.md +2 -2
  28. data/lib/chef-dk/skeletons/code_generator/files/default/delivery-config.json +3 -0
  29. data/lib/chef-dk/skeletons/code_generator/files/default/delivery-project.toml +1 -1
  30. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +1 -0
  31. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +2 -1
  32. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +1 -0
  33. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper.rb +1 -0
  34. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper_policyfile.rb +1 -0
  35. data/lib/chef-dk/skeletons/code_generator/metadata.rb +3 -2
  36. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +1 -1
  37. data/lib/chef-dk/skeletons/code_generator/recipes/attribute.rb +1 -0
  38. data/lib/chef-dk/skeletons/code_generator/recipes/build_cookbook.rb +7 -12
  39. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +1 -0
  40. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook_file.rb +1 -0
  41. data/lib/chef-dk/skeletons/code_generator/recipes/helpers.rb +21 -0
  42. data/lib/chef-dk/skeletons/code_generator/recipes/policyfile.rb +1 -0
  43. data/lib/chef-dk/skeletons/code_generator/recipes/recipe.rb +1 -0
  44. data/lib/chef-dk/skeletons/code_generator/recipes/repo.rb +1 -0
  45. data/lib/chef-dk/skeletons/code_generator/recipes/{lwrp.rb → resource.rb} +1 -11
  46. data/lib/chef-dk/skeletons/code_generator/recipes/template.rb +3 -3
  47. data/lib/chef-dk/skeletons/code_generator/templates/default/helpers.rb.erb +39 -0
  48. data/lib/chef-dk/skeletons/code_generator/templates/default/metadata.rb.erb +1 -1
  49. data/lib/chef-dk/skeletons/code_generator/templates/default/resource.rb.erb +1 -0
  50. data/lib/chef-dk/version.rb +2 -2
  51. data/omnibus_overrides.rb +14 -12
  52. data/spec/unit/command/generator_commands/cookbook_spec.rb +7 -1
  53. data/spec/unit/command/generator_commands/helpers_spec.rb +31 -0
  54. data/spec/unit/command/generator_commands/{lwrp_spec.rb → resource_spec.rb} +5 -5
  55. data/spec/unit/command/install_spec.rb +2 -2
  56. data/spec/unit/command/update_spec.rb +11 -3
  57. data/spec/unit/command/verify_spec.rb +2 -1
  58. data/spec/unit/policyfile/artifactory_cookbook_source_spec.rb +59 -0
  59. data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +1 -1
  60. data/spec/unit/policyfile/solution_dependencies_spec.rb +25 -0
  61. data/spec/unit/policyfile_demands_spec.rb +2 -1
  62. data/spec/unit/policyfile_lock_build_spec.rb +23 -21
  63. data/spec/unit/policyfile_lock_install_spec.rb +2 -2
  64. data/spec/unit/policyfile_lock_validation_spec.rb +3 -3
  65. data/spec/unit/policyfile_services/export_repo_spec.rb +6 -6
  66. data/spec/unit/policyfile_services/install_spec.rb +1 -1
  67. data/spec/unit/policyfile_services/update_spec.rb +143 -0
  68. data/tasks/announce.rb +3 -2
  69. data/tasks/dependencies.rb +35 -111
  70. data/tasks/github_changelog_generator.rb +0 -3
  71. data/tasks/templates/prerelease.md.erb +1 -1
  72. data/tasks/templates/release.md.erb +1 -1
  73. metadata +20 -38
  74. data/lib/chef-dk/skeletons/code_generator/templates/default/provider.rb.erb +0 -0
  75. data/spec/unit/gemfile_util_spec.rb +0 -41
  76. data/spec/unit/helpers_spec.rb +0 -120
  77. data/spec/unit/tasks/helpers_spec.rb +0 -75
  78. data/tasks/bin/bundle-platform +0 -19
  79. data/tasks/bin/create-override-gemfile +0 -110
  80. data/tasks/bundle.rb +0 -96
  81. data/tasks/bundle_util.rb +0 -110
  82. data/tasks/gemfile_util.rb +0 -435
  83. data/tasks/helpers.rb +0 -47
  84. data/version_policy.rb +0 -142
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- platforms = ARGV.shift
4
- platforms = platforms.split(" ").map { |p| Gem::Platform.new(p) }
5
- Gem::Platform.instance_eval { @local = platforms.last }
6
- old_platforms = Gem.platforms
7
- Gem.platforms = platforms
8
- puts "bundle-platform set Gem.platforms to #{Gem.platforms.map { |p| p.to_s }} (was #{old_platforms.map { |p| p.to_s } })"
9
-
10
- desired_version = ARGV.shift.delete("_")
11
-
12
- # The rest of this is a normal bundler binstub
13
- require "pathname"
14
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile",
15
- Pathname.new(__FILE__).realpath)
16
-
17
- require "rubygems"
18
-
19
- load Gem.bin_path("bundler", "bundle", desired_version)
@@ -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,96 +0,0 @@
1
- #
2
- # Copyright:: Copyright (c) 2016 Chef Software Inc.
3
- # License:: Apache License, Version 2.0
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
- #
17
-
18
- require_relative "bundle_util"
19
- require_relative "../version_policy"
20
- require "fileutils"
21
-
22
- desc "Tasks to work with the main Gemfile and Gemfile.<platform>"
23
- namespace :bundle do
24
- desc "Update Gemfile.lock and all Gemfile.<platform>.locks (or one or more gems via bundle:update gem1 gem2 ...)."
25
- task :update, [:args] do |t, rake_args|
26
- extend BundleUtil
27
- args = rake_args[:args] || ""
28
- with_bundle_unfrozen do
29
- puts ""
30
- puts "-------------------------------------------------------------------"
31
- puts "Updating Gemfile.lock ..."
32
- puts "-------------------------------------------------------------------"
33
- bundle "update #{args}"
34
- platforms.each do |platform|
35
- bundle "update #{args}", platform: platform
36
- end
37
- end
38
- end
39
-
40
- desc "Conservatively update Gemfile.lock and all Gemfile.<platform>.locks"
41
- task :install, [:args] do |t, rake_args|
42
- extend BundleUtil
43
- args = rake_args[:args] || ""
44
- with_bundle_unfrozen do
45
- puts ""
46
- puts "-------------------------------------------------------------------"
47
- puts "Updating Gemfile.lock ..."
48
- puts "-------------------------------------------------------------------"
49
- bundle "install #{args}"
50
- platforms.each do |platform|
51
- bundle "lock", platform: platform
52
- end
53
- end
54
- end
55
-
56
- # Find out if we're using the latest gems we can (so we don't regress versions)
57
- desc "Check for gems that are not at the latest released version, and report if anything not in ACCEPTABLE_OUTDATED_GEMS (version_policy.rb) is out of date."
58
- task :outdated do
59
- extend BundleUtil
60
- puts ""
61
- puts "-------------------------------------------------------------------"
62
- puts "Checking for outdated gems ..."
63
- puts "-------------------------------------------------------------------"
64
- with_bundle_unfrozen do
65
- bundle_outdated = bundle("outdated", extract_output: true)
66
- puts bundle_outdated
67
- outdated_gems = parse_bundle_outdated(bundle_outdated).map { |line, gem_name| gem_name }
68
- # Weed out the acceptable ones
69
- outdated_gems = outdated_gems.reject { |gem_name| ACCEPTABLE_OUTDATED_GEMS.include?(gem_name) }
70
- if outdated_gems.empty?
71
- puts ""
72
- puts "SUCCESS!"
73
- else
74
- raise "ERROR: outdated gems: #{outdated_gems.join(", ")}. Either fix them or add them to ACCEPTABLE_OUTDATED_GEMS in #{__FILE__}."
75
- end
76
- end
77
- end
78
- end
79
-
80
- desc "Run bundle with arbitrary args against the given platform; e.g. rake bundle[show]. No platform to run against the main bundle; bundle[show,windows] to run the windows one; bundle[show,*] to run against all non-default platforms."
81
- task :bundle, [:args, :platform] do |t, rake_args|
82
- extend BundleUtil
83
- args = rake_args[:args] || ""
84
- platform = rake_args[:platform]
85
- with_bundle_unfrozen do
86
- if platform == "*"
87
- platforms.each do |platform|
88
- bundle args, platform: platform
89
- end
90
- elsif platform
91
- bundle args, platform: platform
92
- else
93
- bundle args
94
- end
95
- end
96
- end
@@ -1,110 +0,0 @@
1
- require "bundler"
2
- require "shellwords"
3
-
4
- module BundleUtil
5
- PLATFORMS = { "windows" => %w{ruby x86-mingw32} }
6
-
7
- def project_root
8
- File.expand_path("../..", __FILE__)
9
- end
10
-
11
- def bundle_platform
12
- File.join(project_root, "tasks", "bin", "bundle-platform")
13
- end
14
-
15
- # Parse the output of "bundle outdated" and get the list of gems that
16
- # were outdated
17
- def parse_bundle_outdated(bundle_outdated_output)
18
- result = []
19
- bundle_outdated_output.each_line do |line|
20
- if line =~ /^\s*\* (.+) \(newest ([^,]+), installed ([^,)])*/
21
- gem_name, newest_version, installed_version = $1, $2, $3
22
- result << [ line, gem_name ]
23
- end
24
- end
25
- result
26
- end
27
-
28
- def with_bundle_unfrozen(cwd: nil, leave_frozen: false)
29
- bundle "config --delete frozen", cwd: cwd
30
- begin
31
- yield
32
- ensure
33
- bundle "config --local frozen 1", cwd: cwd unless leave_frozen
34
- end
35
- end
36
-
37
- # Run bundle-platform with the given ruby platform(s)
38
- def bundle(args, gemfile: nil, platform: nil, cwd: nil, extract_output: false, delete_gemfile_lock: false)
39
- args = args.split(/\s+/)
40
- if cwd
41
- prefix = "[#{cwd}] "
42
- end
43
- cwd = File.expand_path(cwd || ".", project_root)
44
- Bundler.with_clean_env do
45
- Dir.chdir(cwd) do
46
- gemfile ||= "Gemfile"
47
- gemfile = File.expand_path(gemfile, cwd)
48
- raise "No platform #{platform} (supported: #{PLATFORMS.keys.join(", ")})" if platform && !PLATFORMS[platform]
49
-
50
- # First delete the gemfile.lock
51
- if delete_gemfile_lock
52
- if File.exist?("#{gemfile}.lock")
53
- puts "Deleting #{gemfile}.lock ..."
54
- File.delete("#{gemfile}.lock")
55
- end
56
- end
57
-
58
- # Run the bundle command
59
- ruby_platforms = platform ? PLATFORMS[platform].join(" ") : "ruby"
60
- cmd = Shellwords.join([
61
- Gem.ruby,
62
- "-S",
63
- bundle_platform,
64
- ruby_platforms,
65
- "_#{desired_bundler_version}_",
66
- *args,
67
- ])
68
- puts "#{prefix}#{Shellwords.join(["bundle", *args])}#{platform ? " for #{platform} platform" : ""}:"
69
- with_gemfile(gemfile) do
70
- puts "#{prefix}BUNDLE_GEMFILE=#{gemfile}"
71
- puts "#{prefix}> #{cmd}"
72
- if extract_output
73
- `#{cmd}`
74
- else
75
- unless system(bundle_platform, ruby_platforms, "_#{desired_bundler_version}_", *args)
76
- raise "#{bundle_platform} failed: exit code #{$?}"
77
- end
78
- end
79
- end
80
- end
81
- end
82
- end
83
-
84
- def with_gemfile(gemfile)
85
- old_gemfile = ENV["BUNDLE_GEMFILE"]
86
- ENV["BUNDLE_GEMFILE"] = gemfile
87
- begin
88
- yield
89
- ensure
90
- if old_gemfile
91
- ENV["BUNDLE_GEMFILE"] = old_gemfile
92
- else
93
- ENV.delete("BUNDLE_GEMFILE")
94
- end
95
- end
96
- end
97
-
98
- def platforms
99
- PLATFORMS.keys
100
- end
101
-
102
- def desired_bundler_version
103
- @desired_bundler_version ||= begin
104
- omnibus_overrides = File.join(project_root, "omnibus_overrides.rb")
105
- File.readlines(omnibus_overrides).each do |line|
106
- return $1 if line =~ /^override :bundler, version: "(.+)"$/
107
- end
108
- end
109
- end
110
- end
@@ -1,435 +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
- # :path does likewise.
12
- #
13
- # :overrideable holds off on processing the
14
- #
15
- def gemfile_parsing_done?
16
- overridden_gems == :finished
17
- end
18
-
19
- def overridey_thing?(options)
20
- options[:path] || options[:override] || options[:overrideable]
21
- end
22
-
23
- def gem(name, *args)
24
- options = args[-1].is_a?(Hash) ? args[-1] : {}
25
-
26
- # Unless we're finished with everything, ignore gems that are being overridden
27
- if gemfile_parsing_done?
28
- # Otherwise, add the gem normally
29
- super
30
- elsif overridey_thing?(options)
31
- # If it's a path or override gem, it overrides whatever else is there.
32
- if options[:path] || options[:override]
33
- options.delete(:override)
34
- warn_if_replacing(name, overridden_gems[name], args)
35
- overridden_gems[name] = args
36
-
37
- # if this can be overridden by a later `gem` line, don't do anything but save it for later.
38
- elsif options[:overrideable]
39
- # if you put a `gem` line before ours (which you're supposed to), let it be.
40
- unless seen_gems[name]
41
- options.delete(:overrideable)
42
- overrideable_gems[name] = args
43
- end
44
- end
45
-
46
- # This is a normal `gem` call. Check if it's overridden by something else.
47
- else
48
- # If there's an override gem, and we're *not* an override gem, don't do anything
49
- if overridden_gems[name]
50
- warn_if_replacing(name, args, overridden_gems[name])
51
-
52
- # ok, we found a `gem` definition to override it, so do that.
53
- else
54
- overrideable_gems.delete(name)
55
- super
56
- end
57
- end
58
-
59
- seen_gems[name] = true
60
-
61
- rescue
62
- puts $!.backtrace
63
- raise
64
- end
65
-
66
- def overridden_gems
67
- @overridden_gems ||= {}
68
- end
69
-
70
- def overrideable_gems
71
- @overrideable_gems ||= {}
72
- end
73
-
74
- def seen_gems
75
- @seen_gems ||= {}
76
- end
77
-
78
- #
79
- # Just before we finish the Gemfile, finish up the overridden and overrideable gems
80
- #
81
- def to_definition(*args)
82
- complete_overrides
83
- complete_overrideables
84
- super
85
- end
86
-
87
- def complete_overrides
88
- to_override = overridden_gems
89
- unless to_override == :finished
90
- @overridden_gems = :finished
91
- to_override.each do |name, args|
92
- gem name, *args
93
- end
94
- end
95
- end
96
-
97
- def complete_overrideables
98
- # we're mostly done, we just have to process the overrideable gems that didn't get overridden.
99
- overrideable_gems.each do |name, args|
100
- gem name, *args
101
- end
102
- end
103
-
104
- #
105
- # Include all gems in the locked gemfile.
106
- #
107
- # @param gemfile_path Path to the Gemfile to load (relative to your Gemfile)
108
- # @param lockfile_path Path to the Gemfile to load (relative to your Gemfile).
109
- # Defaults to <gemfile_path>.lock.
110
- # @param groups A list of groups to include (whitelist). If not passed (or set
111
- # to nil), all gems will be selected.
112
- # @param without_groups A list of groups to ignore. Gems will be excluded from
113
- # the results if all groups they belong to are ignored. This matches
114
- # bundler's `without` behavior.
115
- # @param gems A list of gems to include above and beyond the given groups.
116
- # Gems in this list must be explicitly included in the Gemfile
117
- # with a `gem "gem_name", ...` line or they will be silently
118
- # ignored.
119
- # @param copy_groups Whether to copy the groups over from the old lockfile to
120
- # the new. Use this when the new lockfile has the same convention for
121
- # groups as the old. Defaults to `false`.
122
- #
123
- def include_locked_gemfile(gemfile_path, lockfile_path = "#{gemfile_path}.lock", groups: nil, without_groups: nil, gems: [], copy_groups: false)
124
- # Parse the desired lockfile
125
- gemfile_path = Pathname.new(gemfile_path).expand_path(Bundler.default_gemfile.dirname).realpath
126
- lockfile_path = Pathname.new(lockfile_path).expand_path(Bundler.default_gemfile.dirname).realpath
127
-
128
- # Calculate relative_to
129
- relative_to = Bundler.default_gemfile.dirname.realpath
130
-
131
- # 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)
132
- create_override_gemfile_bin = File.expand_path("../bin/create-override-gemfile", __FILE__)
133
- arguments = [
134
- "--gemfile", gemfile_path,
135
- "--lockfile", lockfile_path,
136
- "--override"
137
- ]
138
- arguments += [ "--relative-to", relative_to ] if relative_to != "."
139
- arguments += Array(groups).flat_map { |group| [ "--group", group ] }
140
- arguments += Array(without_groups).flat_map { |without| [ "--without", without ] }
141
- arguments += Array(gems).flat_map { |name| [ "--gem", name ] }
142
- arguments << "--copy-groups" if copy_groups
143
- cmd = Shellwords.join([ Gem.ruby, "-S", create_override_gemfile_bin, *arguments ])
144
- output = nil
145
- Bundler.ui.info("> #{cmd}")
146
- Bundler.with_clean_env do
147
- output = `#{cmd}`
148
- end
149
- instance_eval(output, cmd, 1)
150
- end
151
-
152
- #
153
- # Include all gems in the locked gemfile.
154
- #
155
- # @param current_gemfile The Gemfile you are currently loading (`self`).
156
- # @param gemfile_path Path to the Gemfile to load (relative to your Gemfile)
157
- # @param lockfile_path Path to the Gemfile to load (relative to your Gemfile).
158
- # Defaults to <gemfile_path>.lock.
159
- # @param groups A list of groups to include (whitelist). If not passed (or set
160
- # to nil), all gems will be selected.
161
- # @param without_groups A list of groups to ignore. Gems will be excluded from
162
- # the results if all groups they belong to are ignored. This matches
163
- # bundler's `without` behavior.
164
- # @param gems A list of gems to include above and beyond the given groups.
165
- # Gems in this list must be explicitly included in the Gemfile
166
- # with a `gem "gem_name", ...` line or they will be silently
167
- # ignored.
168
- # @param copy_groups Whether to copy the groups over from the old lockfile to
169
- # the new. Use this when the new lockfile has the same convention for
170
- # groups as the old. Defaults to `false`.
171
- #
172
- def self.include_locked_gemfile(current_gemfile, gemfile_path, lockfile_path = "#{gemfile_path}.lock", groups: nil, without_groups: nil, gems: [], copy_groups: false)
173
- current_gemfile.instance_eval do
174
- extend GemfileUtil
175
- include_locked_gemfile(gemfile_path, lockfile_path, groups: groups, without_groups: without_groups, gems: gems, copy_groups: copy_groups)
176
- end
177
- end
178
-
179
- def warn_if_replacing(name, old_args, new_args)
180
- return if !old_args || !new_args
181
- if args_to_dep(name, *old_args) =~ args_to_dep(name, *new_args)
182
- Bundler.ui.debug "Replaced Gemfile dependency #{name} (#{old_args}) with (#{new_args})"
183
- else
184
- Bundler.ui.warn "Replaced Gemfile dependency #{name} (#{old_args}) with (#{new_args})"
185
- end
186
- end
187
-
188
- def args_to_dep(name, *version, **options)
189
- version = [">= 0"] if version.empty?
190
- Bundler::Dependency.new(name, version, options)
191
- end
192
-
193
- #
194
- # Reads a bundle, including a gemfile and lockfile.
195
- #
196
- # Does no validation, does not update the lockfile or its gems in any way.
197
- #
198
- class Bundle
199
- #
200
- # Parse the given gemfile/lockfile pair.
201
- #
202
- # @return [Bundle] The parsed bundle.
203
- #
204
- def self.parse(gemfile_path, lockfile_path = "#{gemfile_path}.lock")
205
- result = new(gemfile_path, lockfile_path)
206
- result.gems
207
- result
208
- end
209
-
210
- #
211
- # Create a new Bundle to parse the given gemfile/lockfile pair.
212
- #
213
- def initialize(gemfile_path, lockfile_path = "#{gemfile_path}.lock")
214
- @gemfile_path = gemfile_path
215
- @lockfile_path = lockfile_path
216
- end
217
-
218
- #
219
- # The path to the Gemfile
220
- #
221
- attr_reader :gemfile_path
222
-
223
- #
224
- # The path to the Lockfile
225
- #
226
- attr_reader :lockfile_path
227
-
228
- #
229
- # The list of gems.
230
- #
231
- # @return [Hash<String, Hash>] The resulting gems, where key = gem_name, and the
232
- # hash has:
233
- # - version: version of the gem.
234
- # - source info (:source/:git/:ref/:path) from the lockfile
235
- # - dependencies: A list of gem names this gem has a runtime
236
- # dependency on. Dependencies are transitive: if A depends on B,
237
- # and B depends on C, then A has C in its :dependencies list.
238
- # - development_dependencies: - A list of gem names this gem has a
239
- # development dependency on. Dependencies are transitive: if A
240
- # depends on B, and B depends on C, then A has C in its
241
- # :development_dependencies list. development dependencies *include*
242
- # runtime dependencies.
243
- # - groups: The list of groups (symbols) this gem is in. Groups
244
- # are transitive: if A has a runtime dependency on B, and A is
245
- # in group X, then B is also in group X.
246
- # - declared_groups: The list of groups (symbols) this gem was
247
- # declared in the Gemfile.
248
- #
249
- def gems
250
- @gems ||= begin
251
- gems = locks.dup
252
- gems.each do |name, g|
253
- if gem_declarations.has_key?(name)
254
- g[:declared_groups] = gem_declarations[name][:groups]
255
- else
256
- g[:declared_groups] = []
257
- end
258
- g[:groups] = g[:declared_groups].dup
259
- end
260
- # Transitivize groups (since dependencies are already transitive, this is easy)
261
- gems.each do |name, g|
262
- g[:dependencies].each do |dep|
263
- gems[dep][:groups] |= gems[name][:declared_groups].dup
264
- end
265
- end
266
- gems
267
- end
268
- end
269
-
270
- #
271
- # Get the gems (and their deps) in the given group.
272
- #
273
- # @param groups A list of groups to include (whitelist). If not passed (or set
274
- # to nil), all gems will be selected.
275
- # @param without_groups A list of groups to ignore. Gems will be excluded from
276
- # the results if all groups they belong to are ignored.
277
- # This matches bundler's `without` behavior.
278
- # @param gems A list of gems to include regardless of what groups are included.
279
- #
280
- # @return Hash[String, Hash] The resulting gems, where key = gem_name, and the
281
- # hash has:
282
- # - version: version of the gem.
283
- # - source info (:source/:git/:ref/:path) from the lockfile
284
- # - dependencies: A list of gem names this gem has a runtime
285
- # dependency on. Dependencies are transitive: if A depends on B,
286
- # and B depends on C, then A has C in its :dependencies list.
287
- # - development_dependencies: - A list of gem names this gem has a
288
- # development dependency on. Dependencies are transitive: if A
289
- # depends on B, and B depends on C, then A has C in its
290
- # :development_dependencies list. development dependencies
291
- # *include* runtime dependencies.
292
- # - groups: The list of groups (symbols) this gem is in. Groups
293
- # are transitive: if A has a runtime dependency on B, and A is
294
- # in group X, then B is also in group X.
295
- # - declared_groups: The list of groups (symbols) this gem was
296
- # declared in the Gemfile.
297
- #
298
- def select_gems(groups: nil, without_groups: nil)
299
- # First, select the gems that match
300
- result = {}
301
- gems.each do |name, g|
302
- dep_groups = g[:declared_groups] - [ :only_a_runtime_dependency_of_other_gems ]
303
- dep_groups = dep_groups & groups if groups
304
- dep_groups = dep_groups - without_groups if without_groups
305
- if dep_groups.any?
306
- result[name] ||= g
307
- g[:dependencies].each do |dep|
308
- result[dep] ||= gems[dep]
309
- end
310
- end
311
- end
312
- result
313
- end
314
-
315
- #
316
- # Get all locks from the given lockfile.
317
- #
318
- # @return Hash[String, Hash] The resulting gems, where key = gem_name, and the
319
- # hash has:
320
- # - version: version of the gem.
321
- # - source info (:source/:git/:ref/:path)
322
- # - dependencies: A list of gem names this gem has a runtime
323
- # dependency on. Dependencies are transitive: if A depends on B,
324
- # and B depends on C, then A has C in its :dependencies list.
325
- # - development_dependencies: - A list of gem names this gem has a
326
- # development dependency on. Dependencies are transitive: if A
327
- # depends on B, and B depends on C, then A has C in its
328
- # :development_dependencies list. development dependencies *include*
329
- # runtime dependencies.
330
- #
331
- def locks
332
- @locks ||= begin
333
- # Grab all the specs from the lockfile
334
- locks = {}
335
- parsed_lockfile = Bundler::LockfileParser.new(IO.read(lockfile_path))
336
- parsed_lockfile.specs.each do |spec|
337
- # Never include bundler, it can't be bundled and doesn't put itself in
338
- # the lockfile correctly anyway
339
- next if spec.name == "bundler"
340
- # Only the platform-specific locks for now (TODO make it possible to emit all locks)
341
- next if spec.platform && spec.platform != Gem::Platform::RUBY
342
- lock = lock_source_metadata(spec)
343
- lock[:version] = spec.version.to_s
344
- runtime = spec.dependencies.select { |dep| dep.type == :runtime }
345
- lock[:dependencies] = Set.new(runtime.map { |dep| dep.name })
346
- lock[:development_dependencies] = Set.new(spec.dependencies.map { |dep| dep.name })
347
- lock[:dependencies].delete("bundler")
348
- lock[:development_dependencies].delete("bundler")
349
- locks[spec.name] = lock
350
- end
351
-
352
- # Transitivize the deps.
353
- locks.each do |name, lock|
354
- # Not all deps were brought over (platform-specific ones) so weed them out
355
- lock[:dependencies] &= locks.keys
356
- lock[:development_dependencies] &= locks.keys
357
-
358
- lock[:dependencies] = transitive_dependencies(locks, name, :dependencies)
359
- lock[:development_dependencies] = transitive_dependencies(locks, name, :development_dependencies)
360
- end
361
-
362
- locks
363
- end
364
- end
365
-
366
- #
367
- # Get all desired gems, sans dependencies, from the gemfile.
368
- #
369
- # @param gemfile Path to the Gemfile to load
370
- #
371
- # @return Hash<String, Hash> An array of hashes where key = gem name and value
372
- # has :groups (an array of symbols representing the groups the gem
373
- # is in). :groups are not transitive, since we don't know the
374
- # dependency tree yet.
375
- #
376
- def gem_declarations
377
- @gem_declarations ||= begin
378
- Bundler.with_clean_env do
379
- # Set BUNDLE_GEMFILE to the new gemfile temporarily so all bundler's things work
380
- # This works around some issues in bundler 1.11.2.
381
- ENV["BUNDLE_GEMFILE"] = gemfile_path
382
-
383
- parsed_gemfile = Bundler::Dsl.new
384
- parsed_gemfile.eval_gemfile(gemfile_path)
385
- parsed_gemfile.complete_overrides if parsed_gemfile.respond_to?(:complete_overrides)
386
-
387
- result = {}
388
- parsed_gemfile.dependencies.each do |dep|
389
- groups = dep.groups.empty? ? [:default] : dep.groups
390
- result[dep.name] = { groups: groups, platforms: dep.platforms }
391
- end
392
- result
393
- end
394
- end
395
- end
396
-
397
- private
398
-
399
- #
400
- # Given a bunch of locks (name -> { dependencies: [name,name] }) and a
401
- # dependency name, add its dependencies to the result transitively.
402
- #
403
- def transitive_dependencies(locks, name, dep_key, result = Set.new)
404
- locks[name][dep_key].each do |dep|
405
- # Only ever add a dep once, so we don't infinitely recurse
406
- if result.add?(dep)
407
- transitive_dependencies(locks, dep, dep_key, result)
408
- end
409
- end
410
- result
411
- end
412
-
413
- #
414
- # Get source and version metadata for the given Bundler spec (coming from a lockfile).
415
- #
416
- # @return Hash { version: <version>, git: <git>, path: <path>, source: <source>, ref: <ref> }
417
- #
418
- def lock_source_metadata(spec)
419
- # Copy source information from included Gemfile
420
- result = {}
421
- case spec.source
422
- when Bundler::Source::Rubygems
423
- result[:source] = spec.source.remotes.first.to_s
424
- when Bundler::Source::Git
425
- result[:git] = spec.source.uri.to_s
426
- result[:ref] = spec.source.revision
427
- when Bundler::Source::Path
428
- result[:path] = spec.source.path.to_s
429
- else
430
- raise "Unknown source #{spec.source} for gem #{spec.name}"
431
- end
432
- result
433
- end
434
- end
435
- end