Skip to content

Commit

Permalink
Update refspec implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
zanieb committed Feb 21, 2024
1 parent 127393d commit 188fc0a
Showing 1 changed file with 19 additions and 17 deletions.
36 changes: 19 additions & 17 deletions crates/uv-git/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,10 +907,6 @@ pub(crate) fn fetch(
// Translate the reference desired here into an actual list of refspecs
// which need to get fetched. Additionally record if we're fetching tags.
let mut refspecs = Vec::new();
// Track a secondary refspec list to include if the first fetch fails,
// this is important when using [`FetchStrategy::Cli`] as it will not
// succeed if _any_ given refspec cannot be found.
let mut secondary_refspecs = Vec::new();
let mut tags = false;
// The `+` symbol on the refspec means to allow a forced (fast-forward)
// update which is needed if there is ever a force push that requires a
Expand All @@ -930,7 +926,7 @@ pub(crate) fn fetch(
refspecs.push(format!(
"+refs/heads/{branch_or_tag}:refs/remotes/origin/{branch_or_tag}"
));
secondary_refspecs.push(format!(
refspecs.push(format!(
"+refs/tags/{branch_or_tag}:refs/remotes/origin/tags/{branch_or_tag}"
));
}
Expand Down Expand Up @@ -974,16 +970,25 @@ pub(crate) fn fetch(
debug!("Performing a Git fetch for: {remote_url}");
match strategy {
FetchStrategy::Cli => {
fetch_with_cli(repo, remote_url, &refspecs, tags).or_else(|err| {
// If secondary refspecs are populated i.e. from [`GitReference::BranchOrTag`],
// then ignore the first error and try again; ideally we'd only retry if the
// error was due to a missing ref but this is already not the fast path
if secondary_refspecs.is_empty() {
Err(err)
} else {
fetch_with_cli(repo, remote_url, &secondary_refspecs, tags)
// Try each refspec
let results = refspecs
.into_iter()
.map(|refspec| fetch_with_cli(repo, remote_url, &[refspec], tags))
.collect::<Vec<_>>();

// Only fail if _all_ refspecs cannot be found
// This matches the Libgit2 behavior
if results.iter().all(Result::is_err) {
let mut combined_err = anyhow!("failed to fetch all refspecs");
for err in results {
if let Err(err) = err {
combined_err = combined_err.context(err.to_string());
}
}
})
Err(combined_err)
} else {
Ok(())
}
}
FetchStrategy::Libgit2 => {
let git_config = git2::Config::open_default()?;
Expand All @@ -992,9 +997,6 @@ pub(crate) fn fetch(
opts.download_tags(git2::AutotagOption::All);
}

// When using libgit2, missing refspecs are okay
refspecs.append(&mut secondary_refspecs);

// The `fetch` operation here may fail spuriously due to a corrupt
// repository. It could also fail, however, for a whole slew of other
// reasons (aka network related reasons). We want Cargo to automatically
Expand Down

0 comments on commit 188fc0a

Please sign in to comment.