bundler 1.16.1 → 1.17.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (143) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +195 -0
  3. data/README.md +5 -1
  4. data/bundler.gemspec +9 -2
  5. data/lib/bundler/build_metadata.rb +19 -4
  6. data/lib/bundler/cli/add.rb +15 -5
  7. data/lib/bundler/cli/binstubs.rb +8 -2
  8. data/lib/bundler/cli/check.rb +1 -1
  9. data/lib/bundler/cli/doctor.rb +47 -1
  10. data/lib/bundler/cli/exec.rb +4 -4
  11. data/lib/bundler/cli/gem.rb +5 -2
  12. data/lib/bundler/cli/init.rb +5 -0
  13. data/lib/bundler/cli/install.rb +10 -7
  14. data/lib/bundler/cli/list.rb +41 -5
  15. data/lib/bundler/cli/outdated.rb +8 -2
  16. data/lib/bundler/cli/pristine.rb +4 -0
  17. data/lib/bundler/cli/remove.rb +18 -0
  18. data/lib/bundler/cli/update.rb +3 -3
  19. data/lib/bundler/cli.rb +66 -22
  20. data/lib/bundler/compact_index_client/updater.rb +10 -1
  21. data/lib/bundler/current_ruby.rb +8 -1
  22. data/lib/bundler/definition.rb +48 -39
  23. data/lib/bundler/dep_proxy.rb +2 -2
  24. data/lib/bundler/dependency.rb +3 -2
  25. data/lib/bundler/deprecate.rb +2 -1
  26. data/lib/bundler/dsl.rb +19 -3
  27. data/lib/bundler/endpoint_specification.rb +1 -1
  28. data/lib/bundler/env.rb +10 -8
  29. data/lib/bundler/feature_flag.rb +7 -0
  30. data/lib/bundler/fetcher/downloader.rb +10 -5
  31. data/lib/bundler/fetcher/index.rb +2 -2
  32. data/lib/bundler/fetcher.rb +3 -3
  33. data/lib/bundler/friendly_errors.rb +2 -0
  34. data/lib/bundler/gem_helper.rb +1 -1
  35. data/lib/bundler/gem_version_promoter.rb +16 -2
  36. data/lib/bundler/injector.rb +173 -14
  37. data/lib/bundler/installer/gem_installer.rb +9 -2
  38. data/lib/bundler/installer/parallel_installer.rb +6 -1
  39. data/lib/bundler/installer.rb +41 -10
  40. data/lib/bundler/lazy_specification.rb +1 -1
  41. data/lib/bundler/mirror.rb +2 -2
  42. data/lib/bundler/plugin/events.rb +61 -0
  43. data/lib/bundler/plugin/index.rb +7 -2
  44. data/lib/bundler/plugin.rb +12 -5
  45. data/lib/bundler/process_lock.rb +1 -1
  46. data/lib/bundler/resolver/spec_group.rb +0 -5
  47. data/lib/bundler/resolver.rb +11 -10
  48. data/lib/bundler/ruby_version.rb +1 -1
  49. data/lib/bundler/rubygems_gem_installer.rb +7 -0
  50. data/lib/bundler/rubygems_integration.rb +9 -3
  51. data/lib/bundler/runtime.rb +10 -4
  52. data/lib/bundler/settings/validator.rb +23 -0
  53. data/lib/bundler/settings.rb +24 -3
  54. data/lib/bundler/shared_helpers.rb +33 -5
  55. data/lib/bundler/source/git/git_proxy.rb +6 -1
  56. data/lib/bundler/source/git.rb +2 -1
  57. data/lib/bundler/source/metadata.rb +2 -3
  58. data/lib/bundler/source/rubygems/remote.rb +4 -1
  59. data/lib/bundler/source/rubygems.rb +11 -2
  60. data/lib/bundler/source.rb +9 -9
  61. data/lib/bundler/spec_set.rb +4 -1
  62. data/lib/bundler/templates/Executable +1 -1
  63. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
  64. data/lib/bundler/templates/newgem/newgem.gemspec.tt +8 -2
  65. data/lib/bundler/templates/newgem/travis.yml.tt +2 -0
  66. data/lib/bundler/ui/shell.rb +3 -1
  67. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +11 -1
  68. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +7 -2
  69. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  70. data/lib/bundler/version.rb +1 -1
  71. data/lib/bundler.rb +38 -16
  72. data/man/bundle-add.1 +18 -3
  73. data/man/bundle-add.1.txt +17 -5
  74. data/man/bundle-add.ronn +13 -2
  75. data/man/bundle-binstubs.1 +4 -4
  76. data/man/bundle-binstubs.1.txt +4 -4
  77. data/man/bundle-binstubs.ronn +3 -3
  78. data/man/bundle-check.1 +4 -4
  79. data/man/bundle-check.1.txt +6 -5
  80. data/man/bundle-check.ronn +3 -3
  81. data/man/bundle-clean.1 +1 -1
  82. data/man/bundle-clean.1.txt +1 -1
  83. data/man/bundle-config.1 +48 -6
  84. data/man/bundle-config.1.txt +64 -26
  85. data/man/bundle-config.ronn +34 -9
  86. data/man/bundle-doctor.1 +44 -0
  87. data/man/bundle-doctor.1.txt +44 -0
  88. data/man/bundle-doctor.ronn +33 -0
  89. data/man/bundle-exec.1 +4 -4
  90. data/man/bundle-exec.1.txt +9 -9
  91. data/man/bundle-exec.ronn +3 -3
  92. data/man/bundle-gem.1 +2 -2
  93. data/man/bundle-gem.1.txt +2 -2
  94. data/man/bundle-gem.ronn +1 -1
  95. data/man/bundle-info.1 +1 -1
  96. data/man/bundle-info.1.txt +1 -1
  97. data/man/bundle-init.1 +9 -4
  98. data/man/bundle-init.1.txt +16 -6
  99. data/man/bundle-init.ronn +15 -4
  100. data/man/bundle-inject.1 +4 -4
  101. data/man/bundle-inject.1.txt +5 -5
  102. data/man/bundle-inject.ronn +3 -3
  103. data/man/bundle-install.1 +7 -4
  104. data/man/bundle-install.1.txt +119 -108
  105. data/man/bundle-install.ronn +13 -4
  106. data/man/bundle-list.1 +32 -2
  107. data/man/bundle-list.1.txt +24 -2
  108. data/man/bundle-list.ronn +19 -1
  109. data/man/bundle-lock.1 +2 -2
  110. data/man/bundle-lock.1.txt +2 -2
  111. data/man/bundle-lock.ronn +1 -1
  112. data/man/bundle-open.1 +1 -1
  113. data/man/bundle-open.1.txt +1 -1
  114. data/man/bundle-outdated.1 +7 -3
  115. data/man/bundle-outdated.1.txt +11 -7
  116. data/man/bundle-outdated.ronn +5 -1
  117. data/man/bundle-package.1 +3 -3
  118. data/man/bundle-package.1.txt +6 -6
  119. data/man/bundle-package.ronn +3 -3
  120. data/man/bundle-platform.1 +1 -1
  121. data/man/bundle-platform.1.txt +1 -1
  122. data/man/bundle-pristine.1 +1 -1
  123. data/man/bundle-pristine.1.txt +1 -1
  124. data/man/bundle-remove.1 +31 -0
  125. data/man/bundle-remove.1.txt +34 -0
  126. data/man/bundle-remove.ronn +23 -0
  127. data/man/bundle-show.1 +3 -3
  128. data/man/bundle-show.1.txt +6 -4
  129. data/man/bundle-show.ronn +3 -2
  130. data/man/bundle-update.1 +17 -13
  131. data/man/bundle-update.1.txt +68 -63
  132. data/man/bundle-update.ronn +19 -15
  133. data/man/bundle-viz.1 +2 -2
  134. data/man/bundle-viz.1.txt +3 -2
  135. data/man/bundle-viz.ronn +1 -1
  136. data/man/bundle.1 +32 -28
  137. data/man/bundle.1.txt +31 -28
  138. data/man/bundle.ronn +30 -27
  139. data/man/gemfile.5 +19 -9
  140. data/man/gemfile.5.ronn +24 -9
  141. data/man/gemfile.5.txt +114 -97
  142. data/man/index.txt +2 -0
  143. metadata +16 -3
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class CLI::Remove
5
+ def initialize(gems, options)
6
+ @gems = gems
7
+ @options = options
8
+ end
9
+
10
+ def run
11
+ raise InvalidOption, "Please specify gems to remove." if @gems.empty?
12
+
13
+ Injector.remove(@gems, {})
14
+
15
+ Installer.install(Bundler.root, Bundler.definition) if @options["install"]
16
+ end
17
+ end
18
+ end
@@ -38,8 +38,8 @@ module Bundler
38
38
  Bundler::CLI::Common.ensure_all_gems_in_lockfile!(gems)
39
39
 
40
40
  if groups.any?
41
- specs = Bundler.definition.specs_for groups
42
- gems.concat(specs.map(&:name))
41
+ deps = Bundler.definition.dependencies.select {|d| (d.groups & groups).any? }
42
+ gems.concat(deps.map(&:name))
43
43
  end
44
44
 
45
45
  Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
@@ -76,7 +76,7 @@ module Bundler
76
76
  if !new_version
77
77
  Bundler.ui.warn "Bundler attempted to update #{name} but it was removed from the bundle"
78
78
  elsif new_version < locked_version
79
- Bundler.ui.warn "Bundler attempted to update #{name} but its version regressed from #{locked_version} to #{new_version}"
79
+ Bundler.ui.warn "Note: #{name} version regressed from #{locked_version} to #{new_version}"
80
80
  elsif new_version == locked_version
81
81
  Bundler.ui.warn "Bundler attempted to update #{name} but its version stayed the same"
82
82
  end
data/lib/bundler/cli.rb CHANGED
@@ -166,6 +166,17 @@ module Bundler
166
166
  Check.new(options).run
167
167
  end
168
168
 
169
+ desc "remove [GEM [GEM ...]]", "Removes gems from the Gemfile"
170
+ long_desc <<-D
171
+ Removes the given gems from the Gemfile while ensuring that the resulting Gemfile is still valid. If the gem is not found, Bundler prints a error message and if gem could not be removed due to any reason Bundler will display a warning.
172
+ D
173
+ method_option "install", :type => :boolean, :banner =>
174
+ "Runs 'bundle install' after removing the gems from the Gemfile"
175
+ def remove(*gems)
176
+ require "bundler/cli/remove"
177
+ Remove.new(gems, options).run
178
+ end
179
+
169
180
  desc "install [OPTIONS]", "Install the current environment to the system"
170
181
  long_desc <<-D
171
182
  Install will install all of the gems in the current bundle, making them available
@@ -195,8 +206,7 @@ module Bundler
195
206
  "Do not attempt to fetch gems remotely and use the gem cache instead"
196
207
  deprecated_option "no-cache", :type => :boolean, :banner =>
197
208
  "Don't update the existing gem cache."
198
- method_option "redownload", :type => :boolean, :aliases =>
199
- [Bundler.feature_flag.forget_cli_options? ? nil : "--force"].compact, :banner =>
209
+ method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
200
210
  "Force downloading every gem."
201
211
  deprecated_option "no-prune", :type => :boolean, :banner =>
202
212
  "Don't remove stale gems from the cache."
@@ -219,6 +229,7 @@ module Bundler
219
229
  "Include gems that are part of the specified named group."
220
230
  map "i" => "install"
221
231
  def install
232
+ SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
222
233
  require "bundler/cli/install"
223
234
  Bundler.settings.temporary(:no_install => false) do
224
235
  Install.new(options.dup).run
@@ -233,6 +244,8 @@ module Bundler
233
244
  D
234
245
  method_option "full-index", :type => :boolean, :banner =>
235
246
  "Fall back to using the single-file index of all gems"
247
+ method_option "gemfile", :type => :string, :banner =>
248
+ "Use the specified gemfile instead of Gemfile"
236
249
  method_option "group", :aliases => "-g", :type => :array, :banner =>
237
250
  "Update a specific group"
238
251
  method_option "jobs", :aliases => "-j", :type => :numeric, :banner =>
@@ -243,7 +256,7 @@ module Bundler
243
256
  "Only output warnings and errors."
244
257
  method_option "source", :type => :array, :banner =>
245
258
  "Update a specific source (and all gems associated with it)"
246
- method_option "force", :type => :boolean, :banner =>
259
+ method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
247
260
  "Force downloading every gem."
248
261
  method_option "ruby", :type => :boolean, :banner =>
249
262
  "Update ruby specified in Gemfile.lock"
@@ -262,6 +275,7 @@ module Bundler
262
275
  method_option "all", :type => :boolean, :banner =>
263
276
  "Update everything."
264
277
  def update(*gems)
278
+ SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
265
279
  require "bundler/cli/update"
266
280
  Update.new(options, gems).run
267
281
  end
@@ -276,7 +290,21 @@ module Bundler
276
290
  method_option "outdated", :type => :boolean,
277
291
  :banner => "Show verbose output including whether gems are outdated."
278
292
  def show(gem_name = nil)
279
- Bundler::SharedHelpers.major_deprecation(2, "use `bundle list` instead of `bundle show`") if ARGV[0] == "show"
293
+ if ARGV[0] == "show"
294
+ rest = ARGV[1..-1]
295
+
296
+ new_command = rest.find {|arg| !arg.start_with?("--") } ? "info" : "list"
297
+
298
+ new_arguments = rest.map do |arg|
299
+ next arg if arg != "--paths"
300
+ next "--path" if new_command == "info"
301
+ end
302
+
303
+ old_argv = ARGV.join(" ")
304
+ new_argv = [new_command, *new_arguments.compact].join(" ")
305
+
306
+ Bundler::SharedHelpers.major_deprecation(2, "use `bundle #{new_argv}` instead of `bundle #{old_argv}`")
307
+ end
280
308
  require "bundler/cli/show"
281
309
  Show.new(options, gem_name).run
282
310
  end
@@ -285,6 +313,9 @@ module Bundler
285
313
  if Bundler.feature_flag.list_command?
286
314
  desc "list", "List all gems in the bundle"
287
315
  method_option "name-only", :type => :boolean, :banner => "print only the gem names"
316
+ method_option "only-group", :type => :string, :banner => "print gems from a particular group"
317
+ method_option "without-group", :type => :string, :banner => "print all gems expect from a group"
318
+ method_option "paths", :type => :boolean, :banner => "print the path to each gem in the bundle"
288
319
  def list
289
320
  require "bundler/cli/list"
290
321
  List.new(options).run
@@ -316,6 +347,8 @@ module Bundler
316
347
  "Specify a different shebang executable name than the default (usually 'ruby')"
317
348
  method_option "standalone", :type => :boolean, :banner =>
318
349
  "Make binstubs that can work without the Bundler runtime"
350
+ method_option "all", :type => :boolean, :banner =>
351
+ "Install binstubs for all gems"
319
352
  def binstubs(*gems)
320
353
  require "bundler/cli/binstubs"
321
354
  Binstubs.new(options, gems).run
@@ -328,10 +361,13 @@ module Bundler
328
361
  method_option "version", :aliases => "-v", :type => :string
329
362
  method_option "group", :aliases => "-g", :type => :string
330
363
  method_option "source", :aliases => "-s", :type => :string
331
-
332
- def add(gem_name)
364
+ method_option "skip-install", :type => :boolean, :banner =>
365
+ "Adds gem to the Gemfile but does not install it"
366
+ method_option "optimistic", :type => :boolean, :banner => "Adds optimistic declaration of version to gem"
367
+ method_option "strict", :type => :boolean, :banner => "Adds strict declaration of version to gem"
368
+ def add(*gems)
333
369
  require "bundler/cli/add"
334
- Add.new(options.dup, gem_name).run
370
+ Add.new(options.dup, gems).run
335
371
  end
336
372
 
337
373
  desc "outdated GEM [OPTIONS]", "List installed gems with newer versions available"
@@ -362,6 +398,8 @@ module Bundler
362
398
  method_option "filter-patch", :type => :boolean, :banner => "Only list patch newer versions"
363
399
  method_option "parseable", :aliases => "--porcelain", :type => :boolean, :banner =>
364
400
  "Use minimal formatting for more parseable output"
401
+ method_option "only-explicit", :type => :boolean, :banner =>
402
+ "Only list gems specified in your Gemfile, not their dependencies"
365
403
  def outdated(*gems)
366
404
  require "bundler/cli/outdated"
367
405
  Outdated.new(options, gems).run
@@ -413,6 +451,7 @@ module Bundler
413
451
 
414
452
  desc "exec [OPTIONS]", "Run the command in context of the bundle"
415
453
  method_option :keep_file_descriptors, :type => :boolean, :default => false
454
+ method_option :gemfile, :type => :string, :required => false
416
455
  long_desc <<-D
417
456
  Exec runs a command, providing it access to the gems in the bundle. While using
418
457
  bundle exec you can require and call the bundled gems as if they were installed
@@ -485,20 +524,23 @@ module Bundler
485
524
  end
486
525
  end
487
526
 
488
- desc "viz [OPTIONS]", "Generates a visual dependency graph", :hide => true
489
- long_desc <<-D
490
- Viz generates a PNG file of the current Gemfile as a dependency graph.
491
- Viz requires the ruby-graphviz gem (and its dependencies).
492
- The associated gems must also be installed via 'bundle install'.
493
- D
494
- method_option :file, :type => :string, :default => "gem_graph", :aliases => "-f", :desc => "The name to use for the generated file. see format option"
495
- method_option :format, :type => :string, :default => "png", :aliases => "-F", :desc => "This is output format option. Supported format is png, jpg, svg, dot ..."
496
- method_option :requirements, :type => :boolean, :default => false, :aliases => "-R", :desc => "Set to show the version of each required dependency."
497
- method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version."
498
- method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group."
499
- def viz
500
- require "bundler/cli/viz"
501
- Viz.new(options.dup).run
527
+ if Bundler.feature_flag.viz_command?
528
+ desc "viz [OPTIONS]", "Generates a visual dependency graph", :hide => true
529
+ long_desc <<-D
530
+ Viz generates a PNG file of the current Gemfile as a dependency graph.
531
+ Viz requires the ruby-graphviz gem (and its dependencies).
532
+ The associated gems must also be installed via 'bundle install'.
533
+ D
534
+ method_option :file, :type => :string, :default => "gem_graph", :aliases => "-f", :desc => "The name to use for the generated file. see format option"
535
+ method_option :format, :type => :string, :default => "png", :aliases => "-F", :desc => "This is output format option. Supported format is png, jpg, svg, dot ..."
536
+ method_option :requirements, :type => :boolean, :default => false, :aliases => "-R", :desc => "Set to show the version of each required dependency."
537
+ method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version."
538
+ method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group."
539
+ def viz
540
+ SharedHelpers.major_deprecation 2, "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz"
541
+ require "bundler/cli/viz"
542
+ Viz.new(options.dup).run
543
+ end
502
544
  end
503
545
 
504
546
  old_gem = instance_method(:gem)
@@ -717,6 +759,8 @@ module Bundler
717
759
  command_name = current_command.name
718
760
  return if PARSEABLE_COMMANDS.include?(command_name)
719
761
 
762
+ return unless SharedHelpers.md5_available?
763
+
720
764
  latest = Fetcher::CompactIndex.
721
765
  new(nil, Source::Rubygems::Remote.new(URI("https://rubygems.org")), nil).
722
766
  send(:compact_index_client).
@@ -739,7 +783,7 @@ module Bundler
739
783
  end
740
784
 
741
785
  Bundler.ui.warn "The latest bundler is #{latest}, but you are currently running #{current}.\n#{suggestion}"
742
- rescue
786
+ rescue RuntimeError
743
787
  nil
744
788
  end
745
789
  end
@@ -33,7 +33,9 @@ module Bundler
33
33
 
34
34
  # first try to fetch any new bytes on the existing file
35
35
  if retrying.nil? && local_path.file?
36
- FileUtils.cp local_path, local_temp_path
36
+ SharedHelpers.filesystem_access(local_temp_path) do
37
+ FileUtils.cp local_path, local_temp_path
38
+ end
37
39
  headers["If-None-Match"] = etag_for(local_temp_path)
38
40
  headers["Range"] =
39
41
  if local_temp_path.size.nonzero?
@@ -78,6 +80,13 @@ module Bundler
78
80
 
79
81
  update(local_path, remote_path, :retrying)
80
82
  end
83
+ rescue Errno::EACCES
84
+ raise Bundler::PermissionError,
85
+ "Bundler does not have write access to create a temp directory " \
86
+ "within #{Dir.tmpdir}. Bundler must have write access to your " \
87
+ "systems temp directory to function properly. "
88
+ rescue Zlib::GzipFile::Error
89
+ raise Bundler::HTTPError
81
90
  end
82
91
 
83
92
  def etag_for(path)
@@ -18,6 +18,7 @@ module Bundler
18
18
  2.3
19
19
  2.4
20
20
  2.5
21
+ 2.6
21
22
  ].freeze
22
23
 
23
24
  KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze
@@ -31,11 +32,13 @@ module Bundler
31
32
  mswin64
32
33
  rbx
33
34
  ruby
35
+ truffleruby
34
36
  x64_mingw
35
37
  ].freeze
36
38
 
37
39
  def ruby?
38
- !mswin? && (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev")
40
+ !mswin? && (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" ||
41
+ RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev" || RUBY_ENGINE == "truffleruby")
39
42
  end
40
43
 
41
44
  def mri?
@@ -54,6 +57,10 @@ module Bundler
54
57
  defined?(RUBY_ENGINE) && RUBY_ENGINE == "maglev"
55
58
  end
56
59
 
60
+ def truffleruby?
61
+ defined?(RUBY_ENGINE) && RUBY_ENGINE == "truffleruby"
62
+ end
63
+
57
64
  def mswin?
58
65
  Bundler::WINDOWS
59
66
  end
@@ -9,7 +9,6 @@ module Bundler
9
9
 
10
10
  attr_reader(
11
11
  :dependencies,
12
- :gem_version_promoter,
13
12
  :locked_deps,
14
13
  :locked_gems,
15
14
  :platforms,
@@ -77,6 +76,7 @@ module Bundler
77
76
  @lockfile_contents = String.new
78
77
  @locked_bundler_version = nil
79
78
  @locked_ruby_version = nil
79
+ @locked_specs_incomplete_for_platform = false
80
80
 
81
81
  if lockfile && File.exist?(lockfile)
82
82
  @lockfile_contents = Bundler.read_file(lockfile)
@@ -113,36 +113,36 @@ module Bundler
113
113
  end
114
114
  @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
115
115
 
116
- add_current_platform unless Bundler.frozen?
116
+ add_current_platform unless Bundler.frozen_bundle?
117
117
 
118
118
  converge_path_sources_to_gemspec_sources
119
119
  @path_changes = converge_paths
120
120
  @source_changes = converge_sources
121
121
 
122
122
  unless @unlock[:lock_shared_dependencies]
123
- eager_unlock = expand_dependencies(@unlock[:gems])
124
- @unlock[:gems] = @locked_specs.for(eager_unlock).map(&:name)
123
+ eager_unlock = expand_dependencies(@unlock[:gems], true)
124
+ @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name)
125
125
  end
126
126
 
127
- @gem_version_promoter = create_gem_version_promoter
128
-
129
127
  @dependency_changes = converge_dependencies
130
128
  @local_changes = converge_locals
131
129
 
132
130
  @requires = compute_requires
133
131
  end
134
132
 
135
- def create_gem_version_promoter
136
- locked_specs =
137
- if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty?
138
- # Definition uses an empty set of locked_specs to indicate all gems
139
- # are unlocked, but GemVersionPromoter needs the locked_specs
140
- # for conservative comparison.
141
- Bundler::SpecSet.new(@locked_gems.specs)
142
- else
143
- @locked_specs
144
- end
145
- GemVersionPromoter.new(locked_specs, @unlock[:gems])
133
+ def gem_version_promoter
134
+ @gem_version_promoter ||= begin
135
+ locked_specs =
136
+ if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty?
137
+ # Definition uses an empty set of locked_specs to indicate all gems
138
+ # are unlocked, but GemVersionPromoter needs the locked_specs
139
+ # for conservative comparison.
140
+ Bundler::SpecSet.new(@locked_gems.specs)
141
+ else
142
+ @locked_specs
143
+ end
144
+ GemVersionPromoter.new(locked_specs, @unlock[:gems])
145
+ end
146
146
  end
147
147
 
148
148
  def resolve_with_cache!
@@ -175,7 +175,7 @@ module Bundler
175
175
  raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \
176
176
  "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \
177
177
  "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \
178
- "to a different version of #{locked_gem} that hasn't been removed in order to install."
178
+ "to a version other than #{locked_gem} that hasn't been removed in order to install."
179
179
  end
180
180
  unless specs["bundler"].any?
181
181
  bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
@@ -213,7 +213,7 @@ module Bundler
213
213
  @index = nil
214
214
  @resolve = nil
215
215
  @specs = nil
216
- @gem_version_promoter = create_gem_version_promoter
216
+ @gem_version_promoter = nil
217
217
 
218
218
  Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
219
219
  true
@@ -245,17 +245,22 @@ module Bundler
245
245
  def resolve
246
246
  @resolve ||= begin
247
247
  last_resolve = converge_locked_specs
248
- if Bundler.frozen?
249
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
250
- last_resolve
251
- elsif !unlocking? && nothing_changed?
252
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
253
- last_resolve
254
- else
255
- # Run a resolve against the locally available gems
256
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
257
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
258
- end
248
+ resolve =
249
+ if Bundler.frozen_bundle?
250
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
251
+ last_resolve
252
+ elsif !unlocking? && nothing_changed?
253
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
254
+ last_resolve
255
+ else
256
+ # Run a resolve against the locally available gems
257
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
258
+ last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
259
+ end
260
+
261
+ # filter out gems that _can_ be installed on multiple platforms, but don't need
262
+ # to be
263
+ resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
259
264
  end
260
265
  end
261
266
 
@@ -336,10 +341,11 @@ module Bundler
336
341
  end
337
342
  end
338
343
 
339
- preserve_unknown_sections ||= !updating_major && (Bundler.frozen? || !(unlocking? || @unlocking_bundler))
340
- return if lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
344
+ preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
345
+
346
+ return if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
341
347
 
342
- if Bundler.frozen?
348
+ if Bundler.frozen_bundle?
343
349
  Bundler.ui.error "Cannot write a changed lockfile while frozen."
344
350
  return
345
351
  end
@@ -530,7 +536,7 @@ module Bundler
530
536
  private :sources
531
537
 
532
538
  def nothing_changed?
533
- !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes
539
+ !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
534
540
  end
535
541
 
536
542
  def unlocking?
@@ -557,6 +563,7 @@ module Bundler
557
563
  [@new_platform, "you added a new platform to your gemfile"],
558
564
  [@path_changes, "the gemspecs for path gems changed"],
559
565
  [@local_changes, "the gemspecs for git local gems changed"],
566
+ [@locked_specs_incomplete_for_platform, "the lockfile does not have all gems needed for the current platform"],
560
567
  ].select(&:first).map(&:last).join(", ")
561
568
  end
562
569
 
@@ -682,7 +689,7 @@ module Bundler
682
689
  end
683
690
 
684
691
  def converge_dependencies
685
- frozen = Bundler.frozen?
692
+ frozen = Bundler.frozen_bundle?
686
693
  (@dependencies + @locked_deps.values).each do |dep|
687
694
  locked_source = @locked_deps[dep.name]
688
695
  # This is to make sure that if bundler is installing in deployment mode and
@@ -803,7 +810,9 @@ module Bundler
803
810
  end
804
811
 
805
812
  resolve = SpecSet.new(converged)
806
- resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
813
+ expanded_deps = expand_dependencies(deps, true)
814
+ @locked_specs_incomplete_for_platform = !resolve.for(expanded_deps, @unlock[:gems], true, true)
815
+ resolve = resolve.for(expanded_deps, @unlock[:gems], false, false, false)
807
816
  diff = nil
808
817
 
809
818
  # Now, we unlock any sources that do not have anymore gems pinned to it
@@ -875,7 +884,7 @@ module Bundler
875
884
  dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
876
885
  next if !remote && !dep.current_platform?
877
886
  platforms = dep.gem_platforms(sorted_platforms)
878
- if platforms.empty?
887
+ if platforms.empty? && !Bundler.settings[:disable_platform_warnings]
879
888
  mapped_platforms = dep.platforms.map {|p| Dependency::PLATFORM_MAP[p] }
880
889
  Bundler.ui.warn \
881
890
  "The dependency #{dep} will be unused by any of the platforms Bundler is installing for. " \
@@ -965,10 +974,10 @@ module Bundler
965
974
 
966
975
  def additional_base_requirements_for_resolve
967
976
  return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
968
- dependencies_by_name = dependencies.group_by(&:name)
977
+ dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
969
978
  @locked_gems.specs.reduce({}) do |requirements, locked_spec|
970
979
  name = locked_spec.name
971
- next requirements if @locked_deps[name] != dependencies_by_name[name]
980
+ next requirements if @locked_gems.dependencies[name] != dependencies_by_name[name]
972
981
  dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
973
982
  requirements[name] = DepProxy.new(dep, locked_spec.platform)
974
983
  requirements
@@ -10,11 +10,11 @@ module Bundler
10
10
  end
11
11
 
12
12
  def hash
13
- @hash ||= dep.hash
13
+ @hash ||= [dep, __platform].hash
14
14
  end
15
15
 
16
16
  def ==(other)
17
- return if other.nil?
17
+ return false if other.class != self.class
18
18
  dep == other.dep && __platform == other.__platform
19
19
  end
20
20
 
@@ -7,8 +7,7 @@ require "bundler/rubygems_ext"
7
7
  module Bundler
8
8
  class Dependency < Gem::Dependency
9
9
  attr_reader :autorequire
10
- attr_reader :groups
11
- attr_reader :platforms
10
+ attr_reader :groups, :platforms, :gemfile
12
11
 
13
12
  PLATFORM_MAP = {
14
13
  :ruby => Gem::Platform::RUBY,
@@ -30,6 +29,7 @@ module Bundler
30
29
  :mri_24 => Gem::Platform::RUBY,
31
30
  :mri_25 => Gem::Platform::RUBY,
32
31
  :rbx => Gem::Platform::RUBY,
32
+ :truffleruby => Gem::Platform::RUBY,
33
33
  :jruby => Gem::Platform::JAVA,
34
34
  :jruby_18 => Gem::Platform::JAVA,
35
35
  :jruby_19 => Gem::Platform::JAVA,
@@ -87,6 +87,7 @@ module Bundler
87
87
  @platforms = Array(options["platforms"])
88
88
  @env = options["env"]
89
89
  @should_include = options.fetch("should_include", true)
90
+ @gemfile = options["gemfile"]
90
91
 
91
92
  @autorequire = Array(options["require"] || []) if options.key?("require")
92
93
  end
@@ -8,7 +8,8 @@ rescue LoadError
8
8
  end
9
9
 
10
10
  module Bundler
11
- if defined? Bundler::Deprecate
11
+ # If Bundler::Deprecate is an autoload constant, we need to define it
12
+ if defined?(Bundler::Deprecate) && !autoload?(:Deprecate)
12
13
  # nothing to do!
13
14
  elsif defined? ::Deprecate
14
15
  Deprecate = ::Deprecate
data/lib/bundler/dsl.rb CHANGED
@@ -16,7 +16,7 @@ module Bundler
16
16
  VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
17
17
 
18
18
  VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
19
- platform platforms type source install_if].freeze
19
+ platform platforms type source install_if gemfile].freeze
20
20
 
21
21
  attr_reader :gemspecs
22
22
  attr_accessor :dependencies
@@ -93,6 +93,7 @@ module Bundler
93
93
 
94
94
  def gem(name, *args)
95
95
  options = args.last.is_a?(Hash) ? args.pop.dup : {}
96
+ options["gemfile"] = @gemfile
96
97
  version = args || [">= 0"]
97
98
 
98
99
  normalize_options(name, version, options)
@@ -106,13 +107,28 @@ module Bundler
106
107
  if current.requirement != dep.requirement
107
108
  unless deleted_dep
108
109
  return if dep.type == :development
110
+
111
+ update_prompt = ""
112
+
113
+ if File.basename(@gemfile) == Injector::INJECTED_GEMS
114
+ if dep.requirements_list.include?(">= 0") && !current.requirements_list.include?(">= 0")
115
+ update_prompt = ". Gem already added"
116
+ else
117
+ update_prompt = ". If you want to update the gem version, run `bundle update #{current.name}`"
118
+
119
+ update_prompt += ". You may also need to change the version requirement specified in the Gemfile if it's too restrictive." unless current.requirements_list.include?(">= 0")
120
+ end
121
+ end
122
+
109
123
  raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
110
- "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})"
124
+ "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \
125
+ "#{update_prompt}"
111
126
  end
112
127
 
113
128
  else
114
129
  Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
115
130
  "You should probably keep only one of them.\n" \
131
+ "Remove any duplicate entries and specify the gem only once (per group).\n" \
116
132
  "While it's not a problem now, it could cause errors if you change the version of one of them later."
117
133
  end
118
134
 
@@ -289,7 +305,7 @@ module Bundler
289
305
  # end
290
306
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
291
307
  # TODO: 2.0 upgrade this setting to the default
292
- if Bundler.settings["github.https"]
308
+ if Bundler.feature_flag.github_https?
293
309
  Bundler::SharedHelpers.major_deprecation 2, "The `github.https` setting will be removed"
294
310
  "https://github.com/#{repo_name}.git"
295
311
  else
@@ -123,7 +123,7 @@ module Bundler
123
123
  @required_ruby_version = Gem::Requirement.new(v)
124
124
  end
125
125
  end
126
- rescue => e
126
+ rescue StandardError => e
127
127
  raise GemspecError, "There was an error parsing the metadata for the gem #{name} (#{version}): #{e.class}\n#{e}\nThe metadata was #{data.inspect}"
128
128
  end
129
129
 
data/lib/bundler/env.rb CHANGED
@@ -61,10 +61,10 @@ module Bundler
61
61
  end
62
62
 
63
63
  def self.read_file(filename)
64
- File.read(filename.to_s).strip
64
+ Bundler.read_file(filename.to_s).strip
65
65
  rescue Errno::ENOENT
66
66
  "<No #{filename} found>"
67
- rescue => e
67
+ rescue RuntimeError => e
68
68
  "#{e.class}: #{e.message}"
69
69
  end
70
70
 
@@ -88,7 +88,7 @@ module Bundler
88
88
 
89
89
  def self.version_of(script)
90
90
  return "not installed" unless Bundler.which(script)
91
- `#{script} --version`
91
+ `#{script} --version`.chomp
92
92
  end
93
93
 
94
94
  def self.chruby_version
@@ -110,11 +110,13 @@ module Bundler
110
110
  out << [" Gem Path", ENV.fetch("GEM_PATH") { Gem.path.join(File::PATH_SEPARATOR) }]
111
111
  out << [" User Path", Gem.user_dir]
112
112
  out << [" Bin Dir", Gem.bindir]
113
- out << ["OpenSSL"] if defined?(OpenSSL)
114
- out << [" Compiled", OpenSSL::OPENSSL_VERSION] if defined?(OpenSSL::OPENSSL_VERSION)
115
- out << [" Loaded", OpenSSL::OPENSSL_LIBRARY_VERSION] if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION)
116
- out << [" Cert File", OpenSSL::X509::DEFAULT_CERT_FILE] if defined?(OpenSSL::X509::DEFAULT_CERT_FILE)
117
- out << [" Cert Dir", OpenSSL::X509::DEFAULT_CERT_DIR] if defined?(OpenSSL::X509::DEFAULT_CERT_DIR)
113
+ if defined?(OpenSSL)
114
+ out << ["OpenSSL"]
115
+ out << [" Compiled", OpenSSL::OPENSSL_VERSION] if defined?(OpenSSL::OPENSSL_VERSION)
116
+ out << [" Loaded", OpenSSL::OPENSSL_LIBRARY_VERSION] if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION)
117
+ out << [" Cert File", OpenSSL::X509::DEFAULT_CERT_FILE] if defined?(OpenSSL::X509::DEFAULT_CERT_FILE)
118
+ out << [" Cert Dir", OpenSSL::X509::DEFAULT_CERT_DIR] if defined?(OpenSSL::X509::DEFAULT_CERT_DIR)
119
+ end
118
120
  out << ["Tools"]
119
121
  out << [" Git", git_version]
120
122
  out << [" RVM", ENV.fetch("rvm_version") { version_of("rvm") }]