[ruby/rubygems] Allow bundle pristine to work for git gems in the same repo:

- Fix https://github.com/ruby/rubygems/pull/9186
- ### Problem

  Running `bundle pristine` in a Gemfile where there is many git gem
  pointing to the same repository will result in a error
  "Another git process seems to be running in this repository".

  ### Context

  This error is a regression since https://github.com/ruby/rubygems/commit/a555fd6ccd17
  where `bundle pristine` now runs in parallel which could lead
  to running simultaneous git operations in the same repository.

  ### Solution

  When Bundler pristine a git gem it does a `git reset --hard` without
  specifying a path.
  This means the whole repository will be reset. In this case, we can
  leverage that by just pristining one gem per unique git sources.
  This is also more efficient.

https://github.com/ruby/rubygems/commit/710ba514a8
This commit is contained in:
Edouard CHIN 2025-12-15 15:56:41 +01:00 committed by git
parent 98cac1a75d
commit f88e797090
2 changed files with 64 additions and 0 deletions

View File

@ -11,6 +11,7 @@ module Bundler
definition = Bundler.definition
definition.validate_runtime!
installer = Bundler::Installer.new(Bundler.root, definition)
git_sources = []
ProcessLock.lock do
installed_specs = definition.specs.reject do |spec|
@ -41,6 +42,9 @@ module Bundler
end
FileUtils.rm_rf spec.extension_dir
FileUtils.rm_rf spec.full_gem_path
next if git_sources.include?(source)
git_sources << source
else
Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
next

View File

@ -89,6 +89,66 @@ RSpec.describe "bundle pristine" do
expect(changes_txt).to be_file
expect(err).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is locally overridden.")
end
it "doesn't run multiple git processes for the same repository" do
nested_gems = [
"actioncable",
"actionmailer",
"actionpack",
"actionview",
"activejob",
"activemodel",
"activerecord",
"activestorage",
"activesupport",
"railties",
]
build_repo2 do
nested_gems.each do |gem|
build_lib gem, path: lib_path("rails/#{gem}")
end
build_git "rails", path: lib_path("rails") do |s|
nested_gems.each do |gem|
s.add_dependency gem
end
end
end
install_gemfile <<-G
source 'https://rubygems.org'
git "#{lib_path("rails")}" do
gem "rails"
gem "actioncable"
gem "actionmailer"
gem "actionpack"
gem "actionview"
gem "activejob"
gem "activemodel"
gem "activerecord"
gem "activestorage"
gem "activesupport"
gem "railties"
end
G
changed_files = []
diff = "#Pristine spec changes"
nested_gems.each do |gem|
spec = find_spec(gem)
changed_files << Pathname.new(spec.full_gem_path).join("lib/#{gem}.rb")
File.open(changed_files.last, "a") {|f| f.puts diff }
end
bundle "pristine"
changed_files.each do |changed_file|
expect(File.read(changed_file)).to_not include(diff)
end
end
end
context "when sourced from gemspec" do