diff --git a/Manifest.txt b/Manifest.txt index 95f05fedcafc..3591f722552e 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -74,7 +74,6 @@ bundler/lib/bundler/fetcher/compact_index.rb bundler/lib/bundler/fetcher/dependency.rb bundler/lib/bundler/fetcher/downloader.rb bundler/lib/bundler/fetcher/index.rb -bundler/lib/bundler/force_platform.rb bundler/lib/bundler/friendly_errors.rb bundler/lib/bundler/gem_helper.rb bundler/lib/bundler/gem_helpers.rb diff --git a/bundler/lib/bundler.rb b/bundler/lib/bundler.rb index 9fb9ce3e8223..c99114ae64f0 100644 --- a/bundler/lib/bundler.rb +++ b/bundler/lib/bundler.rb @@ -455,7 +455,7 @@ def unbundled_exec(*args) end def local_platform - return Gem::Platform::RUBY if settings[:force_ruby_platform] + return Gem::Platform::RUBY if settings[:force_ruby_platform] || Gem.platforms == [Gem::Platform::RUBY] Gem::Platform.local end diff --git a/bundler/lib/bundler/dependency.rb b/bundler/lib/bundler/dependency.rb index 2449cb64119f..7f94079e096f 100644 --- a/bundler/lib/bundler/dependency.rb +++ b/bundler/lib/bundler/dependency.rb @@ -1,14 +1,11 @@ # frozen_string_literal: true require "rubygems/dependency" -require_relative "force_platform" require_relative "shared_helpers" require_relative "rubygems_ext" module Bundler class Dependency < Gem::Dependency - include ForcePlatform - attr_reader :autorequire attr_reader :groups, :platforms, :gemfile, :git, :github, :branch, :ref, :force_ruby_platform @@ -112,7 +109,7 @@ def initialize(name, version, options = {}, &blk) @env = options["env"] @should_include = options.fetch("should_include", true) @gemfile = options["gemfile"] - @force_ruby_platform = options.fetch("force_ruby_platform", default_force_ruby_platform) + @force_ruby_platform = options["force_ruby_platform"] @autorequire = Array(options["require"] || []) if options.key?("require") end diff --git a/bundler/lib/bundler/force_platform.rb b/bundler/lib/bundler/force_platform.rb deleted file mode 100644 index 0648ea9737a0..000000000000 --- a/bundler/lib/bundler/force_platform.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module Bundler - module ForcePlatform - private - - # The `:force_ruby_platform` value used by dependencies for resolution, and - # by locked specifications for materialization is `false` by default, except - # for TruffleRuby. TruffleRuby generally needs to force the RUBY platform - # variant unless the name is explicitly allowlisted. - - def default_force_ruby_platform - return false unless Bundler.current_ruby.truffleruby? - - !Gem::Platform::REUSE_AS_BINARY_ON_TRUFFLERUBY.include?(name) - end - end -end diff --git a/bundler/lib/bundler/lazy_specification.rb b/bundler/lib/bundler/lazy_specification.rb index 89b21efc04df..ddfa10041133 100644 --- a/bundler/lib/bundler/lazy_specification.rb +++ b/bundler/lib/bundler/lazy_specification.rb @@ -1,16 +1,13 @@ # frozen_string_literal: true -require_relative "force_platform" require_relative "match_platform" module Bundler class LazySpecification - include ForcePlatform include MatchPlatform attr_reader :name, :version, :dependencies, :platform - attr_writer :force_ruby_platform - attr_accessor :source, :remote + attr_accessor :source, :remote, :force_ruby_platform def initialize(name, version, platform, source = nil) @name = name @@ -19,7 +16,6 @@ def initialize(name, version, platform, source = nil) @platform = platform || Gem::Platform::RUBY @source = source @specification = nil - @force_ruby_platform = nil end def full_name @@ -30,12 +26,6 @@ def full_name end end - def force_ruby_platform - return @force_ruby_platform unless @force_ruby_platform.nil? - - default_force_ruby_platform - end - def ==(other) identifier == other.identifier end diff --git a/bundler/lib/bundler/rubygems_ext.rb b/bundler/lib/bundler/rubygems_ext.rb index d679d20c21ef..a47692d1f25d 100644 --- a/bundler/lib/bundler/rubygems_ext.rb +++ b/bundler/lib/bundler/rubygems_ext.rb @@ -222,9 +222,27 @@ class Platform MINGW = Gem::Platform.new("x86-mingw32") X64_MINGW = [Gem::Platform.new("x64-mingw32"), Gem::Platform.new("x64-mingw-ucrt")].freeze + end + + Platform.singleton_class.module_eval do + unless Platform.singleton_methods.include?(:match_spec?) + def match_spec?(spec) + match_gem?(spec.platform, spec.name) + end + + def match_gem?(platform, gem_name) + match_platforms?(platform, Gem.platforms) + end + + private - if RUBY_ENGINE == "truffleruby" && !defined?(REUSE_AS_BINARY_ON_TRUFFLERUBY) - REUSE_AS_BINARY_ON_TRUFFLERUBY = %w[libv8 sorbet-static].freeze + def match_platforms?(platform, platforms) + platforms.any? do |local_platform| + platform.nil? || + local_platform == platform || + (local_platform != Gem::Platform::RUBY && local_platform =~ platform) + end + end end end diff --git a/bundler/lib/bundler/spec_set.rb b/bundler/lib/bundler/spec_set.rb index 06257ac93fd3..3ff7342981f2 100644 --- a/bundler/lib/bundler/spec_set.rb +++ b/bundler/lib/bundler/spec_set.rb @@ -176,7 +176,7 @@ def tsort_each_node def specs_for_dependency(dep, match_current_platform) specs_for_name = lookup[dep.name] if match_current_platform - GemHelpers.select_best_platform_match(specs_for_name, Bundler.local_platform) + GemHelpers.select_best_platform_match(specs_for_name.select {|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform) else specs_for_name_and_platform = GemHelpers.select_best_platform_match(specs_for_name, dep.force_ruby_platform ? Gem::Platform::RUBY : dep.__platform) specs_for_name_and_platform.any? ? specs_for_name_and_platform : specs_for_name diff --git a/bundler/spec/runtime/platform_spec.rb b/bundler/spec/runtime/platform_spec.rb index 34dc5ba79902..a8aaa2b60792 100644 --- a/bundler/spec/runtime/platform_spec.rb +++ b/bundler/spec/runtime/platform_spec.rb @@ -281,30 +281,59 @@ expect(the_bundle).to include_gems "platform_specific 1.0 RUBY" - build_repo4 do - build_gem "libv8" + simulate_platform "x86_64-linux" do + build_repo4 do + build_gem "libv8" - build_gem "libv8" do |s| - s.platform = Bundler.local_platform + build_gem "libv8" do |s| + s.platform = "x86_64-linux" + end end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "libv8" + G + + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + libv8 (1.0) + + PLATFORMS + ruby + + DEPENDENCIES + libv8 + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install" + + expect(the_bundle).to include_gems "libv8 1.0 x86_64-linux" end + end + it "doesn't pull platform specific gems on truffleruby, even if lockfile only includes those", :truffleruby_only do gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem "libv8" + source "#{file_uri_for(gem_repo1)}" + gem "platform_specific" G lockfile <<-L GEM - remote: #{file_uri_for(gem_repo4)}/ + remote: #{file_uri_for(gem_repo1)}/ specs: - libv8 (1.0) + platform_specific (1.0-x86-darwin-100) PLATFORMS - ruby + x86-darwin-100 DEPENDENCIES - libv8 + platform_specific BUNDLED WITH #{Bundler::VERSION} @@ -312,7 +341,7 @@ bundle "install" - expect(the_bundle).to include_gems "libv8 1.0 #{Bundler.local_platform}" + expect(the_bundle).to include_gems "platform_specific 1.0 RUBY" end it "allows specifying only-ruby-platform on windows with dependency platforms" do