@@ -2,6 +2,7 @@ use crate::{
22 bstr:: { BString , ByteSlice } ,
33 clone:: PrepareFetch ,
44} ;
5+ use gix_ref:: Category ;
56
67/// The error returned by [`PrepareFetch::fetch_only()`].
78#[ derive( Debug , thiserror:: Error ) ]
@@ -49,6 +50,8 @@ pub enum Error {
4950 CommitterOrFallback ( #[ from] crate :: config:: time:: Error ) ,
5051 #[ error( transparent) ]
5152 RefMap ( #[ from] crate :: remote:: ref_map:: Error ) ,
53+ #[ error( transparent) ]
54+ ReferenceName ( #[ from] gix_validate:: reference:: name:: Error ) ,
5255}
5356
5457/// Modification
@@ -106,15 +109,13 @@ impl PrepareFetch {
106109
107110 // For shallow clones without custom configuration, we'll use a single-branch refspec
108111 // to match git's behavior (matching git's single-branch behavior for shallow clones).
109- let use_single_branch_for_shallow = self . shallow != remote:: fetch:: Shallow :: NoChange
110- && self . configure_remote . is_none ( )
111- && remote. fetch_specs . is_empty ( ) ;
112+ let use_single_branch_for_shallow =
113+ self . shallow != remote:: fetch:: Shallow :: NoChange && remote. fetch_specs . is_empty ( ) ;
112114
113115 let target_ref = if use_single_branch_for_shallow {
114116 // Determine target branch from user-specified ref_name or default branch
115117 if let Some ( ref_name) = & self . ref_name {
116- // User specified a branch, use that
117- Some ( format ! ( "refs/heads/{}" , ref_name. as_ref( ) . as_bstr( ) ) )
118+ Some ( Category :: LocalBranch . to_full_name ( ref_name. as_ref ( ) . as_bstr ( ) ) ?)
118119 } else {
119120 // For shallow clones without a specified ref, we need to determine the default branch.
120121 // We'll connect to get HEAD information. For Protocol V2, we need to explicitly list refs.
@@ -129,7 +130,7 @@ impl PrepareFetch {
129130 refs. iter ( ) . find_map ( |r| match r {
130131 gix_protocol:: handshake:: Ref :: Symbolic {
131132 full_ref_name, target, ..
132- } if full_ref_name == "HEAD" => Some ( target. to_string ( ) ) ,
133+ } if full_ref_name == "HEAD" => gix_ref :: FullName :: try_from ( target) . ok ( ) ,
133134 _ => None ,
134135 } )
135136 } )
@@ -143,9 +144,9 @@ impl PrepareFetch {
143144 repo. config
144145 . resolved
145146 . string ( crate :: config:: tree:: Init :: DEFAULT_BRANCH )
146- . and_then ( |name| name. to_str ( ) . ok ( ) . map ( |s| format ! ( "refs/heads/{}" , s ) ) )
147+ . and_then ( |name| Category :: LocalBranch . to_full_name ( name. as_bstr ( ) ) . ok ( ) )
147148 } )
148- . unwrap_or_else ( || "refs/heads/main" . to_string ( ) ) ;
149+ . unwrap_or_else ( || gix_ref :: FullName :: try_from ( "refs/heads/main" ) . expect ( "known to be valid" ) ) ;
149150
150151 // Drop the connection explicitly to release the borrow on remote
151152 drop ( connection) ;
@@ -156,11 +157,12 @@ impl PrepareFetch {
156157 None
157158 } ;
158159
159- // Set up refspec based on whether we're doing a single-branch shallow clone
160+ // Set up refspec based on whether we're doing a single-branch shallow clone,
161+ // which requires a single ref to match Git unless it's overridden.
160162 if remote. fetch_specs . is_empty ( ) {
161163 if let Some ( target_ref) = & target_ref {
162164 // Single-branch refspec for shallow clones
163- let short_name = target_ref. strip_prefix ( "refs/heads/" ) . unwrap_or ( target_ref . as_str ( ) ) ;
165+ let short_name = target_ref. shorten ( ) ;
164166 remote = remote
165167 . with_refspecs (
166168 Some ( format ! ( "+{target_ref}:refs/remotes/{remote_name}/{short_name}" ) . as_str ( ) ) ,
0 commit comments