[rubygems/rubygems] Ensure refs directory in cached git source

See https://github.com/rubygems/rubygems/issues/8046 for details

Prior to this commit a cached git source without a specific ref wouldn't
survive pushing to a remote and then pulling on a different machine.
We'd end up without a refs directory in the cache, at which point git
won't recognize it as a repo.

This commit fixes the problem by adding a refs directory if it's not
already there. This needs to be done as early as possible, so any git
commands will work as expected, so this commit adds it before creating
the app cached git proxy.

8c89f0b065
This commit is contained in:
Daniel Colson 2024-09-19 14:48:57 -04:00 committed by git
parent c071fedb32
commit d0925c075b
2 changed files with 34 additions and 1 deletions

View file

@ -188,7 +188,7 @@ module Bundler
end
def specs(*)
set_cache_path!(app_cache_path) if use_app_cache?
set_up_app_cache!(app_cache_path) if use_app_cache?
if requires_checkout? && !@copied
FileUtils.rm_rf(app_cache_path) if use_app_cache? && git_proxy.not_a_bare_repository?
@ -320,6 +320,11 @@ module Bundler
@install_path = path
end
def set_up_app_cache!(path)
FileUtils.mkdir_p(path.join("refs"))
set_cache_path!(path)
end
def has_app_cache?
cached_revision && super
end

View file

@ -212,6 +212,34 @@ RSpec.describe "bundle cache with git" do
expect(the_bundle).to include_gem "foo 1.0"
end
it "can install after bundle cache without cloning remote repositories with only git tracked files" do
build_git "foo"
gemfile <<-G
source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set cache_all true"
bundle :cache, "all-platforms" => true
FileUtils.rm_rf Dir.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s
FileUtils.rm_rf Dir.glob(default_bundle_path("bundler/gems/foo-1.0-*")).first.to_s
simulate_new_machine
bundle "config set frozen true"
FileUtils.rm_rf "#{default_bundle_path}/cache/bundler/git/foo-1.0-*"
# Remove untracked files (including the empty refs dir in the cache)
Dir.chdir(bundled_app) do
system(*%W[git init --quiet])
system(*%W[git add --all])
system(*%W[git clean -d --force --quiet])
end
bundle "install --local --verbose"
expect(out).to_not include("Fetching")
expect(the_bundle).to include_gem "foo 1.0"
end
it "copies repository to vendor cache" do
# CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
system(*%W[git config --global protocol.file.allow always])