[rubygems/rubygems] Fix resolver hangs when dealing with an incomplete lockfile

While working on locking multiple platforms by default, I got an
infinite resolution loop in one of our resolver specs.

The culprit ended up being that when dealing with lockfile specs with
incomplete dependencies (spec appears in lockfile, but its dependencies
don't), those specs were not being properly expired and that tripped up
resolution.

The issue for some reason only manifests when dealing with multiple
lockfile platforms, that's why it only manifested when working on
locking multiple platforms by default.

https://github.com/rubygems/rubygems/commit/4ca72913bb
This commit is contained in:
David Rodríguez 2023-03-16 17:45:54 +01:00 committed by Hiroshi SHIBATA
parent c257380965
commit f3d69bed62
No known key found for this signature in database
GPG Key ID: F9CF13417264FAC2
4 changed files with 35 additions and 6 deletions

View File

@ -668,9 +668,17 @@ module Bundler
def check_missing_lockfile_specs
all_locked_specs = @locked_specs.map(&:name) << "bundler"
@locked_specs.any? do |s|
missing = @locked_specs.select do |s|
s.dependencies.any? {|dep| !all_locked_specs.include?(dep.name) }
end
if missing.any?
@locked_specs.delete(missing)
true
else
false
end
end
def converge_paths

View File

@ -35,9 +35,7 @@ module Bundler
end
def delete(specs)
specs.each do |spec|
@base.delete(spec)
end
@base.delete(specs)
end
def get_package(name)

View File

@ -63,8 +63,8 @@ module Bundler
@sorted = nil
end
def delete(spec)
@specs.delete(spec)
def delete(specs)
specs.each {|spec| @specs.delete(spec) }
@lookup = nil
@sorted = nil
end

View File

@ -1008,6 +1008,29 @@ RSpec.describe "bundle lock" do
So, because Gemfile depends on rails >= 7.0.2.3,
version solving has failed.
ERR
lockfile lockfile.gsub(/PLATFORMS\n #{lockfile_platforms}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
bundle "lock", :raise_on_error => false
expect(err).to eq <<~ERR.strip
Could not find compatible versions
Because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
and rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 OR = 7.0.3.1.
And because every version of activemodel depends on activesupport = 6.0.4,
rails >= 7.0.2.3, < 7.0.4 requires activesupport = 6.0.4.
Because rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1
and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
rails >= 7.0.2.3, < 7.0.4 requires activesupport = 7.0.2.3 OR = 7.0.3.1.
Thus, rails >= 7.0.2.3, < 7.0.4 cannot be used.
And because rails >= 7.0.4 depends on activemodel = 7.0.4,
rails >= 7.0.2.3 requires activemodel = 7.0.4.
So, because activemodel = 7.0.4 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally
and Gemfile depends on rails >= 7.0.2.3,
version solving has failed.
ERR
end
it "does not accidentally resolves to prereleases" do