[rubygems/rubygems] Fix generic platform gems getting incorrectly removed when locked for a specific platform

If they are already in the lockfile as the most specific variant for a
platform, we shouldn't change that unless explicitly unlocking.

https://github.com/rubygems/rubygems/commit/a901660498
This commit is contained in:
David Rodríguez 2024-07-04 18:22:03 +02:00 committed by git
parent e6c7a309d0
commit 140d8318db
4 changed files with 107 additions and 2 deletions

View File

@ -46,13 +46,18 @@ module Bundler
end
module_function :platform_specificity_match
def select_best_platform_match(specs, platform, force_ruby: false)
def select_best_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
matching = if force_ruby
specs.select {|spec| spec.match_platform(Gem::Platform::RUBY) && spec.force_ruby_platform! }
else
specs.select {|spec| spec.match_platform(platform) }
end
if prefer_locked
locked_originally = matching.select {|spec| spec.is_a?(LazySpecification) }
return locked_originally if locked_originally.any?
end
sort_best_platform_match(matching, platform)
end
module_function :select_best_platform_match

View File

@ -255,7 +255,7 @@ module Bundler
results = filter_matching_specs(results, locked_requirement) if locked_requirement
results.group_by(&:version).reduce([]) do |groups, (version, specs)|
platform_specs = package.platforms.map {|platform| select_best_platform_match(specs, platform) }
platform_specs = package.platform_specs(specs)
# If package is a top-level dependency,
# candidate is only valid if there are matching versions for all resolution platforms.

View File

@ -25,6 +25,10 @@ module Bundler
@prerelease = @dependency.prerelease? || @locked_version&.prerelease? || prerelease ? :consider_first : :ignore
end
def platform_specs(specs)
platforms.map {|platform| GemHelpers.select_best_platform_match(specs, platform, prefer_locked: !unlock?) }
end
def to_s
@name.delete("\0")
end

View File

@ -1521,6 +1521,102 @@ RSpec.describe "bundle install with specific platforms" do
end
end
it "does not remove generic platform gems locked for a specific platform from lockfile when unlocking an unrelated gem" do
build_repo4 do
build_gem "ffi"
build_gem "ffi" do |s|
s.platform = "x86_64-linux"
end
build_gem "nokogiri"
end
gemfile <<~G
source "https://gem.repo4"
gem "ffi"
gem "nokogiri"
G
original_lockfile = <<~L
GEM
remote: https://gem.repo4/
specs:
ffi (1.0)
nokogiri (1.0)
PLATFORMS
x86_64-linux
DEPENDENCIES
ffi
nokogiri
BUNDLED WITH
#{Bundler::VERSION}
L
lockfile original_lockfile
simulate_platform "x86_64-linux" do
bundle "lock --update nokogiri"
expect(lockfile).to eq(original_lockfile)
end
end
it "does not remove generic platform gems locked for a specific platform from lockfile when unlocking an unrelated gem, and variants for other platform also locked" do
build_repo4 do
build_gem "ffi"
build_gem "ffi" do |s|
s.platform = "x86_64-linux"
end
build_gem "ffi" do |s|
s.platform = "java"
end
build_gem "nokogiri"
end
gemfile <<~G
source "https://gem.repo4"
gem "ffi"
gem "nokogiri"
G
original_lockfile = <<~L
GEM
remote: https://gem.repo4/
specs:
ffi (1.0)
ffi (1.0-java)
nokogiri (1.0)
PLATFORMS
java
x86_64-linux
DEPENDENCIES
ffi
nokogiri
BUNDLED WITH
#{Bundler::VERSION}
L
lockfile original_lockfile
simulate_platform "x86_64-linux" do
bundle "lock --update nokogiri"
expect(lockfile).to eq(original_lockfile)
end
end
private
def setup_multiplatform_gem