summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Rodríguez <deivid.rodriguez@riseup.net>2025-01-09 21:34:29 +0100
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2025-01-14 12:24:37 +0900
commit0b1b8bc3ec08de6944e6784de1ea5e03e90d8dba (patch)
treee80f982ef9fda23e3f5b2de553d6a65a4cb289f7
parent5c83d09ec874db44f6a69d8f81952f31a811013d (diff)
[rubygems/rubygems] Don't remove platform specific variants from the lockfile unless necessary
Even if they don't match the current Ruby version, they could still work in other rubies. So it's better to keep them. https://github.com/rubygems/rubygems/commit/9a3e583b0c
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/12568
-rw-r--r--lib/bundler/definition.rb2
-rw-r--r--lib/bundler/resolver.rb3
-rw-r--r--lib/bundler/resolver/base.rb3
-rw-r--r--lib/bundler/spec_set.rb10
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb46
5 files changed, 60 insertions, 4 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index fd81fe2aa3..c31682ce4e 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -742,7 +742,7 @@ module Bundler
@platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
- SpecSet.new(result.for(dependencies, @platforms))
+ SpecSet.new(result.for(dependencies, @platforms | [Gem::Platform::RUBY]))
end
def precompute_source_requirements_for_indirect_dependencies?
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 54e25a2adc..56a6c7ac67 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -80,7 +80,8 @@ module Bundler
def solve_versions(root:, logger:)
solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
result = solver.solve
- result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
+ resolved_specs = result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
+ SpecSet.new(resolved_specs).specs_with_additional_variants_from(@base.locked_specs)
rescue PubGrub::SolveFailure => e
incompatibility = e.incompatibility
diff --git a/lib/bundler/resolver/base.rb b/lib/bundler/resolver/base.rb
index f7d15a3024..932a92ff41 100644
--- a/lib/bundler/resolver/base.rb
+++ b/lib/bundler/resolver/base.rb
@@ -5,10 +5,11 @@ require_relative "package"
module Bundler
class Resolver
class Base
- attr_reader :packages, :requirements, :source_requirements
+ attr_reader :packages, :requirements, :source_requirements, :locked_specs
def initialize(source_requirements, dependencies, base, platforms, options)
@source_requirements = source_requirements
+ @locked_specs = options[:locked_specs]
@base = base
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index 994c3d29d2..f0082d46d5 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -163,6 +163,10 @@ module Bundler
@specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
end
+ def specs_with_additional_variants_from(other)
+ sorted | additional_variants_from(other)
+ end
+
def delete_by_name(name)
@specs.reject! {|spec| spec.name == name }
@@ -277,6 +281,12 @@ module Bundler
@specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq
end
+ def additional_variants_from(other)
+ other.select do |spec|
+ version_for(spec.name) == spec.version && valid_dependencies?(spec)
+ end
+ end
+
def valid_dependencies?(s)
validate_deps(s) == :valid
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index dc9bbd1144..04495e2b72 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -1121,7 +1121,7 @@ RSpec.describe "bundle install with specific platforms" do
bundle :install
end
- it "automatically fixes the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
+ it "automatically adds the ruby variant to the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
#
# Given an existing application using native gems (e.g., nokogiri)
# And a lockfile generated with a stable ruby version
@@ -1167,6 +1167,7 @@ RSpec.describe "bundle install with specific platforms" do
checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "nokogiri", "1.14.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
end
expect(lockfile).to eq(<<~L)
@@ -1174,6 +1175,7 @@ RSpec.describe "bundle install with specific platforms" do
remote: https://gem.repo4/
specs:
nokogiri (1.14.0)
+ nokogiri (1.14.0-x86_64-linux)
PLATFORMS
x86_64-linux
@@ -1699,6 +1701,48 @@ RSpec.describe "bundle install with specific platforms" do
end
end
+ it "does not remove platform specific gems from lockfile when using a ruby version that does not match their ruby requirements, since they may be useful in other rubies" do
+ build_repo4 do
+ build_gem("google-protobuf", "3.25.5")
+ build_gem("google-protobuf", "3.25.5") do |s|
+ s.required_ruby_version = "< #{current_ruby_minor}.dev"
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "google-protobuf", "~> 3.0"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ google-protobuf (3.25.5)
+ google-protobuf (3.25.5-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ google-protobuf (~> 3.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update"
+ end
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+
private
def setup_multiplatform_gem