Skip to content

Commit 188fc0a

Browse files
committed
Update refspec implementation
1 parent 127393d commit 188fc0a

File tree

1 file changed

+19
-17
lines changed

1 file changed

+19
-17
lines changed

crates/uv-git/src/git.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -907,10 +907,6 @@ pub(crate) fn fetch(
907907
// Translate the reference desired here into an actual list of refspecs
908908
// which need to get fetched. Additionally record if we're fetching tags.
909909
let mut refspecs = Vec::new();
910-
// Track a secondary refspec list to include if the first fetch fails,
911-
// this is important when using [`FetchStrategy::Cli`] as it will not
912-
// succeed if _any_ given refspec cannot be found.
913-
let mut secondary_refspecs = Vec::new();
914910
let mut tags = false;
915911
// The `+` symbol on the refspec means to allow a forced (fast-forward)
916912
// update which is needed if there is ever a force push that requires a
@@ -930,7 +926,7 @@ pub(crate) fn fetch(
930926
refspecs.push(format!(
931927
"+refs/heads/{branch_or_tag}:refs/remotes/origin/{branch_or_tag}"
932928
));
933-
secondary_refspecs.push(format!(
929+
refspecs.push(format!(
934930
"+refs/tags/{branch_or_tag}:refs/remotes/origin/tags/{branch_or_tag}"
935931
));
936932
}
@@ -974,16 +970,25 @@ pub(crate) fn fetch(
974970
debug!("Performing a Git fetch for: {remote_url}");
975971
match strategy {
976972
FetchStrategy::Cli => {
977-
fetch_with_cli(repo, remote_url, &refspecs, tags).or_else(|err| {
978-
// If secondary refspecs are populated i.e. from [`GitReference::BranchOrTag`],
979-
// then ignore the first error and try again; ideally we'd only retry if the
980-
// error was due to a missing ref but this is already not the fast path
981-
if secondary_refspecs.is_empty() {
982-
Err(err)
983-
} else {
984-
fetch_with_cli(repo, remote_url, &secondary_refspecs, tags)
973+
// Try each refspec
974+
let results = refspecs
975+
.into_iter()
976+
.map(|refspec| fetch_with_cli(repo, remote_url, &[refspec], tags))
977+
.collect::<Vec<_>>();
978+
979+
// Only fail if _all_ refspecs cannot be found
980+
// This matches the Libgit2 behavior
981+
if results.iter().all(Result::is_err) {
982+
let mut combined_err = anyhow!("failed to fetch all refspecs");
983+
for err in results {
984+
if let Err(err) = err {
985+
combined_err = combined_err.context(err.to_string());
986+
}
985987
}
986-
})
988+
Err(combined_err)
989+
} else {
990+
Ok(())
991+
}
987992
}
988993
FetchStrategy::Libgit2 => {
989994
let git_config = git2::Config::open_default()?;
@@ -992,9 +997,6 @@ pub(crate) fn fetch(
992997
opts.download_tags(git2::AutotagOption::All);
993998
}
994999

995-
// When using libgit2, missing refspecs are okay
996-
refspecs.append(&mut secondary_refspecs);
997-
9981000
// The `fetch` operation here may fail spuriously due to a corrupt
9991001
// repository. It could also fail, however, for a whole slew of other
10001002
// reasons (aka network related reasons). We want Cargo to automatically

0 commit comments

Comments
 (0)