@@ -907,6 +907,10 @@ 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 ( ) ;
910
914
let mut tags = false ;
911
915
// The `+` symbol on the refspec means to allow a forced (fast-forward)
912
916
// update which is needed if there is ever a force push that requires a
@@ -926,7 +930,7 @@ pub(crate) fn fetch(
926
930
refspecs. push ( format ! (
927
931
"+refs/heads/{branch_or_tag}:refs/remotes/origin/{branch_or_tag}"
928
932
) ) ;
929
- refspecs . push ( format ! (
933
+ secondary_refspecs . push ( format ! (
930
934
"+refs/tags/{branch_or_tag}:refs/remotes/origin/tags/{branch_or_tag}"
931
935
) ) ;
932
936
}
@@ -969,13 +973,28 @@ pub(crate) fn fetch(
969
973
970
974
debug ! ( "Performing a Git fetch for: {remote_url}" ) ;
971
975
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
+ }
973
988
FetchStrategy :: Libgit2 => {
974
989
let git_config = git2:: Config :: open_default ( ) ?;
975
990
with_fetch_options ( & git_config, remote_url, & mut |mut opts| {
976
991
if tags {
977
992
opts. download_tags ( git2:: AutotagOption :: All ) ;
978
993
}
994
+
995
+ // When using libgit2, missing refspecs are okay
996
+ refspecs. append ( & mut secondary_refspecs) ;
997
+
979
998
// The `fetch` operation here may fail spuriously due to a corrupt
980
999
// repository. It could also fail, however, for a whole slew of other
981
1000
// reasons (aka network related reasons). We want Cargo to automatically
0 commit comments