| @@ -2,6 +2,7 @@ use crate::{ · 1 unmodified line |
| 2 | 2 | bstr::{BString, ByteSlice}, |
| 3 | 3 | clone::PrepareFetch, |
| 4 | 4 | }; |
| 5 | +use gix_ref::Category; |
| 5 | 6 | |
| 6 | 7 | /// The error returned by [`PrepareFetch::fetch_only()`]. |
| 7 | 8 | #[derive(Debug, thiserror::Error)] |
| @@ -49,6 +50,8 @@ pub enum Error { · 41 unmodified lines |
| 49 | 50 | CommitterOrFallback(#[from] crate::config::time::Error), |
| 50 | 51 | #[error(transparent)] |
| 51 | 52 | RefMap(#[from] crate::remote::ref_map::Error), |
| 53 | + #[error(transparent)] |
| 54 | + ReferenceName(#[from] gix_validate::reference::name::Error), |
| 52 | 55 | } |
| 53 | 56 | |
| 54 | 57 | /// Modification |
| @@ -107,14 +110,13 @@ impl PrepareFetch { · 52 unmodified lines |
| 107 | 110 | // For shallow clones without custom configuration, we'll use a single-branch refspec |
| 108 | 111 | // to match git's behavior (matching git's single-branch behavior for shallow clones). |
| 109 | 112 | let use_single_branch_for_shallow = self.shallow != remote::fetch::Shallow::NoChange |
| 110 | | − && self.configure_remote.is_none() |
| 111 | | − && remote.fetch_specs.is_empty(); |
| 113 | + && remote.fetch_specs.is_empty() |
| 114 | + && self.fetch_options.extra_refspecs.is_empty(); |
| 112 | 115 | |
| 113 | 116 | let target_ref = if use_single_branch_for_shallow { |
| 114 | 117 | // Determine target branch from user-specified ref_name or default branch |
| 115 | 118 | 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())) |
| 119 | + Some(Category::LocalBranch.to_full_name(ref_name.as_ref().as_bstr())?) |
| 118 | 120 | } else { |
| 119 | 121 | // For shallow clones without a specified ref, we need to determine the default branch. |
| 120 | 122 | // We'll connect to get HEAD information. For Protocol V2, we need to explicitly list refs. |
| @@ -129,7 +131,7 @@ impl PrepareFetch { · 8 unmodified lines |
| 129 | 131 | refs.iter().find_map(|r| match r { |
| 130 | 132 | gix_protocol::handshake::Ref::Symbolic { |
| 131 | 133 | full_ref_name, target, .. |
| 132 | | − } if full_ref_name == "HEAD" => Some(target.to_string()), |
| 134 | + } if full_ref_name == "HEAD" => gix_ref::FullName::try_from(target).ok(), |
| 133 | 135 | _ => None, |
| 134 | 136 | }) |
| 135 | 137 | }) |
| @@ -143,9 +145,9 @@ impl PrepareFetch { · 7 unmodified lines |
| 143 | 145 | repo.config |
| 144 | 146 | .resolved |
| 145 | 147 | .string(crate::config::tree::Init::DEFAULT_BRANCH) |
| 146 | | − .and_then(|name| name.to_str().ok().map(|s| format!("refs/heads/{}", s))) |
| 148 | + .and_then(|name| Category::LocalBranch.to_full_name(name.as_bstr()).ok()) |
| 147 | 149 | }) |
| 148 | | − .unwrap_or_else(|| "refs/heads/main".to_string()); |
| 150 | + .unwrap_or_else(|| gix_ref::FullName::try_from("refs/heads/main").expect("known to be valid")); |
| 149 | 151 | |
| 150 | 152 | // Drop the connection explicitly to release the borrow on remote |
| 151 | 153 | drop(connection); |
| @@ -156,11 +158,12 @@ impl PrepareFetch { · 4 unmodified lines |
| 156 | 158 | None |
| 157 | 159 | }; |
| 158 | 160 | |
| 159 | | − // Set up refspec based on whether we're doing a single-branch shallow clone |
| 161 | + // Set up refspec based on whether we're doing a single-branch shallow clone, |
| 162 | + // which requires a single ref to match Git unless it's overridden. |
| 160 | 163 | if remote.fetch_specs.is_empty() { |
| 161 | 164 | if let Some(target_ref) = &target_ref { |
| 162 | 165 | // Single-branch refspec for shallow clones |
| 163 | | − let short_name = target_ref.strip_prefix("refs/heads/").unwrap_or(target_ref.as_str()); |
| 166 | + let short_name = target_ref.shorten(); |
| 164 | 167 | remote = remote |
| 165 | 168 | .with_refspecs( |
| 166 | 169 | Some(format!("+{target_ref}:refs/remotes/{remote_name}/{short_name}").as_str()), |