diff options
| author | David RodrÃguez <deivid.rodriguez@riseup.net> | 2025-04-10 21:03:44 +0200 |
|---|---|---|
| committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2025-04-14 16:17:50 +0900 |
| commit | ce2640dde8c65d9e11c3bc2249c5cd5bb7d0dbce (patch) | |
| tree | a7d2524105deeb67b963fa35d4890d04042ba70a | |
| parent | 66aa7139800e7ab5ef7d7a1b0dec73789936e672 (diff) | |
[rubygems/rubygems] Fix edge case making `bundle update` behave incorrectly
If both a native and a generic version are locked, but the native
version is incompatible with the running Ruby, Bundler will still keep
the native version in the lockfile, since it could be potentially useful
when using other rubies.
However, when `bundle update` is run, this was not the case because the
locked native gems were not using the right source when materializing.
They were using the lockfile source instead of the Gemfile source, and
that meant they could not be found when materializing, because the
lockfile source always uses local mode so does not see them.
The effect of this was normally that they were incorrectly removed from
the lockfile and a strange "this spec has been possibly yanked" was
printed in verbose mode. However, in certain situations (i.e., when the
generic gem would bring extra dependencies), it could also make `bundle
update` crash.
The solution is, when adding this extra locked specs to the result after
resolving, maybe sure they inherit the source from the resolved specs,
so they can be found when materializing.
`bundle install` did not have the issue because it passes locked specs
to the resolver, and assigns the right source to them in
`Definition#converge_locked_specs`.
https://github.com/rubygems/rubygems/commit/91ce881fda
| -rw-r--r-- | lib/bundler/spec_set.rb | 15 | ||||
| -rw-r--r-- | spec/bundler/install/gems/resolving_spec.rb | 11 |
2 files changed, 22 insertions, 4 deletions
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 5abbaaeb4b..65c9c6e73e 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -181,7 +181,7 @@ module Bundler end def version_for(name) - self[name].first&.version + exemplary_spec(name)&.version end def what_required(spec) @@ -286,8 +286,13 @@ module Bundler end def additional_variants_from(other) - other.select do |spec| - version_for(spec.name) == spec.version && valid_dependencies?(spec) + other.select do |other_spec| + spec = exemplary_spec(other_spec.name) + next unless spec + + selected = spec.version == other_spec.version && valid_dependencies?(other_spec) + other_spec.source = spec.source if selected + selected end end @@ -364,5 +369,9 @@ module Bundler hash[key] ||= [] hash[key] << value end + + def exemplary_spec(name) + self[name].first + end end end diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb index eb6e5aa995..d5335e25bf 100644 --- a/spec/bundler/install/gems/resolving_spec.rb +++ b/spec/bundler/install/gems/resolving_spec.rb @@ -540,7 +540,7 @@ RSpec.describe "bundle install with install-time dependencies" do lockfile original_lockfile end - it "keeps both variants in the lockfile, and uses the generic one since it's compatible" do + it "keeps both variants in the lockfile when installing, and uses the generic one since it's compatible" do simulate_platform "x86_64-linux" do bundle "install --verbose" @@ -548,6 +548,15 @@ RSpec.describe "bundle install with install-time dependencies" do expect(the_bundle).to include_gems("nokogiri 1.16.3") end end + + it "keeps both variants in the lockfile when updating, and uses the generic one since it's compatible" do + simulate_platform "x86_64-linux" do + bundle "update --verbose" + + expect(lockfile).to eq(original_lockfile) + expect(the_bundle).to include_gems("nokogiri 1.16.3") + end + end end it "gives a meaningful error on ruby version mismatches between dependencies" do |
