chef-dk 1.6.11 → 2.0.26

Sign up to get free protection for your applications and to get access to all the features.
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