diff options
author | David RodrÃguez <deivid.rodriguez@riseup.net> | 2022-05-09 10:40:23 +0200 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2022-09-05 11:43:14 +0900 |
commit | f7cf641469161c3770b58f79e08e312512212aa8 (patch) | |
tree | 3c3ee30585b64d5ef42e04eda0ffcb44b22290e3 | |
parent | 1420333455ba335f46887ee7a06c4ee95faa37ad (diff) | |
download | ruby-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.rb | 2 | ||||
-rw-r--r-- | lib/bundler/rubygems_ext.rb | 13 | ||||
-rw-r--r-- | spec/bundler/realworld/edgecases_spec.rb | 12 | ||||
-rw-r--r-- | spec/bundler/runtime/platform_spec.rb | 17 |
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 |