rubygems-update 3.3.4 → 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 (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.