diff options
author | David RodrÃguez <[email protected]> | 2024-10-08 20:01:25 +0200 |
---|---|---|
committer | git <[email protected]> | 2024-10-10 14:54:04 +0000 |
commit | d12c8cbf14084c35209a9cb07bccc8b4bee7760a (patch) | |
tree | 6c24650c75e41c1c528d32111ed5030ee3ed5451 | |
parent | 36e9a6bb41621793f6719c6e269ffebb422636fe (diff) |
[rubygems/rubygems] Fix `gem pristine etc` resetting gem twice sometimes
If a default version and a regular version of etc are present at the
same time, RubyGems will end up duplicating work and running pristine
twice.
The `etc` gem is special because it's loaded by RubyGems by default.
When doing this, RubyGems will activate the regularly installed version.
The when `gem pristine` runs, it will find to installed specifications
but materialize both to the already activated specification.
Before:
```
$ gem pristine etc --version 1.4.3
Restoring gems to pristine condition...
Building native extensions. This could take a while...
Restored etc-1.4.3
Building native extensions. This could take a while...
Restored etc-1.4.3
```
After:
```
$ gem pristine etc --version 1.4.3
Restoring gems to pristine condition...
Skipped etc-1.4.3, it is a default gem
Building native extensions. This could take a while...
Restored etc-1.4.3
```
https://github.com/rubygems/rubygems/commit/5c279ac56b
-rw-r--r-- | lib/rubygems/basic_specification.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/stub_specification.rb | 21 | ||||
-rw-r--r-- | test/rubygems/test_gem_stub_specification.rb | 29 |
3 files changed, 41 insertions, 11 deletions
diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb index ccd3e49cea..8c75fd41d4 100644 --- a/lib/rubygems/basic_specification.rb +++ b/lib/rubygems/basic_specification.rb @@ -100,7 +100,7 @@ class Gem::BasicSpecification end def default_gem? - loaded_from && + !loaded_from.nil? && File.dirname(loaded_from) == Gem.default_specifications_dir end diff --git a/lib/rubygems/stub_specification.rb b/lib/rubygems/stub_specification.rb index ea66fbc3f6..4f6a70ba4b 100644 --- a/lib/rubygems/stub_specification.rb +++ b/lib/rubygems/stub_specification.rb @@ -83,11 +83,7 @@ class Gem::StubSpecification < Gem::BasicSpecification # True when this gem has been activated def activated? - @activated ||= - begin - loaded = Gem.loaded_specs[name] - loaded && loaded.version == version - end + @activated ||= !loaded_spec.nil? end def default_gem? @@ -187,11 +183,7 @@ class Gem::StubSpecification < Gem::BasicSpecification # The full Gem::Specification for this gem, loaded from evalling its gemspec def spec - @spec ||= if @data - loaded = Gem.loaded_specs[name] - loaded if loaded && loaded.version == version - end - + @spec ||= loaded_spec if @data @spec ||= Gem::Specification.load(loaded_from) end alias_method :to_spec, :spec @@ -231,4 +223,13 @@ class Gem::StubSpecification < Gem::BasicSpecification def sort_obj # :nodoc: [name, version, Gem::Platform.sort_priority(platform)] end + + private + + def loaded_spec + spec = Gem.loaded_specs[name] + return unless spec && spec.version == version && spec.default_gem? == default_gem? + + spec + end end diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb index 471fb6bbb2..4b2d4c570a 100644 --- a/test/rubygems/test_gem_stub_specification.rb +++ b/test/rubygems/test_gem_stub_specification.rb @@ -171,6 +171,35 @@ class TestStubSpecification < Gem::TestCase assert_same real_foo, @foo.to_spec end + def test_to_spec_default + bar_default_spec = File.join(@gemhome, "specifications", "default", "bar-0.0.2.gemspec") + File.open bar_default_spec, "w" do |io| + io.write <<~STUB + # -*- encoding: utf-8 -*- + # stub: bar 0.0.2 ruby lib + + Gem::Specification.new do |s| + s.name = "bar" + s.version = "0.0.2" + s.platform = "ruby" + s.require_paths = ["lib"] + s.summary = "A very bar gem" + end + STUB + end + + bar = Gem::StubSpecification.gemspec_stub BAR, @base_dir, @gems_dir + bar_default = Gem::StubSpecification.default_gemspec_stub bar_default_spec, @base_dir, @gems_dir + + real_bar = util_spec bar_default.name, bar_default.version + real_bar.activate + + assert_equal bar.version, Gem.loaded_specs[bar.name].version, + "sanity check" + + refute_same real_bar, bar_default.to_spec + end + def test_to_spec_with_other_specs_loaded_does_not_warn real_foo = util_spec @foo.name, @foo.version real_foo.activate |