diff --git a/bundler/lib/bundler/index.rb b/bundler/lib/bundler/index.rb index 8930fca6d0fd..5bc24fc0b206 100644 --- a/bundler/lib/bundler/index.rb +++ b/bundler/lib/bundler/index.rb @@ -192,11 +192,7 @@ def search_by_dependency(dependency, base = nil) specs += base if base found = specs.select do |spec| next true if spec.source.is_a?(Source::Gemspec) - if base # allow all platforms when searching from a lockfile - dependency.matches_spec?(spec) - else - dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec) - end + dependency.matches_spec?(spec) end found diff --git a/bundler/lib/bundler/lazy_specification.rb b/bundler/lib/bundler/lazy_specification.rb index 198906b987ae..8430b8698813 100644 --- a/bundler/lib/bundler/lazy_specification.rb +++ b/bundler/lib/bundler/lazy_specification.rb @@ -84,7 +84,7 @@ def __materialize__ else ruby_platform_materializes_to_ruby_platform? ? self : Dependency.new(name, version) end - platform_object = Gem::Platform.new(platform) + platform_object = ruby_platform_materializes_to_ruby_platform? ? Gem::Platform.new(platform) : Gem::Platform.local candidates = source.specs.search(search_object) same_platform_candidates = candidates.select do |spec| MatchPlatform.platforms_match?(spec.platform, platform_object) @@ -152,7 +152,7 @@ def method_missing(method, *args, &blk) # explicitly add a more specific platform. # def ruby_platform_materializes_to_ruby_platform? - !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) || Bundler.settings[:force_ruby_platform] + !Bundler.most_specific_locked_platform?(generic_local_platform) || Bundler.settings[:force_ruby_platform] end end end diff --git a/bundler/lib/bundler/match_platform.rb b/bundler/lib/bundler/match_platform.rb index 69074925a615..7f7e8227f915 100644 --- a/bundler/lib/bundler/match_platform.rb +++ b/bundler/lib/bundler/match_platform.rb @@ -15,7 +15,6 @@ def self.platforms_match?(gemspec_platform, local_platform) return true if Gem::Platform::RUBY == gemspec_platform return true if local_platform == gemspec_platform gemspec_platform = Gem::Platform.new(gemspec_platform) - return true if GemHelpers.generic(gemspec_platform) === local_platform return true if gemspec_platform === local_platform false diff --git a/bundler/lib/bundler/resolver.rb b/bundler/lib/bundler/resolver.rb index 18eb18160de2..fc4d7cb15d3e 100644 --- a/bundler/lib/bundler/resolver.rb +++ b/bundler/lib/bundler/resolver.rb @@ -284,7 +284,7 @@ def gem_not_found_message(name, requirement, source, extra_message = "") if specs_matching_requirement.any? specs = specs_matching_requirement matching_part = requirement_label - requirement_label = "#{requirement_label} #{requirement.__platform}" + requirement_label = "#{requirement_label}' with platform '#{requirement.__platform}" end message = String.new("Could not find gem '#{requirement_label}'#{extra_message} in #{source}#{cache_message}.\n") diff --git a/bundler/lib/bundler/spec_set.rb b/bundler/lib/bundler/spec_set.rb index 85a9d1537b67..2df14fbb0911 100644 --- a/bundler/lib/bundler/spec_set.rb +++ b/bundler/lib/bundler/spec_set.rb @@ -24,7 +24,7 @@ def for(dependencies, check = false, match_current_platform = false) # use a hash here to ensure constant lookup time in the `any?` call above handled[dep.name] << dep - specs_for_dep = spec_for_dependency(dep, match_current_platform) + specs_for_dep = specs_for_dependency(dep, match_current_platform) if specs_for_dep.any? specs.concat(specs_for_dep) @@ -173,12 +173,13 @@ def tsort_each_node @specs.sort_by(&:name).each {|s| yield s } end - def spec_for_dependency(dep, match_current_platform) - specs_for_platforms = lookup[dep.name] + 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_platforms.select {|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform) + GemHelpers.select_best_platform_match(specs_for_name.select {|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform) else - GemHelpers.select_best_platform_match(specs_for_platforms, dep.__platform) + specs_for_name_and_platform = GemHelpers.select_best_platform_match(specs_for_name, dep.__platform) + specs_for_name_and_platform.any? ? specs_for_name_and_platform : specs_for_name end end diff --git a/bundler/spec/install/gemfile/specific_platform_spec.rb b/bundler/spec/install/gemfile/specific_platform_spec.rb index 519611f5bf98..276a84f2a6b6 100644 --- a/bundler/spec/install/gemfile/specific_platform_spec.rb +++ b/bundler/spec/install/gemfile/specific_platform_spec.rb @@ -283,19 +283,19 @@ end it "does not resolve if the current platform does not match any of available platform specific variants for a top level dependency" do - build_repo2 do + build_repo4 do build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" } build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" } end gemfile <<~G - source "#{file_uri_for(gem_repo2)}" + source "#{file_uri_for(gem_repo4)}" gem "sorbet-static", "0.5.6433" G error_message = <<~ERROR.strip - Could not find gem 'sorbet-static (= 0.5.6433) arm64-darwin-21' in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally. + Could not find gem 'sorbet-static (= 0.5.6433)' with platform 'arm64-darwin-21' in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally. The source contains the following gems matching 'sorbet-static (= 0.5.6433)': * sorbet-static-0.5.6433-universal-darwin-20 @@ -303,7 +303,7 @@ ERROR simulate_platform "arm64-darwin-21" do - bundle "install", :raise_on_error => false + bundle "lock", :raise_on_error => false end expect(err).to include(error_message).once @@ -311,27 +311,27 @@ # Make sure it doesn't print error twice in verbose mode simulate_platform "arm64-darwin-21" do - bundle "install --verbose", :raise_on_error => false + bundle "lock --verbose", :raise_on_error => false end expect(err).to include(error_message).once end it "does not resolve if the current platform does not match any of available platform specific variants for a transitive dependency" do - build_repo2 do + build_repo4 do build_gem("sorbet", "0.5.6433") {|s| s.add_dependency "sorbet-static", "= 0.5.6433" } build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" } build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" } end gemfile <<~G - source "#{file_uri_for(gem_repo2)}" + source "#{file_uri_for(gem_repo4)}" gem "sorbet", "0.5.6433" G error_message = <<~ERROR.strip - Could not find gem 'sorbet-static (= 0.5.6433) arm64-darwin-21', which is required by gem 'sorbet (= 0.5.6433)', in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally. + Could not find gem 'sorbet-static (= 0.5.6433)' with platform 'arm64-darwin-21', which is required by gem 'sorbet (= 0.5.6433)', in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally. The source contains the following gems matching 'sorbet-static (= 0.5.6433)': * sorbet-static-0.5.6433-universal-darwin-20 @@ -339,7 +339,7 @@ ERROR simulate_platform "arm64-darwin-21" do - bundle "install", :raise_on_error => false + bundle "lock", :raise_on_error => false end expect(err).to include(error_message).once @@ -347,12 +347,33 @@ # Make sure it doesn't print error twice in verbose mode simulate_platform "arm64-darwin-21" do - bundle "install --verbose", :raise_on_error => false + bundle "lock --verbose", :raise_on_error => false end expect(err).to include(error_message).once end + it "does not generate a lockfile if RUBY platform is forced and some gem has no RUBY variant available" do + build_repo4 do + build_gem("sorbet-static", "0.5.9889") {|s| s.platform = Gem::Platform.local } + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "sorbet-static", "0.5.9889" + G + + bundle "lock", :raise_on_error => false, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" } + + expect(err).to include <<~ERROR.rstrip + Could not find gem 'sorbet-static (= 0.5.9889)' with platform 'ruby' in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally. + + The source contains the following gems matching 'sorbet-static (= 0.5.9889)': + * sorbet-static-0.5.9889-#{Gem::Platform.local} + ERROR + end + private def setup_multiplatform_gem