diff options
-rw-r--r-- | lib/bundler/definition.rb | 15 | ||||
-rw-r--r-- | lib/bundler/spec_set.rb | 38 | ||||
-rw-r--r-- | spec/bundler/commands/lock_spec.rb | 11 | ||||
-rw-r--r-- | spec/bundler/commands/update_spec.rb | 26 | ||||
-rw-r--r-- | spec/bundler/install/gemfile/sources_spec.rb | 30 | ||||
-rw-r--r-- | spec/bundler/install/gemfile/specific_platform_spec.rb | 136 | ||||
-rw-r--r-- | spec/bundler/lock/lockfile_spec.rb | 2 | ||||
-rw-r--r-- | spec/bundler/support/platforms.rb | 2 |
8 files changed, 216 insertions, 44 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 72fbae1984..9ef0abed93 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -84,7 +84,7 @@ module Bundler @new_platform = nil @removed_platform = nil - if lockfile && File.exist?(lockfile) + if lockfile_exists? @lockfile_contents = Bundler.read_file(lockfile) @locked_gems = LockfileParser.new(@lockfile_contents) @locked_platforms = @locked_gems.platforms @@ -302,6 +302,10 @@ module Bundler end end + def should_complete_platforms? + !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform] + end + def spec_git_paths sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact end @@ -491,6 +495,10 @@ module Bundler private + def lockfile_exists? + lockfile && File.exist?(lockfile) + end + def resolver @resolver ||= Resolver.new(resolution_packages, gem_version_promoter) end @@ -567,11 +575,12 @@ module Bundler end def start_resolution - result = resolver.start + result = SpecSet.new(resolver.start) @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version + @platforms = result.complete_platforms!(platforms) if should_complete_platforms? - SpecSet.new(SpecSet.new(result).for(dependencies, false, @platforms)) + SpecSet.new(result.for(dependencies, false, @platforms)) end def precompute_source_requirements_for_indirect_dependencies? diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 277824c34f..f4fc005ef2 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -52,6 +52,44 @@ module Bundler specs.uniq end + def complete_platforms!(platforms) + return platforms.concat([Gem::Platform::RUBY]).uniq if @specs.empty? + + new_platforms = @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq.select do |platform| + next if platforms.include?(platform) + next unless GemHelpers.generic(platform) == Gem::Platform::RUBY + + new_specs = [] + + valid_platform = lookup.all? do |_, specs| + spec = specs.first + matching_specs = spec.source.specs.search([spec.name, spec.version]) + platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).first + + if platform_spec + new_specs << LazySpecification.from_spec(platform_spec) + true + else + false + end + end + next unless valid_platform + + @specs.concat(new_specs.uniq) + end + return platforms if new_platforms.empty? + + platforms.concat(new_platforms) + + less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && platform === Bundler.local_platform } + platforms.delete(Bundler.local_platform) if less_specific_platform + + @sorted = nil + @lookup = nil + + platforms + end + def [](key) key = key.name if key.respond_to?(:name) lookup[key].reverse diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index ac220c9318..5c6a2c0e3d 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -733,7 +733,7 @@ RSpec.describe "bundle lock" do gem "libv8" G - simulate_platform(Gem::Platform.new("x86_64-darwin")) { bundle "lock" } + simulate_platform(Gem::Platform.new("x86_64-darwin-19")) { bundle "lock" } expect(lockfile).to eq <<~G GEM @@ -743,7 +743,8 @@ RSpec.describe "bundle lock" do libv8 (8.4.255.0-x86_64-darwin-20) PLATFORMS - x86_64-darwin + x86_64-darwin-19 + x86_64-darwin-20 DEPENDENCIES libv8 @@ -1237,7 +1238,7 @@ RSpec.describe "bundle lock" do activemodel (>= 6.0.4) PLATFORMS - #{lockfile_platforms} + #{local_platform} DEPENDENCIES activeadmin (= 2.13.1) @@ -1273,7 +1274,7 @@ RSpec.describe "bundle lock" do version solving has failed. ERR - lockfile lockfile.gsub(/PLATFORMS\n #{lockfile_platforms}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}") + lockfile lockfile.gsub(/PLATFORMS\n #{local_platform}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}") bundle "lock", :raise_on_error => false @@ -1438,7 +1439,7 @@ RSpec.describe "bundle lock" do nokogiri (1.14.2) PLATFORMS - x86_64-linux + #{lockfile_platforms} DEPENDENCIES foo! diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index 8e48758c04..5c7b569fe2 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -559,12 +559,36 @@ RSpec.describe "bundle update" do before do build_repo2 - install_gemfile <<-G + gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport" gem "rack-obama" gem "platform_specific" G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + activesupport (2.3.5) + platform_specific (1.0-#{local_platform}) + rack (1.0.0) + rack-obama (1.0) + rack + + PLATFORMS + #{local_platform} + + DEPENDENCIES + activesupport + platform_specific + rack-obama + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install" end it "doesn't hit repo2" do diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb index 64eed1a2f4..15ff15e46d 100644 --- a/spec/bundler/install/gemfile/sources_spec.rb +++ b/spec/bundler/install/gemfile/sources_spec.rb @@ -379,7 +379,7 @@ RSpec.describe "bundle install with gems on multiple sources" do rack PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES depends_on_rack! @@ -422,7 +422,7 @@ RSpec.describe "bundle install with gems on multiple sources" do rack PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES depends_on_rack! @@ -803,7 +803,7 @@ RSpec.describe "bundle install with gems on multiple sources" do zeitwerk (2.4.2) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES activesupport @@ -874,7 +874,7 @@ RSpec.describe "bundle install with gems on multiple sources" do sidekiq (>= 6.1.0) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES activesupport @@ -975,7 +975,7 @@ RSpec.describe "bundle install with gems on multiple sources" do sidekiq (>= 6.1.0) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES activesupport @@ -1049,7 +1049,7 @@ RSpec.describe "bundle install with gems on multiple sources" do sidekiq (>= 6.1.0) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES activesupport @@ -1146,7 +1146,7 @@ RSpec.describe "bundle install with gems on multiple sources" do nokogiri (>= 1.2.3) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES handsoap! @@ -1209,7 +1209,7 @@ RSpec.describe "bundle install with gems on multiple sources" do rack (0.9.1) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES rack! @@ -1239,7 +1239,7 @@ RSpec.describe "bundle install with gems on multiple sources" do rack (0.9.1) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES rack! @@ -1261,7 +1261,7 @@ RSpec.describe "bundle install with gems on multiple sources" do rack (0.9.1) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES rack! @@ -1701,7 +1701,7 @@ RSpec.describe "bundle install with gems on multiple sources" do mime-types (3.3.1) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES capybara (~> 2.5.0) @@ -1732,7 +1732,7 @@ RSpec.describe "bundle install with gems on multiple sources" do mime-types (3.0.0) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES capybara (~> 2.5.0) @@ -1789,7 +1789,7 @@ RSpec.describe "bundle install with gems on multiple sources" do pdf-writer (= 1.1.8) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES ruport (= 1.7.0.3)! @@ -1851,7 +1851,7 @@ RSpec.describe "bundle install with gems on multiple sources" do pdf-writer (= 1.1.8) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES ruport (= 1.7.0.3)! @@ -1899,7 +1899,7 @@ RSpec.describe "bundle install with gems on multiple sources" do pdf-writer (1.1.8) PLATFORMS - #{local_platform} + #{lockfile_platforms} DEPENDENCIES pdf-writer (= 1.1.8) diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb index 099ef35bbf..0c9816eaac 100644 --- a/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -11,11 +11,11 @@ RSpec.describe "bundle install with specific platforms" do setup_multiplatform_gem install_gemfile(google_protobuf) allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) - expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to include(pl("x86_64-darwin-15")) expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin") - expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ - google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin - ]) + expect(the_bundle.locked_gems.specs.map(&:full_name)).to include( + "google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin" + ) end end @@ -309,10 +309,10 @@ RSpec.describe "bundle install with specific platforms" do G allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) - expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to include(pl("x86_64-darwin-15")) expect(the_bundle).to include_gems("facter 2.4.6 universal-darwin", "CFPropertyList 1.0") - expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0", - "facter-2.4.6-universal-darwin"]) + expect(the_bundle.locked_gems.specs.map(&:full_name)).to include("CFPropertyList-1.0", + "facter-2.4.6-universal-darwin") end end @@ -327,8 +327,8 @@ RSpec.describe "bundle install with specific platforms" do install_gemfile(google_protobuf) bundle "lock --add-platform=#{x64_mingw32}" - expect(the_bundle.locked_gems.platforms).to eq([x64_mingw32, pl("x86_64-darwin-15")]) - expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ + expect(the_bundle.locked_gems.platforms).to include(x64_mingw32, pl("x86_64-darwin-15")) + expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(*%w[ google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32 ]) @@ -341,11 +341,11 @@ RSpec.describe "bundle install with specific platforms" do install_gemfile(google_protobuf) bundle "lock --add-platform=#{java}" - expect(the_bundle.locked_gems.platforms).to eq([java, pl("x86_64-darwin-15")]) - expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ - google-protobuf-3.0.0.alpha.5.0.5.1 - google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin - ]) + expect(the_bundle.locked_gems.platforms).to include(java, pl("x86_64-darwin-15")) + expect(the_bundle.locked_gems.specs.map(&:full_name)).to include( + "google-protobuf-3.0.0.alpha.5.0.5.1", + "google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin" + ) end end end @@ -517,7 +517,7 @@ RSpec.describe "bundle install with specific platforms" do sorbet-runtime (= 0.5.10160) PLATFORMS - #{lockfile_platforms("ruby")} + #{lockfile_platforms} DEPENDENCIES sorbet-static-and-runtime @@ -548,7 +548,7 @@ RSpec.describe "bundle install with specific platforms" do sorbet-runtime (= 0.5.10160) PLATFORMS - #{lockfile_platforms} + #{local_platform} DEPENDENCIES sorbet-static-and-runtime @@ -601,7 +601,7 @@ RSpec.describe "bundle install with specific platforms" do DEPENDENCIES nokogiri - sorbet + sorbet-static BUNDLED WITH #{Bundler::VERSION} @@ -702,7 +702,7 @@ RSpec.describe "bundle install with specific platforms" do sorbet-runtime (= 0.5.10160) PLATFORMS - #{lockfile_platforms} + #{local_platform} DEPENDENCIES sorbet-static-and-runtime @@ -1067,6 +1067,106 @@ RSpec.describe "bundle install with specific platforms" do end end + it "locks specific platforms automatically" do + simulate_platform "x86_64-linux" do + build_repo4 do + build_gem "nokogiri", "1.14.0" + build_gem "nokogiri", "1.14.0" do |s| + s.platform = "x86_64-linux" + end + build_gem "nokogiri", "1.14.0" do |s| + s.platform = "arm-linux" + end + build_gem "nokogiri", "1.14.0" do |s| + s.platform = "x64-mingw32" + end + build_gem "nokogiri", "1.14.0" do |s| + s.platform = "java" + end + + build_gem "sorbet-static", "0.5.10696" do |s| + s.platform = "x86_64-linux" + end + build_gem "sorbet-static", "0.5.10696" do |s| + s.platform = "universal-darwin-22" + end + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "nokogiri" + G + + bundle "lock" + + # locks all compatible platforms, excluding Java and Windows + expect(lockfile).to eq(<<~L) + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + nokogiri (1.14.0) + nokogiri (1.14.0-arm-linux) + nokogiri (1.14.0-x86_64-linux) + + PLATFORMS + arm-linux + ruby + x86_64-linux + + DEPENDENCIES + nokogiri + + CHECKSUMS + #{gem_no_checksum "nokogiri", "1.14.0"} + #{gem_no_checksum "nokogiri", "1.14.0", "arm-linux"} + #{gem_no_checksum "nokogiri", "1.14.0", "x86_64-linux"} + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "nokogiri" + gem "sorbet-static" + G + + FileUtils.rm bundled_app_lock + + bundle "lock" + + # locks only platforms compatible with all gems in the bundle + expect(lockfile).to eq(<<~L) + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + nokogiri (1.14.0) + nokogiri (1.14.0-x86_64-linux) + sorbet-static (0.5.10696-universal-darwin-22) + sorbet-static (0.5.10696-x86_64-linux) + + PLATFORMS + universal-darwin-22 + x86_64-linux + + DEPENDENCIES + nokogiri + sorbet-static + + CHECKSUMS + #{gem_no_checksum "nokogiri", "1.14.0"} + #{gem_no_checksum "nokogiri", "1.14.0", "x86_64-linux"} + #{gem_no_checksum "sorbet-static", "0.5.10696", "universal-darwin-22"} + #{gem_no_checksum "sorbet-static", "0.5.10696", "x86_64-linux"} + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + private def setup_multiplatform_gem diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index be1fdc37b5..efa5b85788 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1212,7 +1212,7 @@ RSpec.describe "the lockfile format" do rack (1.0.0) PLATFORMS - #{lockfile_platforms("java")} + #{lockfile_platforms("java", local_platform, :defaults => [])} DEPENDENCIES rack diff --git a/spec/bundler/support/platforms.rb b/spec/bundler/support/platforms.rb index 973d34a43a..3289d5e8e2 100644 --- a/spec/bundler/support/platforms.rb +++ b/spec/bundler/support/platforms.rb @@ -105,7 +105,7 @@ module Spec end def default_locked_platforms - [local_platform] + [local_platform, generic_local_platform] end end end |