summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Rodríguez <deivid.rodriguez@riseup.net>2022-05-09 10:40:23 +0200
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2022-09-05 11:43:14 +0900
commitf7cf641469161c3770b58f79e08e312512212aa8 (patch)
tree3c3ee30585b64d5ef42e04eda0ffcb44b22290e3
parent1420333455ba335f46887ee7a06c4ee95faa37ad (diff)
downloadruby-f7cf641469161c3770b58f79e08e312512212aa8.tar.gz
[rubygems/rubygems] Fix resolution hanging on musl platforms
After recent musl support was added, Bundler started hanging in musl platforms. I identified the issue where valid candidates were being filtered out because their platform was specified as a string, and thus `Gem::Platform.match_spec?` which under the hood ends up calling `Gem::Platform#===` would return `nil`, because it does not support comparing platforms to strings. In particular, `Bundler::EndpointSpecification`'s platform coming from the API was not instantiated as a `Gem::Platform`, hence the issue. Also, this spec surfaced another issue where a bug corrected in `Gem::Platform#match_platforms` had not been yet backported to Bundler. So this commit also backports that to get the spec green across RubyGems versions. Finally, the fix in `Bundler::EndpointSpecification` made a realworld spec start failing. This spec was faking out `rails-4.2.7.1` requirement on Bundler in the `Gemfile.lock` file to be `>= 1.17, < 3` when the real requirement is `>= 1.17, < 2`. Due to the bug in `Bundler::EndpointSpecification`, the real requirement provided by the compact index API (recorded with VCR) was being ignored, and the `Gemfile.lock` fake requirement was being used, which made the spec pass. This is all expected, and to fix the issue I changed the spec to be really realworld and don't fake any Bundler requirements. https://github.com/rubygems/rubygems/commit/faf4ef46bc
-rw-r--r--lib/bundler/endpoint_specification.rb2
-rw-r--r--lib/bundler/rubygems_ext.rb13
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb12
-rw-r--r--spec/bundler/runtime/platform_spec.rb17
4 files changed, 35 insertions, 9 deletions
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index ea197328ba..863544b1f9 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -12,7 +12,7 @@ module Bundler
super()
@name = name
@version = Gem::Version.create version
- @platform = platform
+ @platform = Gem::Platform.new(platform)
@spec_fetcher = spec_fetcher
@dependencies = dependencies.map {|dep, reqs| build_dependency(dep, reqs) }
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 9b8455d0fc..8b46d7ece4 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -238,8 +238,10 @@ module Gem
X64_MINGW = [Gem::Platform.new("x64-mingw32"),
Gem::Platform.new("x64-mingw-ucrt")].freeze
WINDOWS = [MSWIN, MSWIN64, MINGW, X64_MINGW].flatten.freeze
+ X64_LINUX = Gem::Platform.new("x86_64-linux")
+ X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl")
- if Gem::Platform.new("x86_64-linux-musl") === Gem::Platform.new("x86_64-linux")
+ if X64_LINUX === X64_LINUX_MUSL
remove_method :===
def ===(other)
@@ -275,14 +277,21 @@ module Gem
def match_gem?(platform, gem_name)
match_platforms?(platform, Gem.platforms)
end
+ end
+
+ match_platforms_defined = Gem::Platform.respond_to?(:match_platforms?, true)
+
+ if !match_platforms_defined || Gem::Platform.send(:match_platforms?, Gem::Platform::X64_LINUX_MUSL, [Gem::Platform::X64_LINUX])
private
+ remove_method :match_platforms? if match_platforms_defined
+
def match_platforms?(platform, platforms)
platforms.any? do |local_platform|
platform.nil? ||
local_platform == platform ||
- (local_platform != Gem::Platform::RUBY && local_platform =~ platform)
+ (local_platform != Gem::Platform::RUBY && platform =~ local_platform)
end
end
end
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index 2a667011a1..a98859c2d9 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -4,9 +4,9 @@ RSpec.describe "real world edgecases", :realworld => true do
def rubygems_version(name, requirement)
ruby <<-RUBY
require "#{spec_dir}/support/artifice/vcr"
- require "#{entrypoint}"
- require "#{entrypoint}/source/rubygems/remote"
- require "#{entrypoint}/fetcher"
+ require "bundler"
+ require "bundler/source/rubygems/remote"
+ require "bundler/fetcher"
rubygem = Bundler.ui.silence do
source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org"))
fetcher = Bundler::Fetcher.new(source)
@@ -64,7 +64,7 @@ RSpec.describe "real world edgecases", :realworld => true do
it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do
# from https://github.com/rubygems/bundler/issues/5031
- system_gems "bundler-2.99.0"
+ pristine_system_gems "bundler-1.99.0"
gemfile <<-G
source "https://rubygems.org"
@@ -154,7 +154,7 @@ RSpec.describe "real world edgecases", :realworld => true do
activemodel (= 4.2.7.1)
activerecord (= 4.2.7.1)
activesupport (= 4.2.7.1)
- bundler (>= 1.3.0, < 3.0)
+ bundler (>= 1.3.0, < 2.0)
railties (= 4.2.7.1)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
@@ -191,7 +191,7 @@ RSpec.describe "real world edgecases", :realworld => true do
rails (~> 4.2.7.1)
L
- bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" }
+ bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "1.99.0" }
expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
end
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index 84c8dfcab3..caf69bf085 100644
--- a/spec/bundler/runtime/platform_spec.rb
+++ b/spec/bundler/runtime/platform_spec.rb
@@ -344,6 +344,23 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
end
+ it "pulls platform specific gems correctly on musl" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = "aarch64-linux"
+ end
+ end
+
+ simulate_platform "aarch64-linux-musl" do
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, :verbose => true
+ source "https://gems.repo4"
+ gem "nokogiri"
+ G
+ end
+
+ expect(out).to include("Fetching nokogiri 1.13.8 (aarch64-linux)")
+ end
+
it "allows specifying only-ruby-platform on windows with dependency platforms" do
simulate_windows do
install_gemfile <<-G