From 29a5dbe55e7ff5a104457f371cf7cc58795f0fc6 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 25 Jun 2024 14:54:17 -0600 Subject: [PATCH 1/3] spec: fix spec broken by newer FFI gem having more platforms --- spec/bundler/multilock_spec.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spec/bundler/multilock_spec.rb b/spec/bundler/multilock_spec.rb index be2c413..6ce7a8b 100644 --- a/spec/bundler/multilock_spec.rb +++ b/spec/bundler/multilock_spec.rb @@ -827,7 +827,12 @@ end RUBY - with_gemfile(orig_gemfile) do + with_gemfile("") do + # install once with nothing so that it doesn't try to lock every single + # platform available for FFI + invoke_bundler("install") + + write_gemfile(orig_gemfile) invoke_bundler("install") write_gemfile(<<~RUBY) From 0def57b481a465b2d3d5d45eca7ddf97190c29db Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 25 Jun 2024 15:14:12 -0600 Subject: [PATCH 2/3] fix syncing of changed git sources --- lib/bundler/multilock.rb | 14 +++++++++++--- spec/bundler/multilock_spec.rb | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/bundler/multilock.rb b/lib/bundler/multilock.rb index 53660e7..912b9b9 100644 --- a/lib/bundler/multilock.rb +++ b/lib/bundler/multilock.rb @@ -260,6 +260,9 @@ def after_install_all(install: true) spec_precedences[spec.name] = precedence || :parent end + lockfile.sources.map! do |source| + parent_lockfile.sources.find { |s| s == source } || source + end # replace any duplicate specs with what's in the parent lockfile lockfile.specs.map! do |spec| parent_spec = cache.find_matching_spec(parent_specs, spec) @@ -268,9 +271,7 @@ def after_install_all(install: true) dependency_changes ||= spec != parent_spec - new_spec = parent_spec.dup - new_spec.source = spec.source - new_spec + parent_spec end lockfile.platforms.replace(parent_lockfile.platforms).uniq! @@ -483,6 +484,13 @@ def write_lockfile(lockfile_definition, # from someone else if current_lockfile.exist? && install Bundler.settings.temporary(frozen: true) do + # it keeps the same sources as the builder, which now shares with + # `definition` above; give it its own copy to avoid stomping on it + builder.instance_variable_set( + :@sources, + builder.instance_variable_get(:@sources).dup + ) + current_definition = builder.to_definition(current_lockfile, {}) # if something has changed, we skip this step; it's unlocking anyway next unless current_definition.no_resolve_needed? diff --git a/spec/bundler/multilock_spec.rb b/spec/bundler/multilock_spec.rb index 6ce7a8b..9ec3dba 100644 --- a/spec/bundler/multilock_spec.rb +++ b/spec/bundler/multilock_spec.rb @@ -974,6 +974,24 @@ end end + it "syncs git sources that have updated" do + with_gemfile(<<~RUBY) do + gem "rspecq", github: "instructure/rspecq" + + lockfile "alt" do + end + RUBY + invoke_bundler("install") + replace_lockfile_git_pin("d7fa5536da01cccb5109ba05c9e236d6660da593") + invoke_bundler("install") + + expect(invoke_bundler("info rspecq")).to include("d7fa553") + + invoke_bundler("update rspecq") + expect(invoke_bundler("info rspecq")).not_to include("d7fa553") + end + end + private def create_local_gem(name, content = "", subdirectory: true) @@ -1070,6 +1088,12 @@ def replace_lockfile_pin(lockfile, gem, version) File.write(lockfile, new_contents) end + def replace_lockfile_git_pin(revision) + new_contents = File.read("Gemfile.lock").gsub(/revision: [0-9a-f]+/, "revision: #{revision}") + + File.write("Gemfile.lock", new_contents) + end + def update_lockfile_bundler(lockfile, version) new_contents = File.read(lockfile).gsub(/BUNDLED WITH\n [0-9.]+/, "BUNDLED WITH\n #{version}") From d8ff979dcbc0981b88eaf0d3c061b39bcdcb370a Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 25 Jun 2024 15:42:00 -0600 Subject: [PATCH 3/3] fix an issue on initial sync that doesn't know to include intermediate gems --- lib/bundler/multilock.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/bundler/multilock.rb b/lib/bundler/multilock.rb index 912b9b9..b76cdff 100644 --- a/lib/bundler/multilock.rb +++ b/lib/bundler/multilock.rb @@ -512,6 +512,14 @@ def write_lockfile(lockfile_definition, previous_ui_level = Bundler.ui.level Bundler.ui.level = "warn" begin + # force a remote resolution if intermediate gems are missing + if definition.instance_variable_get(:@locked_spec_with_missing_deps) || + definition.instance_variable_get(:@locked_spec_with_invalid_deps) || + definition.instance_variable_get(:@missing_lockfile_dep) || + definition.instance_variable_get(:@invalid_lockfile_dep) + raise SolveFailure + end + # this is a horrible hack, to fix what I consider to be a Bundler bug. # basically, if you have multiple platform specific gems in your # lockfile, and that gem gets unlocked, Bundler will only search