[前][次][番号順一覧][スレッド一覧]

ruby-changes:72537

From: David <ko1@a...>
Date: Thu, 14 Jul 2022 04:48:09 +0900 (JST)
Subject: [ruby-changes:72537] 8c74eaa08d (master): [rubygems/rubygems] Fix `gem update --system` crash while regenerating binstubs

https://git.ruby-lang.org/ruby.git/commit/?id=8c74eaa08d

From 8c74eaa08d25355560550787e38da079f1929abf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Rodr=C3=ADguez?= <deivid.rodriguez@r...>
Date: Wed, 13 Jul 2022 19:10:47 +0200
Subject: [rubygems/rubygems] Fix `gem update --system` crash while
 regenerating binstubs

Since a few commits ago, we no longer call `Gem::Specification.reset`
after each invocation of `Gem::Installer#install`. This means we don't
call it when the default Bundler is installed during `gem update
--system`. This causes no issues until the end of the upgrade process
when:

* The previous default Bundler spec is removed from disk.
* All specification stubs are turned into real specifications by loading
  them from disk. But the one for Bundler no longer exists so
  materializes to `nil` and regenerating binstubs crashes like this:

  ```
  Bundler 2.4.0.dev installed
  RubyGems 3.4.0.dev installed
  Regenerating binstubs
  ERROR:  While executing gem ... (NoMethodError)
      undefined method `platform' for nil:NilClass
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/commands/pristine_command.rb:116:in `block in execute'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/specification.rb:981:in `block in each'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/specification.rb:980:in `each'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/specification.rb:980:in `each'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/commands/pristine_command.rb:116:in `map'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/commands/pristine_command.rb:116:in `each'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/commands/pristine_command.rb:116:in `select'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/commands/pristine_command.rb:116:in `execute'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/command.rb:323:in `invoke_with_build_args'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/command.rb:301:in `invoke'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/commands/setup_command.rb:604:in `regenerate_binstubs'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/commands/setup_command.rb:183:in `execute'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/command.rb:323:in `invoke_with_build_args'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/command_manager.rb:185:in `process_args'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/command_manager.rb:149:in `run'
    /Users/deivid/Code/rubygems/rubygems/lib/rubygems/gem_runner.rb:51:in `run'
  setup.rb:33:in `<main>'
  ```

We fix it by more carefully managing the removal of the previous default
Bundler gem.

https://github.com/rubygems/rubygems/commit/9989f6d5af
---
 lib/rubygems/commands/setup_command.rb | 9 +++++----
 lib/rubygems/specification.rb          | 9 +++++++++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb
index 84e9210cfb..35b500936d 100644
--- a/lib/rubygems/commands/setup_command.rb
+++ b/lib/rubygems/commands/setup_command.rb
@@ -365,10 +365,11 @@ By default, this RubyGems will install gem as: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/setup_command.rb#L365
 
     bundler_spec = Dir.chdir("bundler") { Gem::Specification.load("bundler.gemspec") }
 
-    # Remove bundler-*.gemspec in default specification directory.
-    Dir.entries(specs_dir).
-      select {|gs| gs.start_with?("bundler-") }.
-      each {|gs| File.delete(File.join(specs_dir, gs)) }
+    current_default_spec = Gem::Specification.default_stubs.find {|s| s.name == "bundler" }
+    if current_default_spec
+      File.delete(current_default_spec.loaded_from)
+      Gem::Specification.remove_spec current_default_spec
+    end
 
     default_spec_path = File.join(specs_dir, "#{bundler_spec.full_name}.gemspec")
     Gem.write_binary(default_spec_path, bundler_spec.to_ruby)
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index f6704cbc17..edabcf392a 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -897,6 +897,15 @@ class Gem::Specification < Gem::BasicSpecification https://github.com/ruby/ruby/blob/trunk/lib/rubygems/specification.rb#L897
     _resort!(stubs)
   end
 
+  ##
+  # Removes +spec+ from the known specs.
+
+  def self.remove_spec(spec)
+    _all.delete spec.to_spec
+    stubs.delete spec
+    (@@stubs_by_name[spec.name] || []).delete spec
+  end
+
   ##
   # Returns all specifications. This method is discouraged from use.
   # You probably want to use one of the Enumerable methods instead.
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]