@@ -907,10 +907,6 @@ pub(crate) fn fetch(
907
907
// Translate the reference desired here into an actual list of refspecs
908
908
// which need to get fetched. Additionally record if we're fetching tags.
909
909
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 ( ) ;
914
910
let mut tags = false ;
915
911
// The `+` symbol on the refspec means to allow a forced (fast-forward)
916
912
// update which is needed if there is ever a force push that requires a
@@ -930,7 +926,7 @@ pub(crate) fn fetch(
930
926
refspecs. push ( format ! (
931
927
"+refs/heads/{branch_or_tag}:refs/remotes/origin/{branch_or_tag}"
932
928
) ) ;
933
- secondary_refspecs . push ( format ! (
929
+ refspecs . push ( format ! (
934
930
"+refs/tags/{branch_or_tag}:refs/remotes/origin/tags/{branch_or_tag}"
935
931
) ) ;
936
932
}
@@ -974,16 +970,25 @@ pub(crate) fn fetch(
974
970
debug ! ( "Performing a Git fetch for: {remote_url}" ) ;
975
971
match strategy {
976
972
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
+ }
985
987
}
986
- } )
988
+ Err ( combined_err)
989
+ } else {
990
+ Ok ( ( ) )
991
+ }
987
992
}
988
993
FetchStrategy :: Libgit2 => {
989
994
let git_config = git2:: Config :: open_default ( ) ?;
@@ -992,9 +997,6 @@ pub(crate) fn fetch(
992
997
opts. download_tags ( git2:: AutotagOption :: All ) ;
993
998
}
994
999
995
- // When using libgit2, missing refspecs are okay
996
- refspecs. append ( & mut secondary_refspecs) ;
997
-
998
1000
// The `fetch` operation here may fail spuriously due to a corrupt
999
1001
// repository. It could also fail, however, for a whole slew of other
1000
1002
// reasons (aka network related reasons). We want Cargo to automatically
0 commit comments