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