Skip to content

Commit 127393d

Browse files
committed
Fix handling of GitReference::BranchOrTag
1 parent 73df4fb commit 127393d

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

crates/uv-git/src/git.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,10 @@ 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();
910914
let mut tags = false;
911915
// The `+` symbol on the refspec means to allow a forced (fast-forward)
912916
// update which is needed if there is ever a force push that requires a
@@ -926,7 +930,7 @@ pub(crate) fn fetch(
926930
refspecs.push(format!(
927931
"+refs/heads/{branch_or_tag}:refs/remotes/origin/{branch_or_tag}"
928932
));
929-
refspecs.push(format!(
933+
secondary_refspecs.push(format!(
930934
"+refs/tags/{branch_or_tag}:refs/remotes/origin/tags/{branch_or_tag}"
931935
));
932936
}
@@ -969,13 +973,28 @@ pub(crate) fn fetch(
969973

970974
debug!("Performing a Git fetch for: {remote_url}");
971975
match strategy {
972-
FetchStrategy::Cli => fetch_with_cli(repo, remote_url, &refspecs, tags),
976+
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)
985+
}
986+
})
987+
}
973988
FetchStrategy::Libgit2 => {
974989
let git_config = git2::Config::open_default()?;
975990
with_fetch_options(&git_config, remote_url, &mut |mut opts| {
976991
if tags {
977992
opts.download_tags(git2::AutotagOption::All);
978993
}
994+
995+
// When using libgit2, missing refspecs are okay
996+
refspecs.append(&mut secondary_refspecs);
997+
979998
// The `fetch` operation here may fail spuriously due to a corrupt
980999
// repository. It could also fail, however, for a whole slew of other
9811000
// reasons (aka network related reasons). We want Cargo to automatically

0 commit comments

Comments
 (0)