[前][次][番号順一覧][スレッド一覧]

ruby-changes:73419

From: David <ko1@a...>
Date: Mon, 5 Sep 2022 11:43:46 +0900 (JST)
Subject: [ruby-changes:73419] f7cf641469 (master): [rubygems/rubygems] Fix resolution hanging on musl platforms

https://git.ruby-lang.org/ruby.git/commit/?id=f7cf641469

From f7cf641469161c3770b58f79e08e312512212aa8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Rodr=C3=ADguez?= <deivid.rodriguez@r...>
Date: Mon, 9 May 2022 10:40:23 +0200
Subject: [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
---
 lib/bundler/endpoint_specification.rb    |  2 +-
 lib/bundler/rubygems_ext.rb              | 13 +++++++++++--
 spec/bundler/realworld/edgecases_spec.rb | 12 ++++++------
 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 https://github.com/ruby/ruby/blob/trunk/lib/bundler/endpoint_specification.rb#L12
       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 https://github.com/ruby/ruby/blob/trunk/lib/bundler/rubygems_ext.rb#L238
     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 https://github.com/ruby/ruby/blob/trunk/lib/bundler/rubygems_ext.rb#L277
       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 https://github.com/ruby/ruby/blob/trunk/spec/bundler/realworld/edgecases_spec.rb#L4
   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 https://github.com/ruby/ruby/blob/trunk/spec/bundler/realworld/edgecases_spec.rb#L64
   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 https://github.com/ruby/ruby/blob/trunk/spec/bundler/realworld/edgecases_spec.rb#L154
             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 https://github.com/ruby/ruby/blob/trunk/spec/bundler/realworld/edgecases_spec.rb#L191
         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 https://github.com/ruby/ruby/blob/trunk/spec/bundler/runtime/platform_spec.rb#L344
     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
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]