rubygems-update 3.3.1 → 3.3.5

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -0
  3. data/Manifest.txt +1 -0
  4. data/bundler/CHANGELOG.md +35 -0
  5. data/bundler/lib/bundler/.document +1 -0
  6. data/bundler/lib/bundler/build_metadata.rb +2 -2
  7. data/bundler/lib/bundler/cli/install.rb +0 -3
  8. data/bundler/lib/bundler/cli/update.rb +6 -2
  9. data/bundler/lib/bundler/cli.rb +3 -10
  10. data/bundler/lib/bundler/compact_index_client/cache.rb +0 -9
  11. data/bundler/lib/bundler/compact_index_client.rb +0 -6
  12. data/bundler/lib/bundler/definition.rb +1 -12
  13. data/bundler/lib/bundler/endpoint_specification.rb +21 -3
  14. data/bundler/lib/bundler/fetcher/compact_index.rb +0 -10
  15. data/bundler/lib/bundler/fetcher/index.rb +0 -26
  16. data/bundler/lib/bundler/fetcher.rb +4 -9
  17. data/bundler/lib/bundler/gem_helper.rb +2 -2
  18. data/bundler/lib/bundler/lazy_specification.rb +2 -2
  19. data/bundler/lib/bundler/lockfile_generator.rb +1 -1
  20. data/bundler/lib/bundler/resolver/spec_group.rb +1 -1
  21. data/bundler/lib/bundler/resolver.rb +2 -8
  22. data/bundler/lib/bundler/ruby_version.rb +1 -1
  23. data/bundler/lib/bundler/self_manager.rb +106 -14
  24. data/bundler/lib/bundler/settings.rb +1 -0
  25. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
  26. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -4
  27. data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  28. data/bundler/lib/bundler/version.rb +1 -1
  29. data/lib/rubygems/commands/fetch_command.rb +27 -8
  30. data/lib/rubygems/commands/update_command.rb +4 -3
  31. data/lib/rubygems/exceptions.rb +7 -3
  32. data/lib/rubygems/package/old.rb +1 -1
  33. data/lib/rubygems/package.rb +1 -1
  34. data/lib/rubygems/psych_additions.rb +1 -1
  35. data/lib/rubygems/resolver/installer_set.rb +9 -9
  36. data/lib/rubygems/safe_yaml.rb +8 -8
  37. data/lib/rubygems/security.rb +1 -1
  38. data/lib/rubygems/specification.rb +5 -6
  39. data/lib/rubygems/stub_specification.rb +1 -4
  40. data/lib/rubygems.rb +34 -41
  41. data/rubygems-update.gemspec +1 -1
  42. data/test/rubygems/helper.rb +6 -6
  43. data/test/rubygems/test_gem_commands_fetch_command.rb +97 -0
  44. data/test/rubygems/test_gem_commands_install_command.rb +49 -0
  45. data/test/rubygems/test_gem_commands_update_command.rb +25 -0
  46. data/test/rubygems/test_gem_installer.rb +0 -27
  47. data/test/rubygems/test_gem_package.rb +2 -2
  48. data/test/rubygems/test_gem_stream_ui.rb +1 -1
  49. data/test/rubygems/test_gem_stub_specification.rb +0 -16
  50. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f3cab95c0495f8346fe4ddaa9d60f798d06132f484f36749d10035c29a9cab8
4
- data.tar.gz: fecd45d7fa7b3c41ae7af764b062b8355d6986aadab9b513759e2af75a9d8720
3
+ metadata.gz: 9648fb20873191a9544a114fb8924f9f08625fa63d590a3a0434e3b2b95b516d
4
+ data.tar.gz: b29121744e804674e10ae19f1cbc9525a8c8c0ee73072e27baf726479b995180
5
5
  SHA512:
6
- metadata.gz: b4b89fb3675c171488c620a0d88998e5f31de023160b77d804c0cab871b8b09446e32e018e2a8923451bf8b2ee33d20c66e6374db97468c1654d677fafb12d37
7
- data.tar.gz: 0e4ddbea298fca2bcbbdddf41bf90d9853d565e705ee5adb1035f6fd85d941ced05c4370511cc12102cc8804753d132a7ccc461316c90cd4644473995e3a0087
6
+ metadata.gz: 5b8f751c2bd5a5bca0b8c7baa474ac226cb697275582681f14cb57326279e5f17db249803f33177344f7ebb199fef3c1c396c7aaf749950b3b8bb62e47b16dce
7
+ data.tar.gz: c5be5acbc735daa56571bbf4b51a1edf0271c8c6d56d7a7a403401a03863580669cdca71b9d426434701200a2cd10e20b215d1b6b17f8d1bebe4cd2bcdf91ed2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,65 @@
1
+ # 3.3.5 / 2022-01-12
2
+
3
+ ## Enhancements:
4
+
5
+ * Don't activate `yaml` gem from RubyGems. Pull request #5266 by
6
+ deivid-rodriguez
7
+ * Let `gem fetch` understand `<gem>:<version>` syntax and
8
+ `--[no-]suggestions` flag. Pull request #5242 by ximenasandoval
9
+ * Installs bundler 2.3.5 as a default gem.
10
+
11
+ ## Bug fixes:
12
+
13
+ * Fix `gem install <non-existent-gem> --force` crash. Pull request #5262
14
+ by deivid-rodriguez
15
+ * Fix longstanding `gem install` failure on JRuby. Pull request #5228 by
16
+ deivid-rodriguez
17
+
18
+ ## Documentation:
19
+
20
+ * Markup `Gem::Specification` documentation with RDoc notations. Pull
21
+ request #5268 by nobu
22
+
23
+ # 3.3.4 / 2021-12-29
24
+
25
+ ## Enhancements:
26
+
27
+ * Don't redownload `rubygems-update` package if already there. Pull
28
+ request #5230 by deivid-rodriguez
29
+ * Installs bundler 2.3.4 as a default gem.
30
+
31
+ ## Bug fixes:
32
+
33
+ * Fix `gem update --system` crashing when latest version not supported.
34
+ Pull request #5191 by deivid-rodriguez
35
+
36
+ ## Performance:
37
+
38
+ * Make SpecificationPolicy autoload constant. Pull request #5222 by pocke
39
+
40
+ # 3.3.3 / 2021-12-24
41
+
42
+ ## Enhancements:
43
+
44
+ * Installs bundler 2.3.3 as a default gem.
45
+
46
+ ## Bug fixes:
47
+
48
+ * Fix gem installation failing in Solaris due to bad `IO#flock` usage.
49
+ Pull request #5216 by mame
50
+
51
+ # 3.3.2 / 2021-12-23
52
+
53
+ ## Enhancements:
54
+
55
+ * Fix deprecations when activating DidYouMean for misspelled command
56
+ suggestions. Pull request #5211 by yuki24
57
+ * Installs bundler 2.3.2 as a default gem.
58
+
59
+ ## Bug fixes:
60
+
61
+ * Fix gemspec truncation. Pull request #5208 by deivid-rodriguez
62
+
1
63
  # 3.3.1 / 2021-12-22
2
64
 
3
65
  ## Enhancements:
data/Manifest.txt CHANGED
@@ -18,6 +18,7 @@ bundler/bundler.gemspec
18
18
  bundler/exe/bundle
19
19
  bundler/exe/bundler
20
20
  bundler/lib/bundler.rb
21
+ bundler/lib/bundler/.document
21
22
  bundler/lib/bundler/build_metadata.rb
22
23
  bundler/lib/bundler/capistrano.rb
23
24
  bundler/lib/bundler/cli.rb
data/bundler/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
+ # 2.3.5 (January 12, 2022)
2
+
3
+ ## Enhancements:
4
+
5
+ - Make `bundle update --bundler` actually lock to the latest bundler version (even if not yet installed) [#5182](https://github.com/rubygems/rubygems/pull/5182)
6
+ - Use thor-1.2.1 [#5260](https://github.com/rubygems/rubygems/pull/5260)
7
+ - Exclude bin directory for newgem template [#5259](https://github.com/rubygems/rubygems/pull/5259)
8
+
9
+ ## Bug fixes:
10
+
11
+ - Fix metadata requirements being bypassed when custom gem servers are used [#5256](https://github.com/rubygems/rubygems/pull/5256)
12
+ - Fix `rake build:checksum` writing checksum of package path, not package contents [#5250](https://github.com/rubygems/rubygems/pull/5250)
13
+
14
+ # 2.3.4 (December 29, 2021)
15
+
16
+ ## Enhancements:
17
+
18
+ - Improve error message when `BUNDLED WITH` version does not exist [#5205](https://github.com/rubygems/rubygems/pull/5205)
19
+
20
+ ## Bug fixes:
21
+
22
+ - Fix `bundle update --bundler` no longer updating lockfile [#5224](https://github.com/rubygems/rubygems/pull/5224)
23
+
24
+ # 2.3.3 (December 24, 2021)
25
+
26
+ ## Bug fixes:
27
+
28
+ - Fix locked bundler not installed to the right path when `deployment` is set [#5217](https://github.com/rubygems/rubygems/pull/5217)
29
+
30
+ # 2.3.2 (December 23, 2021)
31
+
32
+ ## Enhancements:
33
+
34
+ - Remove unnecessary lockfile upgrade warning [#5209](https://github.com/rubygems/rubygems/pull/5209)
35
+
1
36
  # 2.3.1 (December 22, 2021)
2
37
 
3
38
  ## Enhancements:
@@ -0,0 +1 @@
1
+ # not in RDoc
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2021-12-22".freeze
8
- @git_commit_sha = "7b38ca2f84".freeze
7
+ @built_at = "2022-01-12".freeze
8
+ @git_commit_sha = "a13d015fcb".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -165,9 +165,6 @@ module Bundler
165
165
 
166
166
  def normalize_settings
167
167
  Bundler.settings.set_command_option :path, nil if options[:system]
168
- Bundler.settings.temporary(:path_relative_to_cwd => false) do
169
- Bundler.settings.set_command_option :path, "vendor/bundle" if Bundler.settings[:deployment] && Bundler.settings[:path].nil?
170
- end
171
168
  Bundler.settings.set_command_option_if_given :path, options[:path]
172
169
  Bundler.settings.temporary(:path_relative_to_cwd => false) do
173
170
  Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil?
@@ -11,12 +11,16 @@ module Bundler
11
11
  def run
12
12
  Bundler.ui.level = "warn" if options[:quiet]
13
13
 
14
+ update_bundler = options[:bundler]
15
+
16
+ Bundler.self_manager.update_bundler_and_restart_with_it_if_needed(update_bundler) if update_bundler
17
+
14
18
  Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
15
19
 
16
20
  sources = Array(options[:source])
17
21
  groups = Array(options[:group]).map(&:to_sym)
18
22
 
19
- full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !options[:bundler]
23
+ full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !update_bundler
20
24
 
21
25
  if full_update && !options[:all]
22
26
  if Bundler.feature_flag.update_requires_all_flag?
@@ -49,7 +53,7 @@ module Bundler
49
53
 
50
54
  Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
51
55
  :conservative => conservative,
52
- :bundler => options[:bundler])
56
+ :bundler => update_bundler)
53
57
  end
54
58
 
55
59
  Bundler::CLI::Common.configure_gem_version_promoter(Bundler.definition, options)
@@ -809,17 +809,10 @@ module Bundler
809
809
 
810
810
  current = Gem::Version.new(VERSION)
811
811
  return if current >= latest
812
- latest_installed = Bundler.rubygems.find_name("bundler").map(&:version).max
813
812
 
814
- installation = "To install the latest version, run `gem install bundler#{" --pre" if latest.prerelease?}`"
815
- if latest_installed && latest_installed > current
816
- suggestion = "To update to the most recent installed version (#{latest_installed}), run `bundle update --bundler`"
817
- suggestion = "#{installation}\n#{suggestion}" if latest_installed < latest
818
- else
819
- suggestion = installation
820
- end
821
-
822
- Bundler.ui.warn "The latest bundler is #{latest}, but you are currently running #{current}.\n#{suggestion}"
813
+ Bundler.ui.warn \
814
+ "The latest bundler is #{latest}, but you are currently running #{current}.\n" \
815
+ "To update to the most recent version, run `bundle update --bundler`"
823
816
  rescue RuntimeError
824
817
  nil
825
818
  end
@@ -76,15 +76,6 @@ module Bundler
76
76
  end
77
77
  end
78
78
 
79
- def specific_dependency(name, version, platform)
80
- pattern = [version, platform].compact.join("-")
81
- return nil if pattern.empty?
82
-
83
- gem_lines = info_path(name).read
84
- gem_line = gem_lines[/^#{Regexp.escape(pattern)}\b.*/, 0]
85
- gem_line ? parse_gem(gem_line) : nil
86
- end
87
-
88
79
  private
89
80
 
90
81
  def lines(path)
@@ -73,12 +73,6 @@ module Bundler
73
73
  end.flatten(1)
74
74
  end
75
75
 
76
- def spec(name, version, platform = nil)
77
- Bundler::CompactIndexClient.debug { "spec(name = #{name}, version = #{version}, platform = #{platform})" }
78
- update_info(name)
79
- @cache.specific_dependency(name, version, platform)
80
- end
81
-
82
76
  def update_and_parse_checksums!
83
77
  Bundler::CompactIndexClient.debug { "update_and_parse_checksums!" }
84
78
  return @info_checksums_by_name if @parsed_checksums
@@ -292,10 +292,7 @@ module Bundler
292
292
  locked_major = @locked_bundler_version.segments.first
293
293
  current_major = Gem::Version.create(Bundler::VERSION).segments.first
294
294
 
295
- if updating_major = locked_major < current_major
296
- Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \
297
- "after which you will be unable to return to Bundler #{locked_major}."
298
- end
295
+ updating_major = locked_major < current_major
299
296
  end
300
297
 
301
298
  preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
@@ -312,14 +309,6 @@ module Bundler
312
309
  end
313
310
  end
314
311
 
315
- def locked_bundler_version
316
- if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
317
- new_version = Bundler::VERSION
318
- end
319
-
320
- new_version || @locked_bundler_version || Bundler::VERSION
321
- end
322
-
323
312
  def locked_ruby_version
324
313
  return unless ruby_version
325
314
  if @unlock[:ruby] || !@locked_ruby_version
@@ -5,14 +5,15 @@ module Bundler
5
5
  class EndpointSpecification < Gem::Specification
6
6
  include MatchPlatform
7
7
 
8
- attr_reader :name, :version, :platform, :required_rubygems_version, :required_ruby_version, :checksum
8
+ attr_reader :name, :version, :platform, :checksum
9
9
  attr_accessor :source, :remote, :dependencies
10
10
 
11
- def initialize(name, version, platform, dependencies, metadata = nil)
11
+ def initialize(name, version, platform, spec_fetcher, dependencies, metadata = nil)
12
12
  super()
13
13
  @name = name
14
14
  @version = Gem::Version.create version
15
15
  @platform = platform
16
+ @spec_fetcher = spec_fetcher
16
17
  @dependencies = dependencies.map {|dep, reqs| build_dependency(dep, reqs) }
17
18
 
18
19
  @loaded_from = nil
@@ -21,6 +22,14 @@ module Bundler
21
22
  parse_metadata(metadata)
22
23
  end
23
24
 
25
+ def required_ruby_version
26
+ @required_ruby_version ||= _remote_specification.required_ruby_version
27
+ end
28
+
29
+ def required_rubygems_version
30
+ @required_rubygems_version ||= _remote_specification.required_rubygems_version
31
+ end
32
+
24
33
  def fetch_platform
25
34
  @platform
26
35
  end
@@ -105,12 +114,21 @@ module Bundler
105
114
 
106
115
  private
107
116
 
117
+ def _remote_specification
118
+ @_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @platform])
119
+ end
120
+
108
121
  def local_specification_path
109
122
  "#{base_dir}/specifications/#{full_name}.gemspec"
110
123
  end
111
124
 
112
125
  def parse_metadata(data)
113
- return unless data
126
+ unless data
127
+ @required_ruby_version = nil
128
+ @required_rubygems_version = nil
129
+ return
130
+ end
131
+
114
132
  data.each do |k, v|
115
133
  next unless v
116
134
  case k.to_s
@@ -57,16 +57,6 @@ module Bundler
57
57
  gem_info
58
58
  end
59
59
 
60
- def fetch_spec(spec)
61
- spec -= [nil, "ruby", ""]
62
- contents = compact_index_client.spec(*spec)
63
- return nil if contents.nil?
64
- contents.unshift(spec.first)
65
- contents[3].map! {|d| Gem::Dependency.new(*d) }
66
- EndpointSpecification.new(*contents)
67
- end
68
- compact_index_request :fetch_spec
69
-
70
60
  def available?
71
61
  unless SharedHelpers.md5_available?
72
62
  Bundler.ui.debug("FIPS mode is enabled, bundler can't use the CompactIndex API")
@@ -21,32 +21,6 @@ module Bundler
21
21
  raise HTTPError, "Could not fetch specs from #{display_uri} due to underlying error <#{e.message}>"
22
22
  end
23
23
  end
24
-
25
- def fetch_spec(spec)
26
- spec -= [nil, "ruby", ""]
27
- spec_file_name = "#{spec.join "-"}.gemspec"
28
-
29
- uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
30
- if uri.scheme == "file"
31
- path = Bundler.rubygems.correct_for_windows_path(uri.path)
32
- Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(path))
33
- elsif cached_spec_path = gemspec_cached_path(spec_file_name)
34
- Bundler.load_gemspec(cached_spec_path)
35
- else
36
- Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
37
- end
38
- rescue MarshalError
39
- raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
40
- "Your network or your gem server is probably having issues right now."
41
- end
42
-
43
- private
44
-
45
- # cached gem specification path, if one exists
46
- def gemspec_cached_path(spec_file_name)
47
- paths = Bundler.rubygems.spec_cache_dirs.map {|dir| File.join(dir, spec_file_name) }
48
- paths.find {|path| File.file? path }
49
- end
50
24
  end
51
25
  end
52
26
  end
@@ -129,17 +129,15 @@ module Bundler
129
129
  specs = fetchers.last.specs(gem_names)
130
130
  else
131
131
  specs = []
132
- fetchers.shift until fetchers.first.available? || fetchers.empty?
133
- fetchers.dup.each do |f|
134
- break unless f.api_fetcher? && !gem_names || !specs = f.specs(gem_names)
135
- fetchers.delete(f)
132
+ @fetchers = fetchers.drop_while do |f|
133
+ !f.available? || (f.api_fetcher? && !gem_names) || !specs = f.specs(gem_names)
136
134
  end
137
135
  @use_api = false if fetchers.none?(&:api_fetcher?)
138
136
  end
139
137
 
140
138
  specs.each do |name, version, platform, dependencies, metadata|
141
139
  spec = if dependencies
142
- EndpointSpecification.new(name, version, platform, dependencies, metadata)
140
+ EndpointSpecification.new(name, version, platform, self, dependencies, metadata)
143
141
  else
144
142
  RemoteSpecification.new(name, version, platform, self)
145
143
  end
@@ -272,8 +270,7 @@ module Bundler
272
270
  # cached gem specification path, if one exists
273
271
  def gemspec_cached_path(spec_file_name)
274
272
  paths = Bundler.rubygems.spec_cache_dirs.map {|dir| File.join(dir, spec_file_name) }
275
- paths = paths.select {|path| File.file? path }
276
- paths.first
273
+ paths.find {|path| File.file? path }
277
274
  end
278
275
 
279
276
  HTTP_ERRORS = [
@@ -301,8 +298,6 @@ module Bundler
301
298
  store
302
299
  end
303
300
 
304
- private
305
-
306
301
  def remote_uri
307
302
  @remote.uri
308
303
  end
@@ -107,9 +107,9 @@ module Bundler
107
107
  SharedHelpers.filesystem_access(File.join(base, "checksums")) {|p| FileUtils.mkdir_p(p) }
108
108
  file_name = "#{File.basename(built_gem_path)}.sha512"
109
109
  require "digest/sha2"
110
- checksum = ::Digest::SHA512.new.hexdigest(built_gem_path.to_s)
110
+ checksum = ::Digest::SHA512.file(built_gem_path).hexdigest
111
111
  target = File.join(base, "checksums", file_name)
112
- File.write(target, checksum)
112
+ File.write(target, checksum + "\n")
113
113
  Bundler.ui.confirm "#{name} #{version} checksum written to checksums/#{file_name}."
114
114
  end
115
115
 
@@ -90,11 +90,11 @@ module Bundler
90
90
  MatchPlatform.platforms_match?(spec.platform, platform_object)
91
91
  end
92
92
  installable_candidates = same_platform_candidates.select do |spec|
93
- !spec.is_a?(EndpointSpecification) ||
93
+ spec.is_a?(StubSpecification) ||
94
94
  (spec.required_ruby_version.satisfied_by?(Gem.ruby_version) &&
95
95
  spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version))
96
96
  end
97
- search = installable_candidates.last || same_platform_candidates.last
97
+ search = installable_candidates.last
98
98
  search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
99
99
  search
100
100
  end
@@ -71,7 +71,7 @@ module Bundler
71
71
  end
72
72
 
73
73
  def add_bundled_with
74
- add_section("BUNDLED WITH", definition.locked_bundler_version.to_s)
74
+ add_section("BUNDLED WITH", Bundler::VERSION)
75
75
  end
76
76
 
77
77
  def add_section(name, value)
@@ -95,7 +95,7 @@ module Bundler
95
95
 
96
96
  def metadata_dependencies(platform)
97
97
  spec = @specs[platform].first
98
- return [] unless spec.is_a?(Gem::Specification)
98
+ return [] if spec.is_a?(LazySpecification)
99
99
  dependencies = []
100
100
  if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
101
101
  dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
@@ -358,24 +358,18 @@ module Bundler
358
358
  o << "\n"
359
359
  o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
360
360
  o << %(the gems in your Gemfile, which may resolve the conflict.\n)
361
- elsif !conflict.existing
361
+ elsif !conflict.existing && !name.end_with?("\0")
362
362
  o << "\n"
363
363
 
364
364
  relevant_source = conflict.requirement.source || source_for(name)
365
365
 
366
- metadata_requirement = name.end_with?("\0")
367
-
368
366
  extra_message = if conflict.requirement_trees.first.size > 1
369
367
  ", which is required by gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
370
368
  else
371
369
  ""
372
370
  end
373
371
 
374
- if metadata_requirement
375
- o << "#{SharedHelpers.pretty_dependency(conflict.requirement)}#{extra_message} is not available in #{relevant_source}"
376
- else
377
- o << gem_not_found_message(name, conflict.requirement, relevant_source, extra_message)
378
- end
372
+ o << gem_not_found_message(name, conflict.requirement, relevant_source, extra_message)
379
373
  end
380
374
  end,
381
375
  :version_for_spec => lambda {|spec| spec.version },
@@ -103,7 +103,7 @@ module Bundler
103
103
 
104
104
  def self.system
105
105
  ruby_engine = RUBY_ENGINE.dup
106
- ruby_version = ENV.fetch("BUNDLER_SPEC_RUBY_VERSION") { RUBY_VERSION }.dup
106
+ ruby_version = RUBY_VERSION.dup
107
107
  ruby_engine_version = RUBY_ENGINE_VERSION.dup
108
108
  patchlevel = RUBY_PATCHLEVEL.to_s
109
109
 
@@ -9,7 +9,7 @@ module Bundler
9
9
  def restart_with_locked_bundler_if_needed
10
10
  return unless needs_switching? && installed?
11
11
 
12
- restart_with_locked_bundler
12
+ restart_with(lockfile_version)
13
13
  end
14
14
 
15
15
  def install_locked_bundler_and_restart_with_it_if_needed
@@ -19,23 +19,48 @@ module Bundler
19
19
  "Bundler #{current_version} is running, but your lockfile was generated with #{lockfile_version}. " \
20
20
  "Installing Bundler #{lockfile_version} and restarting using that version."
21
21
 
22
- install_and_restart_with_locked_bundler
22
+ install_and_restart_with(lockfile_version)
23
+ end
24
+
25
+ def update_bundler_and_restart_with_it_if_needed(target)
26
+ return unless autoswitching_applies?
27
+
28
+ spec = resolve_update_version_from(target)
29
+ return unless spec
30
+
31
+ version = spec.version
32
+
33
+ Bundler.ui.info "Updating bundler to #{version}."
34
+
35
+ install(spec)
36
+
37
+ restart_with(version)
23
38
  end
24
39
 
25
40
  private
26
41
 
27
- def install_and_restart_with_locked_bundler
28
- bundler_dep = Gem::Dependency.new("bundler", lockfile_version)
42
+ def install_and_restart_with(version)
43
+ requirement = Gem::Requirement.new(version)
44
+ spec = find_latest_matching_spec(requirement)
29
45
 
30
- Gem.install(bundler_dep)
46
+ if spec.nil?
47
+ Bundler.ui.warn "Your lockfile is locked to a version of bundler (#{lockfile_version}) that doesn't exist at https://rubygems.org/. Going on using #{current_version}"
48
+ return
49
+ end
50
+
51
+ install(spec)
31
52
  rescue StandardError => e
32
53
  Bundler.ui.trace e
33
54
  Bundler.ui.warn "There was an error installing the locked bundler version (#{lockfile_version}), rerun with the `--verbose` flag for more details. Going on using bundler #{current_version}."
34
55
  else
35
- restart_with_locked_bundler
56
+ restart_with(version)
57
+ end
58
+
59
+ def install(spec)
60
+ spec.source.install(spec)
36
61
  end
37
62
 
38
- def restart_with_locked_bundler
63
+ def restart_with(version)
39
64
  configured_gem_home = ENV["GEM_HOME"]
40
65
  configured_gem_path = ENV["GEM_PATH"]
41
66
 
@@ -44,33 +69,100 @@ module Bundler
44
69
 
45
70
  Bundler.with_original_env do
46
71
  Kernel.exec(
47
- { "GEM_HOME" => configured_gem_home, "GEM_PATH" => configured_gem_path, "BUNDLER_VERSION" => lockfile_version },
72
+ { "GEM_HOME" => configured_gem_home, "GEM_PATH" => configured_gem_path, "BUNDLER_VERSION" => version.to_s },
48
73
  *cmd
49
74
  )
50
75
  end
51
76
  end
52
77
 
53
78
  def needs_switching?
79
+ autoswitching_applies? &&
80
+ released?(lockfile_version) &&
81
+ !running?(lockfile_version) &&
82
+ !updating?
83
+ end
84
+
85
+ def autoswitching_applies?
54
86
  ENV["BUNDLER_VERSION"].nil? &&
55
87
  Bundler.rubygems.supports_bundler_trampolining? &&
56
88
  SharedHelpers.in_bundle? &&
57
- lockfile_version &&
58
- !lockfile_version.end_with?(".dev") &&
59
- lockfile_version != current_version
89
+ lockfile_version
90
+ end
91
+
92
+ def resolve_update_version_from(target)
93
+ requirement = Gem::Requirement.new(target)
94
+ update_candidate = find_latest_matching_spec(requirement)
95
+
96
+ if update_candidate.nil?
97
+ raise InvalidOption, "The `bundle update --bundler` target version (#{target}) does not exist"
98
+ end
99
+
100
+ resolved_version = update_candidate.version
101
+ needs_update = requirement.specific? ? !running?(resolved_version) : running_older_than?(resolved_version)
102
+
103
+ return unless needs_update
104
+
105
+ update_candidate
106
+ end
107
+
108
+ def local_specs
109
+ @local_specs ||= Bundler::Source::Rubygems.new("allow_local" => true).specs.select {|spec| spec.name == "bundler" }
110
+ end
111
+
112
+ def remote_specs
113
+ @remote_specs ||= begin
114
+ source = Bundler::Source::Rubygems.new("remotes" => "https://rubygems.org")
115
+ source.remote!
116
+ source.add_dependency_names("bundler")
117
+ source.specs
118
+ end
119
+ end
120
+
121
+ def find_latest_matching_spec(requirement)
122
+ local_result = find_latest_matching_spec_from_collection(local_specs, requirement)
123
+ return local_result if local_result && requirement.specific?
124
+
125
+ remote_result = find_latest_matching_spec_from_collection(remote_specs, requirement)
126
+ return remote_result if local_result.nil?
127
+
128
+ [local_result, remote_result].max
129
+ end
130
+
131
+ def find_latest_matching_spec_from_collection(specs, requirement)
132
+ specs.sort.reverse_each.find {|spec| requirement.satisfied_by?(spec.version) }
133
+ end
134
+
135
+ def running?(version)
136
+ version == current_version
137
+ end
138
+
139
+ def running_older_than?(version)
140
+ current_version < version
141
+ end
142
+
143
+ def released?(version)
144
+ !version.to_s.end_with?(".dev")
145
+ end
146
+
147
+ def updating?
148
+ "update".start_with?(ARGV.first || " ") && ARGV[1..-1].any? {|a| a.start_with?("--bundler") }
60
149
  end
61
150
 
62
151
  def installed?
63
152
  Bundler.configure
64
153
 
65
- Bundler.rubygems.find_bundler(lockfile_version)
154
+ Bundler.rubygems.find_bundler(lockfile_version.to_s)
66
155
  end
67
156
 
68
157
  def current_version
69
- @current_version ||= Bundler::VERSION
158
+ @current_version ||= Gem::Version.new(Bundler::VERSION)
70
159
  end
71
160
 
72
161
  def lockfile_version
73
- @lockfile_version ||= Bundler::LockfileParser.bundled_with
162
+ return @lockfile_version if defined?(@lockfile_version)
163
+
164
+ parsed_version = Bundler::LockfileParser.bundled_with
165
+ @lockfile_version = parsed_version ? Gem::Version.new(parsed_version) : nil
74
166
  end
75
167
  end
76
168
  end