[rubygems/rubygems] Fix locking of incorrect version of git gem in an edge case

In particular, when a gem registry transitive dependency is changed to a
git source direct dependency.

https://github.com/rubygems/rubygems/commit/bcdc7660d9
This commit is contained in:
David Rodríguez 2024-11-19 21:21:20 +01:00 committed by git
parent 486485a535
commit ac5661db7b
2 changed files with 63 additions and 2 deletions

View File

@ -950,7 +950,7 @@ module Bundler
if dep if dep
gemfile_source = dep.source || default_source gemfile_source = dep.source || default_source
deps << dep if !dep.source || lockfile_source.include?(dep.source) deps << dep if !dep.source || lockfile_source.include?(dep.source) || new_deps.include?(dep)
# Replace the locked dependency's source with the equivalent source from the Gemfile # Replace the locked dependency's source with the equivalent source from the Gemfile
s.source = gemfile_source s.source = gemfile_source

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe "bundle lock with git gems" do RSpec.describe "bundle lock with git gems" do
before :each do let(:install_gemfile_with_foo_as_a_git_dependency) do
build_git "foo" build_git "foo"
install_gemfile <<-G install_gemfile <<-G
@ -11,10 +11,14 @@ RSpec.describe "bundle lock with git gems" do
end end
it "doesn't break right after running lock" do it "doesn't break right after running lock" do
install_gemfile_with_foo_as_a_git_dependency
expect(the_bundle).to include_gems "foo 1.0.0" expect(the_bundle).to include_gems "foo 1.0.0"
end end
it "doesn't print errors even if running lock after removing the cache" do it "doesn't print errors even if running lock after removing the cache" do
install_gemfile_with_foo_as_a_git_dependency
FileUtils.rm_rf(Dir[default_cache_path("git/foo-1.0-*")].first) FileUtils.rm_rf(Dir[default_cache_path("git/foo-1.0-*")].first)
bundle "lock --verbose" bundle "lock --verbose"
@ -23,6 +27,8 @@ RSpec.describe "bundle lock with git gems" do
end end
it "prints a proper error when changing a locked Gemfile to point to a bad branch" do it "prints a proper error when changing a locked Gemfile to point to a bad branch" do
install_gemfile_with_foo_as_a_git_dependency
gemfile <<-G gemfile <<-G
source "https://gem.repo1" source "https://gem.repo1"
gem 'foo', :git => "#{lib_path("foo-1.0")}", :branch => "bad" gem 'foo', :git => "#{lib_path("foo-1.0")}", :branch => "bad"
@ -34,6 +40,8 @@ RSpec.describe "bundle lock with git gems" do
end end
it "prints a proper error when installing a Gemfile with a locked ref that does not exist" do it "prints a proper error when installing a Gemfile with a locked ref that does not exist" do
install_gemfile_with_foo_as_a_git_dependency
lockfile <<~L lockfile <<~L
GIT GIT
remote: #{lib_path("foo-1.0")} remote: #{lib_path("foo-1.0")}
@ -61,6 +69,8 @@ RSpec.describe "bundle lock with git gems" do
end end
it "locks a git source to the current ref" do it "locks a git source to the current ref" do
install_gemfile_with_foo_as_a_git_dependency
update_git "foo" update_git "foo"
bundle :install bundle :install
@ -73,6 +83,8 @@ RSpec.describe "bundle lock with git gems" do
end end
it "properly clones a git source locked to an out of date ref" do it "properly clones a git source locked to an out of date ref" do
install_gemfile_with_foo_as_a_git_dependency
update_git "foo" update_git "foo"
bundle :install, env: { "BUNDLE_PATH" => "foo" } bundle :install, env: { "BUNDLE_PATH" => "foo" }
@ -80,6 +92,8 @@ RSpec.describe "bundle lock with git gems" do
end end
it "properly fetches a git source locked to an unreachable ref" do it "properly fetches a git source locked to an unreachable ref" do
install_gemfile_with_foo_as_a_git_dependency
# Create a commit and make it unreachable # Create a commit and make it unreachable
git "checkout -b foo ", lib_path("foo-1.0") git "checkout -b foo ", lib_path("foo-1.0")
unreachable_sha = update_git("foo").ref_for("HEAD") unreachable_sha = update_git("foo").ref_for("HEAD")
@ -118,6 +132,8 @@ RSpec.describe "bundle lock with git gems" do
end end
it "properly fetches a git source locked to an annotated tag" do it "properly fetches a git source locked to an annotated tag" do
install_gemfile_with_foo_as_a_git_dependency
# Create an annotated tag # Create an annotated tag
git("tag -a v1.0 -m 'Annotated v1.0'", lib_path("foo-1.0")) git("tag -a v1.0 -m 'Annotated v1.0'", lib_path("foo-1.0"))
annotated_tag = git("rev-parse v1.0", lib_path("foo-1.0")) annotated_tag = git("rev-parse v1.0", lib_path("foo-1.0"))
@ -154,9 +170,54 @@ RSpec.describe "bundle lock with git gems" do
end end
it "provides correct #full_gem_path" do it "provides correct #full_gem_path" do
install_gemfile_with_foo_as_a_git_dependency
run <<-RUBY run <<-RUBY
puts Bundler.rubygems.find_name('foo').first.full_gem_path puts Bundler.rubygems.find_name('foo').first.full_gem_path
RUBY RUBY
expect(out).to eq(bundle("info foo --path")) expect(out).to eq(bundle("info foo --path"))
end end
it "does not lock versions that don't exist in the repository when changing a GEM transitive dep to a GIT direct dep" do
build_repo4 do
build_gem "activesupport", "8.0.0" do |s|
s.add_dependency "securerandom"
end
build_gem "securerandom", "0.3.1"
end
path = lib_path("securerandom")
build_git "securerandom", "0.3.2", path: path
lockfile <<~L
GEM
remote: https://gem.repo4/
specs:
activesupport (8.0.0)
securerandom
securerandom (0.3.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
activesupport
BUNDLED WITH
#{Bundler::VERSION}
L
gemfile <<~G
source "https://gem.repo4"
gem "activesupport"
gem "securerandom", git: "#{path}"
G
bundle "lock"
expect(lockfile).to include("securerandom (0.3.2)")
end
end end