Merge the promisor-style bulk blob fetch

GitHub will not answer a bare blob id through plain fetch --stdin in a
blob:none clone; Git's own lazy fetch shape does. Proven against
GameCult/CultLib on Yggdrasil for partial and full clones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-29 21:15:56 +02:00
commit 583b2a7796

View file

@ -1133,6 +1133,10 @@ impl GitSourceDriver {
/// in depth: Git itself refuses a fetched tree with duplicate names
/// before any of it reaches disk, independent of the explicit `fsck`
/// call S1 added around the revision this bulk fetch serves.
/// The noop negotiation, `--recurse-submodules=no` and explicit
/// `--filter=blob:none` are the arguments Git's own lazy fetch uses for a
/// promisor remote; without them a hosted origin omits the wanted blob and
/// Git's connectivity check fails on the bare blob id.
fn bulk_fetch_objects(&self, repository: &Path, objects: &[String]) -> Result<()> {
if objects.is_empty() {
return Ok(());
@ -1155,11 +1159,15 @@ impl GitSourceDriver {
let mut command = self.git_command([
OsString::from("-c"),
OsString::from("transfer.fsckObjects=true"),
OsString::from("-c"),
OsString::from("fetch.negotiationAlgorithm=noop"),
OsString::from("-C"),
repository.as_os_str().to_owned(),
OsString::from("fetch"),
OsString::from("--no-tags"),
OsString::from("--no-write-fetch-head"),
OsString::from("--recurse-submodules=no"),
OsString::from("--filter=blob:none"),
OsString::from("--stdin"),
OsString::from("origin"),
])?;
@ -10554,6 +10562,90 @@ Content-Le".to_vec()), |_| {}),
bulk_fetches, 1,
"expected exactly one bulk --stdin fetch; invocations:\n{log_text}"
);
// Git's own lazy fetch for a promisor remote sends exactly these; a
// hosted origin (GitHub) omits an explicitly wanted blob, and Git's
// connectivity check then fails, without them. A file:// origin
// delivers the blob either way, so only the arguments can pin this.
let bulk_line = log_text
.lines()
.find(|line| line.contains("fetch") && line.contains("--stdin"))
.unwrap_or_default();
for required in [
"fetch.negotiationAlgorithm=noop",
"--recurse-submodules=no",
"--filter=blob:none",
] {
assert!(
bulk_line.contains(required),
"bulk fetch lacks {required}: {bulk_line}"
);
}
Ok(())
}
/// A real partial clone: the origin advertises `uploadpack.allowFilter`,
/// so `--filter=blob:none` is honoured and the checkout holds no blobs.
/// Every other fixture's origin ignores the filter and clones in full,
/// so `bulk_fetch_objects` never had a missing blob to fetch and never
/// met Git's post-fetch connectivity check on a bare blob id. The blob
/// is checked with `GIT_NO_LAZY_FETCH=1`, so only the bulk fetch itself
/// can have delivered it.
#[cfg(unix)]
#[test]
fn bulk_fetch_objects_delivers_a_blob_into_a_blob_none_partial_clone() -> Result<()> {
let temp = tempfile::tempdir()?;
let origin_repo = temp.path().join("origin");
fs::create_dir(&origin_repo)?;
git_at(&origin_repo, &["init", "--initial-branch=main"])?;
git_at(&origin_repo, &["config", "user.name", "Idunn Test"])?;
git_at(
&origin_repo,
&["config", "user.email", "idunn-test@example.invalid"],
)?;
git_at(&origin_repo, &["config", "uploadpack.allowFilter", "true"])?;
git_at(&origin_repo, &["config", "uploadpack.allowAnySHA1InWant", "true"])?;
fs::write(origin_repo.join("payload.txt"), b"partial clone payload\n")?;
git_at(&origin_repo, &["add", "--all"])?;
git_at(&origin_repo, &["commit", "-m", "fixture"])?;
let blob = git_at(&origin_repo, &["rev-parse", "HEAD:payload.txt"])?;
let source_cache_root = temp.path().join("source-cache");
fs::create_dir(&source_cache_root)?;
let driver = GitSourceDriver::new(
source_cache_root.clone(),
temp.path().join("frozen"),
None,
);
let checkout = source_cache_root.join("checkout");
driver.git([
OsString::from("clone"),
OsString::from("--filter=blob:none"),
OsString::from("--no-checkout"),
OsString::from(format!("file://{}", origin_repo.display())),
checkout.as_os_str().to_owned(),
])?;
let blob_present = || -> Result<bool> {
Ok(Command::new("/usr/bin/git")
.arg("-C")
.arg(&checkout)
.args(["cat-file", "-t", &blob])
.env_clear()
.env("PATH", "/usr/bin:/bin")
.env("GIT_NO_LAZY_FETCH", "1")
.output()?
.status
.success())
};
ensure!(
!blob_present()?,
"fixture is not a partial clone: the blob is already local"
);
driver.bulk_fetch_objects(&checkout, std::slice::from_ref(&blob))?;
assert!(
blob_present()?,
"bulk fetch succeeded but did not deliver the blob"
);
Ok(())
}