[rubygems/rubygems] Resolve all platforms directly

Instead of having to do a complete pass after resolve.

To do this, we add to the ruby group all the platform specs with the
same dependencies as the ruby specs.

https://github.com/rubygems/rubygems/commit/e50415f2a6
This commit is contained in:
David Rodríguez 2024-07-04 13:55:52 +02:00 committed by git
parent 00acc70348
commit dd05191bc3
7 changed files with 63 additions and 34 deletions

View File

@ -638,8 +638,6 @@ module Bundler
@platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
result.complete_platforms!(platforms)
SpecSet.new(result.for(dependencies, false, @platforms))
end

View File

@ -79,7 +79,8 @@ module Bundler
def solve_versions(root:, logger:)
solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
result = solver.solve
result.map {|package, version| version.to_specs(package) }.flatten
resolved_specs = result.map {|package, version| version.to_specs(package) }.flatten
resolved_specs |= @base.specs_compatible_with(SpecSet.new(resolved_specs))
rescue PubGrub::SolveFailure => e
incompatibility = e.incompatibility
@ -269,15 +270,22 @@ module Bundler
next groups if platform_specs.all?(&:empty?)
end
platform_specs.flatten!
platform_specs.uniq!
ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
groups << Resolver::Candidate.new(version, specs: ruby_specs, priority: -1) if ruby_specs.any?
ruby_group = Resolver::SpecGroup.new(ruby_specs)
next groups if platform_specs == ruby_specs || package.force_ruby_platform?
unless ruby_group.empty?
platform_specs.each do |specs|
ruby_group.merge(Resolver::SpecGroup.new(specs))
end
groups << Resolver::Candidate.new(version, specs: platform_specs, priority: 1)
groups << Resolver::Candidate.new(version, group: ruby_group, priority: -1)
next groups if package.force_ruby_platform?
end
platform_group = Resolver::SpecGroup.new(platform_specs.flatten.uniq)
next groups if platform_group == ruby_group
groups << Resolver::Candidate.new(version, group: platform_group, priority: 1)
groups
end

View File

@ -30,6 +30,10 @@ module Bundler
end.compact
end
def specs_compatible_with(result)
@base.specs_compatible_with(result)
end
def [](name)
@base[name]
end

View File

@ -24,8 +24,8 @@ module Bundler
attr_reader :version
def initialize(version, specs: [], priority: -1)
@spec_group = Resolver::SpecGroup.new(specs)
def initialize(version, group: nil, priority: -1)
@spec_group = group || SpecGroup.new([])
@version = Gem::Version.new(version)
@priority = priority
end

View File

@ -3,6 +3,8 @@
module Bundler
class Resolver
class SpecGroup
attr_reader :specs
def initialize(specs)
@specs = specs
end
@ -38,7 +40,19 @@ module Bundler
def dependencies
@dependencies ||= @specs.map do |spec|
__dependencies(spec) + metadata_dependencies(spec)
end.flatten.uniq
end.flatten.uniq.sort
end
def ==(other)
sorted_spec_names == other.sorted_spec_names
end
def merge(other)
return false unless equivalent?(other)
@specs |= other.specs
true
end
protected
@ -49,6 +63,10 @@ module Bundler
private
def equivalent?(other)
name == other.name && version == other.version && source == other.source && dependencies == other.dependencies
end
def exemplary_spec
@specs.first
end

View File

@ -71,12 +71,6 @@ module Bundler
platforms
end
def complete_platforms!(platforms)
platforms.each do |platform|
complete_platform(platform)
end
end
def validate_deps(s)
s.runtime_dependencies.each do |dep|
next if dep.name == "bundler"
@ -158,6 +152,12 @@ module Bundler
@specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
end
def specs_compatible_with(other)
select do |spec|
other.valid?(spec)
end
end
def delete_by_name(name)
@specs.reject! {|spec| spec.name == name }
@ -195,6 +195,10 @@ module Bundler
lookup.keys
end
def valid?(s)
s.matches_current_metadata? && valid_dependencies?(s)
end
private
def reset!
@ -209,7 +213,7 @@ module Bundler
spec = specs.first
matching_specs = spec.source.specs.search([spec.name, spec.version])
platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
s.matches_current_metadata? && valid_dependencies?(s)
valid?(s)
end
if platform_spec

View File

@ -1470,22 +1470,19 @@ RSpec.describe "bundle lock" do
expected_error = <<~ERR.strip
Could not find compatible versions
Because every version of activemodel depends on activesupport = 6.0.4
and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
every version of activemodel is incompatible with rails >= 7.0.2.3, < 7.0.3.1.
And because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
rails >= 7.0.2.3, < 7.0.3.1 cannot be used.
(1) So, because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
and rails >= 7.0.4 depends on activemodel = 7.0.4,
rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4.
Because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1,
rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 or activesupport = 7.0.3.1.
And because rails >= 7.0.4 depends on activesupport = 7.0.4
Because rails >= 7.0.4 depends on activemodel = 7.0.4
and rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1,
rails >= 7.0.3.1 requires activemodel = 7.0.3.1 OR = 7.0.4.
(1) So, because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
and every version of activemodel depends on activesupport = 6.0.4,
activemodel != 7.0.2.3 is incompatible with rails >= 7.0.2.3.
And because rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4 (1),
rails >= 7.0.2.3 requires activesupport = 6.0.4.
Because rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3
and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1,
rails >= 7.0.2.3, < 7.0.4 requires activesupport = 7.0.2.3 OR = 7.0.3.1.
And because rails >= 7.0.4 depends on activesupport = 7.0.4,
rails >= 7.0.2.3 requires activesupport = 7.0.2.3 OR = 7.0.3.1 OR = 7.0.4.
And because rails >= 7.0.2.3 requires activesupport = 6.0.4 (1),
rails >= 7.0.2.3 cannot be used.
So, because Gemfile depends on rails >= 7.0.2.3,
version solving has failed.