rubygems-update 3.3.4 → 3.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/bundler/CHANGELOG.md +13 -0
  4. data/bundler/lib/bundler/build_metadata.rb +2 -2
  5. data/bundler/lib/bundler/cli/update.rb +6 -2
  6. data/bundler/lib/bundler/cli.rb +3 -10
  7. data/bundler/lib/bundler/compact_index_client/cache.rb +0 -9
  8. data/bundler/lib/bundler/compact_index_client.rb +0 -6
  9. data/bundler/lib/bundler/definition.rb +0 -8
  10. data/bundler/lib/bundler/endpoint_specification.rb +21 -3
  11. data/bundler/lib/bundler/fetcher/compact_index.rb +0 -10
  12. data/bundler/lib/bundler/fetcher/index.rb +0 -26
  13. data/bundler/lib/bundler/fetcher.rb +4 -9
  14. data/bundler/lib/bundler/gem_helper.rb +2 -2
  15. data/bundler/lib/bundler/lazy_specification.rb +2 -2
  16. data/bundler/lib/bundler/lockfile_generator.rb +1 -1
  17. data/bundler/lib/bundler/resolver/spec_group.rb +1 -1
  18. data/bundler/lib/bundler/resolver.rb +2 -8
  19. data/bundler/lib/bundler/self_manager.rb +103 -29
  20. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
  21. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -4
  22. data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  23. data/bundler/lib/bundler/version.rb +1 -1
  24. data/lib/rubygems/commands/fetch_command.rb +27 -8
  25. data/lib/rubygems/package/old.rb +1 -1
  26. data/lib/rubygems/package.rb +1 -1
  27. data/lib/rubygems/psych_additions.rb +1 -1
  28. data/lib/rubygems/resolver/installer_set.rb +9 -9
  29. data/lib/rubygems/safe_yaml.rb +8 -8
  30. data/lib/rubygems/security.rb +1 -1
  31. data/lib/rubygems/specification.rb +4 -4
  32. data/lib/rubygems/stub_specification.rb +0 -3
  33. data/lib/rubygems.rb +4 -11
  34. data/rubygems-update.gemspec +1 -1
  35. data/test/rubygems/helper.rb +6 -6
  36. data/test/rubygems/test_gem_commands_fetch_command.rb +97 -0
  37. data/test/rubygems/test_gem_commands_install_command.rb +16 -0
  38. data/test/rubygems/test_gem_package.rb +2 -2
  39. data/test/rubygems/test_gem_stub_specification.rb +0 -16
  40. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8b1ab86a06b30bdc5a03f3124e2e2c7ac40db3e5c5fb5d2e2ae9f42c6bfd549
4
- data.tar.gz: c885501752d796f4a2b656a537242e889c04bb1e67f1d6d21da9047225e5d89f
3
+ metadata.gz: 9648fb20873191a9544a114fb8924f9f08625fa63d590a3a0434e3b2b95b516d
4
+ data.tar.gz: b29121744e804674e10ae19f1cbc9525a8c8c0ee73072e27baf726479b995180
5
5
  SHA512:
6
- metadata.gz: bb514eb2ad2813f5ecf90fbe3ffd1c04bf5af6b34cad1b18f77da08a99c0755b18af42314c2ca1073b2d8af58db2eee81a946dd1890c5098ddaabf263cace321
7
- data.tar.gz: 978538c03440b713418a53126275355e4b0cc3bf31ea0b6574c1813fcaa8b9efe643dcde824a48b2f19eebdf706d5aeba6a10e6ae488e928cf3058f00e2c6e9a
6
+ metadata.gz: 5b8f751c2bd5a5bca0b8c7baa474ac226cb697275582681f14cb57326279e5f17db249803f33177344f7ebb199fef3c1c396c7aaf749950b3b8bb62e47b16dce
7
+ data.tar.gz: c5be5acbc735daa56571bbf4b51a1edf0271c8c6d56d7a7a403401a03863580669cdca71b9d426434701200a2cd10e20b215d1b6b17f8d1bebe4cd2bcdf91ed2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
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
+
1
23
  # 3.3.4 / 2021-12-29
2
24
 
3
25
  ## Enhancements:
data/bundler/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
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
+
1
14
  # 2.3.4 (December 29, 2021)
2
15
 
3
16
  ## Enhancements:
@@ -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-29".freeze
8
- @git_commit_sha = "2296a0d6cc".freeze
7
+ @built_at = "2022-01-12".freeze
8
+ @git_commit_sha = "a13d015fcb".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -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
@@ -309,14 +309,6 @@ module Bundler
309
309
  end
310
310
  end
311
311
 
312
- def locked_bundler_version
313
- if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
314
- new_version = Bundler::VERSION
315
- end
316
-
317
- new_version || @locked_bundler_version || Bundler::VERSION
318
- end
319
-
320
312
  def locked_ruby_version
321
313
  return unless ruby_version
322
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 },
@@ -9,46 +9,58 @@ 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
16
16
  return unless needs_switching?
17
17
 
18
- install_and_restart_with_locked_bundler
18
+ Bundler.ui.info \
19
+ "Bundler #{current_version} is running, but your lockfile was generated with #{lockfile_version}. " \
20
+ "Installing Bundler #{lockfile_version} and restarting using that version."
21
+
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)
19
38
  end
20
39
 
21
40
  private
22
41
 
23
- def install_and_restart_with_locked_bundler
24
- bundler_dep = Gem::Dependency.new("bundler", lockfile_version)
25
- spec = fetch_spec_for(bundler_dep)
26
- return if spec.nil?
42
+ def install_and_restart_with(version)
43
+ requirement = Gem::Requirement.new(version)
44
+ spec = find_latest_matching_spec(requirement)
27
45
 
28
- Bundler.ui.info \
29
- "Bundler #{current_version} is running, but your lockfile was generated with #{lockfile_version}. " \
30
- "Installing Bundler #{lockfile_version} and restarting using that version."
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
31
50
 
32
- spec.source.install(spec)
51
+ install(spec)
33
52
  rescue StandardError => e
34
53
  Bundler.ui.trace e
35
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}."
36
55
  else
37
- restart_with_locked_bundler
56
+ restart_with(version)
38
57
  end
39
58
 
40
- def fetch_spec_for(bundler_dep)
41
- source = Bundler::Source::Rubygems.new("remotes" => "https://rubygems.org")
42
- source.remote!
43
- source.add_dependency_names("bundler")
44
- spec = source.specs.search(bundler_dep).first
45
- if spec.nil?
46
- 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}"
47
- end
48
- spec
59
+ def install(spec)
60
+ spec.source.install(spec)
49
61
  end
50
62
 
51
- def restart_with_locked_bundler
63
+ def restart_with(version)
52
64
  configured_gem_home = ENV["GEM_HOME"]
53
65
  configured_gem_path = ENV["GEM_PATH"]
54
66
 
@@ -57,20 +69,79 @@ module Bundler
57
69
 
58
70
  Bundler.with_original_env do
59
71
  Kernel.exec(
60
- { "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 },
61
73
  *cmd
62
74
  )
63
75
  end
64
76
  end
65
77
 
66
78
  def needs_switching?
79
+ autoswitching_applies? &&
80
+ released?(lockfile_version) &&
81
+ !running?(lockfile_version) &&
82
+ !updating?
83
+ end
84
+
85
+ def autoswitching_applies?
67
86
  ENV["BUNDLER_VERSION"].nil? &&
68
87
  Bundler.rubygems.supports_bundler_trampolining? &&
69
88
  SharedHelpers.in_bundle? &&
70
- lockfile_version &&
71
- !lockfile_version.end_with?(".dev") &&
72
- lockfile_version != current_version &&
73
- !updating?
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")
74
145
  end
75
146
 
76
147
  def updating?
@@ -80,15 +151,18 @@ module Bundler
80
151
  def installed?
81
152
  Bundler.configure
82
153
 
83
- Bundler.rubygems.find_bundler(lockfile_version)
154
+ Bundler.rubygems.find_bundler(lockfile_version.to_s)
84
155
  end
85
156
 
86
157
  def current_version
87
- @current_version ||= Bundler::VERSION
158
+ @current_version ||= Gem::Version.new(Bundler::VERSION)
88
159
  end
89
160
 
90
161
  def lockfile_version
91
- @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
92
166
  end
93
167
  end
94
168
  end
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
27
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
28
  `git ls-files -z`.split("\x0").reject do |f|
29
- (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
29
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
30
30
  end
31
31
  end
32
32
  spec.bindir = "exe"
@@ -107,10 +107,7 @@ class Bundler::Thor
107
107
  #
108
108
  def replace!(regexp, string, force)
109
109
  content = File.read(destination)
110
- before, after = content.split(regexp, 2)
111
- snippet = (behavior == :after ? after : before).to_s
112
-
113
- if force || !snippet.include?(replacement)
110
+ if force || !content.include?(replacement)
114
111
  success = content.gsub!(regexp, string)
115
112
 
116
113
  File.open(destination, "wb") { |file| file.write(content) } unless pretend?
@@ -1,3 +1,3 @@
1
1
  class Bundler::Thor
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.1"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.3.4".freeze
4
+ VERSION = "2.3.5".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
@@ -8,7 +8,12 @@ class Gem::Commands::FetchCommand < Gem::Command
8
8
  include Gem::VersionOption
9
9
 
10
10
  def initialize
11
- super 'fetch', 'Download a gem and place it in the current directory'
11
+ defaults = {
12
+ :suggest_alternate => true,
13
+ :version => Gem::Requirement.default,
14
+ }
15
+
16
+ super 'fetch', 'Download a gem and place it in the current directory', defaults
12
17
 
13
18
  add_bulk_threshold_option
14
19
  add_proxy_option
@@ -18,6 +23,10 @@ class Gem::Commands::FetchCommand < Gem::Command
18
23
  add_version_option
19
24
  add_platform_option
20
25
  add_prerelease_option
26
+
27
+ add_option '--[no-]suggestions', 'Suggest alternates when gems are not found' do |value, options|
28
+ options[:suggest_alternate] = value
29
+ end
21
30
  end
22
31
 
23
32
  def arguments # :nodoc:
@@ -42,15 +51,27 @@ then repackaging it.
42
51
  "#{program_name} GEMNAME [GEMNAME ...]"
43
52
  end
44
53
 
54
+ def check_version # :nodoc:
55
+ if options[:version] != Gem::Requirement.default and
56
+ get_all_gem_names.size > 1
57
+ alert_error "Can't use --version with multiple gems. You can specify multiple gems with" \
58
+ " version requirements using `gem fetch 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`"
59
+ terminate_interaction 1
60
+ end
61
+ end
62
+
45
63
  def execute
46
- version = options[:version] || Gem::Requirement.default
64
+ check_version
65
+ version = options[:version]
47
66
 
48
67
  platform = Gem.platforms.last
49
- gem_names = get_all_gem_names
68
+ gem_names = get_all_gem_names_and_versions
50
69
 
51
- gem_names.each do |gem_name|
52
- dep = Gem::Dependency.new gem_name, version
70
+ gem_names.each do |gem_name, gem_version|
71
+ gem_version ||= version
72
+ dep = Gem::Dependency.new gem_name, gem_version
53
73
  dep.prerelease = options[:prerelease]
74
+ suppress_suggestions = !options[:suggest_alternate]
54
75
 
55
76
  specs_and_sources, errors =
56
77
  Gem::SpecFetcher.fetcher.spec_for_dependency dep
@@ -63,12 +84,10 @@ then repackaging it.
63
84
  spec, source = specs_and_sources.max_by {|s,| s }
64
85
 
65
86
  if spec.nil?
66
- show_lookup_failure gem_name, version, errors, options[:domain]
87
+ show_lookup_failure gem_name, gem_version, errors, suppress_suggestions, options[:domain]
67
88
  next
68
89
  end
69
-
70
90
  source.download spec
71
-
72
91
  say "Downloaded #{spec.full_name}"
73
92
  end
74
93
  end
@@ -145,7 +145,7 @@ class Gem::Package::Old < Gem::Package
145
145
 
146
146
  begin
147
147
  @spec = Gem::Specification.from_yaml yaml
148
- rescue YAML::SyntaxError
148
+ rescue Psych::SyntaxError
149
149
  raise Gem::Exception, "Failed to parse gem specification out of gem file"
150
150
  end
151
151
  rescue ArgumentError
@@ -230,7 +230,7 @@ class Gem::Package
230
230
 
231
231
  tar.add_file_signed 'checksums.yaml.gz', 0444, @signer do |io|
232
232
  gzip_to io do |gz_io|
233
- YAML.dump checksums_by_algorithm, gz_io
233
+ Psych.dump checksums_by_algorithm, gz_io
234
234
  end
235
235
  end
236
236
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # This exists just to satisfy bugs in marshal'd gemspecs that
3
- # contain a reference to YAML::PrivateType. We prune these out
3
+ # contain a reference to Psych::PrivateType. We prune these out
4
4
  # in Specification._load, but if we don't have the constant, Marshal
5
5
  # blows up.
6
6
 
@@ -76,21 +76,21 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
76
76
 
77
77
  newest = found.last
78
78
 
79
+ unless newest
80
+ exc = Gem::UnsatisfiableDependencyError.new request
81
+ exc.errors = errors
82
+
83
+ raise exc
84
+ end
85
+
79
86
  unless @force
80
87
  found_matching_metadata = found.reverse.find do |spec|
81
88
  metadata_satisfied?(spec)
82
89
  end
83
90
 
84
91
  if found_matching_metadata.nil?
85
- if newest
86
- ensure_required_ruby_version_met(newest.spec)
87
- ensure_required_rubygems_version_met(newest.spec)
88
- else
89
- exc = Gem::UnsatisfiableDependencyError.new request
90
- exc.errors = errors
91
-
92
- raise exc
93
- end
92
+ ensure_required_ruby_version_met(newest.spec)
93
+ ensure_required_rubygems_version_met(newest.spec)
94
94
  else
95
95
  newest = found_matching_metadata
96
96
  end
@@ -24,33 +24,33 @@ module Gem
24
24
  runtime
25
25
  ].freeze
26
26
 
27
- if ::YAML.respond_to? :safe_load
27
+ if ::Psych.respond_to? :safe_load
28
28
  def self.safe_load(input)
29
29
  if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
30
- ::YAML.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: true)
30
+ ::Psych.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: true)
31
31
  else
32
- ::YAML.safe_load(input, PERMITTED_CLASSES, PERMITTED_SYMBOLS, true)
32
+ ::Psych.safe_load(input, PERMITTED_CLASSES, PERMITTED_SYMBOLS, true)
33
33
  end
34
34
  end
35
35
 
36
36
  def self.load(input)
37
37
  if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
38
- ::YAML.safe_load(input, permitted_classes: [::Symbol])
38
+ ::Psych.safe_load(input, permitted_classes: [::Symbol])
39
39
  else
40
- ::YAML.safe_load(input, [::Symbol])
40
+ ::Psych.safe_load(input, [::Symbol])
41
41
  end
42
42
  end
43
43
  else
44
44
  unless Gem::Deprecate.skip
45
- warn "YAML safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0)."
45
+ warn "Psych safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0)."
46
46
  end
47
47
 
48
48
  def self.safe_load(input, *args)
49
- ::YAML.load input
49
+ ::Psych.load input
50
50
  end
51
51
 
52
52
  def self.load(input)
53
- ::YAML.load input
53
+ ::Psych.load input
54
54
  end
55
55
  end
56
56
  end
@@ -261,7 +261,7 @@ require_relative 'openssl'
261
261
  # 2. Grab the public key from the gemspec
262
262
  #
263
263
  # gem spec some_signed_gem-1.0.gem cert_chain | \
264
- # ruby -ryaml -e 'puts YAML.load($stdin)' > public_key.crt
264
+ # ruby -rpsych -e 'puts Psych.load($stdin)' > public_key.crt
265
265
  #
266
266
  # 3. Generate a SHA1 hash of the data.tar.gz
267
267
  #
@@ -225,7 +225,7 @@ class Gem::Specification < Gem::BasicSpecification
225
225
  attr_reader :version
226
226
 
227
227
  ##
228
- # A short summary of this gem's description. Displayed in `gem list -d`.
228
+ # A short summary of this gem's description. Displayed in <tt>gem list -d</tt>.
229
229
  #
230
230
  # The #description should be more detailed than the summary.
231
231
  #
@@ -271,7 +271,7 @@ class Gem::Specification < Gem::BasicSpecification
271
271
  # A list of authors for this gem.
272
272
  #
273
273
  # Alternatively, a single author can be specified by assigning a string to
274
- # `spec.author`
274
+ # +spec.author+
275
275
  #
276
276
  # Usage:
277
277
  #
@@ -1279,10 +1279,10 @@ class Gem::Specification < Gem::BasicSpecification
1279
1279
  raise TypeError, "invalid Gem::Specification format #{array.inspect}"
1280
1280
  end
1281
1281
 
1282
- # Cleanup any YAML::PrivateType. They only show up for an old bug
1282
+ # Cleanup any Psych::PrivateType. They only show up for an old bug
1283
1283
  # where nil => null, so just convert them to nil based on the type.
1284
1284
 
1285
- array.map! {|e| e.kind_of?(YAML::PrivateType) ? nil : e }
1285
+ array.map! {|e| e.kind_of?(Psych::PrivateType) ? nil : e }
1286
1286
 
1287
1287
  spec.instance_variable_set :@rubygems_version, array[0]
1288
1288
  # spec version
@@ -190,9 +190,6 @@ class Gem::StubSpecification < Gem::BasicSpecification
190
190
  end
191
191
 
192
192
  @spec ||= Gem::Specification.load(loaded_from)
193
- @spec.ignored = @ignored if @spec
194
-
195
- @spec
196
193
  end
197
194
 
198
195
  ##
data/lib/rubygems.rb CHANGED
@@ -8,7 +8,7 @@
8
8
  require 'rbconfig'
9
9
 
10
10
  module Gem
11
- VERSION = "3.3.4".freeze
11
+ VERSION = "3.3.5".freeze
12
12
  end
13
13
 
14
14
  # Must be first since it unloads the prelude from 1.9.2
@@ -606,17 +606,10 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
606
606
  def self.load_yaml
607
607
  return if @yaml_loaded
608
608
 
609
- begin
610
- # Try requiring the gem version *or* stdlib version of psych.
611
- require 'psych'
612
- rescue ::LoadError
613
- # If we can't load psych, that's fine, go on.
614
- else
615
- require_relative 'rubygems/psych_additions'
616
- require_relative 'rubygems/psych_tree'
617
- end
609
+ require 'psych'
610
+ require_relative 'rubygems/psych_additions'
611
+ require_relative 'rubygems/psych_tree'
618
612
 
619
- require 'yaml'
620
613
  require_relative 'rubygems/safe_yaml'
621
614
 
622
615
  @yaml_loaded = true
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "rubygems-update"
5
- s.version = "3.3.4"
5
+ s.version = "3.3.5"
6
6
  s.authors = ["Jim Weirich", "Chad Fowler", "Eric Hodel", "Luis Lavena", "Aaron Patterson", "Samuel Giddins", "André Arko", "Evan Phoenix", "Hiroshi SHIBATA"]
7
7
  s.email = ["", "", "drbrain@segment7.net", "luislavena@gmail.com", "aaron@tenderlovemaking.com", "segiddins@segiddins.me", "andre@arko.net", "evan@phx.io", "hsbt@ruby-lang.org"]
8
8
 
@@ -685,10 +685,10 @@ class Gem::TestCase < Test::Unit::TestCase
685
685
  # Load a YAML string, the psych 3 way
686
686
 
687
687
  def load_yaml(yaml)
688
- if YAML.respond_to?(:unsafe_load)
689
- YAML.unsafe_load(yaml)
688
+ if Psych.respond_to?(:unsafe_load)
689
+ Psych.unsafe_load(yaml)
690
690
  else
691
- YAML.load(yaml)
691
+ Psych.load(yaml)
692
692
  end
693
693
  end
694
694
 
@@ -696,10 +696,10 @@ class Gem::TestCase < Test::Unit::TestCase
696
696
  # Load a YAML file, the psych 3 way
697
697
 
698
698
  def load_yaml_file(file)
699
- if YAML.respond_to?(:unsafe_load_file)
700
- YAML.unsafe_load_file(file)
699
+ if Psych.respond_to?(:unsafe_load_file)
700
+ Psych.unsafe_load_file(file)
701
701
  else
702
- YAML.load_file(file)
702
+ Psych.load_file(file)
703
703
  end
704
704
  end
705
705
 
@@ -157,4 +157,101 @@ class TestGemCommandsFetchCommand < Gem::TestCase
157
157
  assert_path_exist(File.join(@tempdir, a1.file_name),
158
158
  "#{a1.full_name} not fetched")
159
159
  end
160
+
161
+ def test_execute_version_specified_by_colon
162
+ specs = spec_fetcher do |fetcher|
163
+ fetcher.gem 'a', 1
164
+ end
165
+
166
+ @cmd.options[:args] = %w[a:1]
167
+
168
+ use_ui @ui do
169
+ Dir.chdir @tempdir do
170
+ @cmd.execute
171
+ end
172
+ end
173
+
174
+ a1 = specs['a-1']
175
+
176
+ assert_path_exist(File.join(@tempdir, a1.file_name),
177
+ "#{a1.full_name} not fetched")
178
+ end
179
+
180
+ def test_execute_two_version
181
+ @cmd.options[:args] = %w[a b]
182
+ @cmd.options[:version] = Gem::Requirement.new '1'
183
+
184
+ use_ui @ui do
185
+ assert_raise Gem::MockGemUi::TermError, @ui.error do
186
+ @cmd.execute
187
+ end
188
+ end
189
+
190
+ msg = "ERROR: Can't use --version with multiple gems. You can specify multiple gems with" \
191
+ " version requirements using `gem fetch 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`"
192
+
193
+ assert_empty @ui.output
194
+ assert_equal msg, @ui.error.chomp
195
+ end
196
+
197
+ def test_execute_two_version_specified_by_colon
198
+ specs = spec_fetcher do |fetcher|
199
+ fetcher.gem 'a', 1
200
+ fetcher.gem 'b', 1
201
+ end
202
+
203
+ @cmd.options[:args] = %w[a:1 b:1]
204
+
205
+ use_ui @ui do
206
+ Dir.chdir @tempdir do
207
+ @cmd.execute
208
+ end
209
+ end
210
+
211
+ a1 = specs['a-1']
212
+ b1 = specs['b-1']
213
+
214
+ assert_path_exist(File.join(@tempdir, a1.file_name),
215
+ "#{a1.full_name} not fetched")
216
+ assert_path_exist(File.join(@tempdir, b1.file_name),
217
+ "#{b1.full_name} not fetched")
218
+ end
219
+
220
+ def test_execute_version_nonexistent
221
+ spec_fetcher do |fetcher|
222
+ fetcher.spec 'foo', 1
223
+ end
224
+
225
+ @cmd.options[:args] = %w[foo:2]
226
+
227
+ use_ui @ui do
228
+ @cmd.execute
229
+ end
230
+
231
+ expected = <<-EXPECTED
232
+ ERROR: Could not find a valid gem 'foo' (2) in any repository
233
+ ERROR: Possible alternatives: foo
234
+ EXPECTED
235
+
236
+ assert_equal expected, @ui.error
237
+ end
238
+
239
+ def test_execute_nonexistent_hint_disabled
240
+ spec_fetcher do |fetcher|
241
+ fetcher.spec 'foo', 1
242
+ end
243
+
244
+ @cmd.options[:args] = %w[foo:2]
245
+ @cmd.options[:suggest_alternate] = false
246
+
247
+ use_ui @ui do
248
+ @cmd.execute
249
+ end
250
+
251
+ expected = <<-EXPECTED
252
+ ERROR: Could not find a valid gem 'foo' (2) in any repository
253
+ EXPECTED
254
+
255
+ assert_equal expected, @ui.error
256
+ end
160
257
  end
@@ -277,6 +277,22 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
277
277
  assert_match(/ould not find a valid gem 'nonexistent'/, @ui.error)
278
278
  end
279
279
 
280
+ def test_execute_nonexistent_force
281
+ spec_fetcher
282
+
283
+ @cmd.options[:args] = %w[nonexistent]
284
+ @cmd.options[:force] = true
285
+
286
+ use_ui @ui do
287
+ e = assert_raise Gem::MockGemUi::TermError do
288
+ @cmd.execute
289
+ end
290
+ assert_equal 2, e.exit_code
291
+ end
292
+
293
+ assert_match(/ould not find a valid gem 'nonexistent'/, @ui.error)
294
+ end
295
+
280
296
  def test_execute_dependency_nonexistent
281
297
  spec_fetcher do |fetcher|
282
298
  fetcher.spec 'foo', 2, 'bar' => '0.5'
@@ -822,7 +822,7 @@ class TestGemPackage < Gem::Package::TarTestCase
822
822
  }
823
823
  tar.add_file 'checksums.yaml.gz', 0444 do |io|
824
824
  Zlib::GzipWriter.wrap io do |gz_io|
825
- gz_io.write YAML.dump bogus_checksums
825
+ gz_io.write Psych.dump bogus_checksums
826
826
  end
827
827
  end
828
828
  end
@@ -868,7 +868,7 @@ class TestGemPackage < Gem::Package::TarTestCase
868
868
 
869
869
  tar.add_file 'checksums.yaml.gz', 0444 do |io|
870
870
  Zlib::GzipWriter.wrap io do |gz_io|
871
- gz_io.write YAML.dump checksums
871
+ gz_io.write Psych.dump checksums
872
872
  end
873
873
  end
874
874
 
@@ -180,22 +180,6 @@ class TestStubSpecification < Gem::TestCase
180
180
  assert bar.to_spec
181
181
  end
182
182
 
183
- def test_to_spec_activated
184
- assert @foo.to_spec.is_a?(Gem::Specification)
185
- assert_equal "foo", @foo.to_spec.name
186
- refute @foo.to_spec.instance_variable_get :@ignored
187
- end
188
-
189
- def test_to_spec_missing_extensions
190
- stub = stub_with_extension
191
-
192
- capture_output do
193
- stub.contains_requirable_file? 'nonexistent'
194
- end
195
-
196
- assert stub.to_spec.instance_variable_get :@ignored
197
- end
198
-
199
183
  def stub_with_version
200
184
  spec = File.join @gemhome, 'specifications', 'stub_e-2.gemspec'
201
185
  File.open spec, 'w' do |io|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubygems-update
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.4
4
+ version: 3.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Weirich
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2021-12-29 00:00:00.000000000 Z
19
+ date: 2022-01-12 00:00:00.000000000 Z
20
20
  dependencies: []
21
21
  description: |-
22
22
  A package (also known as a library) contains a set of functionality
@@ -804,7 +804,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
804
804
  - !ruby/object:Gem::Version
805
805
  version: '0'
806
806
  requirements: []
807
- rubygems_version: 3.3.4
807
+ rubygems_version: 3.3.5
808
808
  signing_key:
809
809
  specification_version: 4
810
810
  summary: RubyGems is a package management framework for Ruby.