Skip to content

Commit c331afc

Browse files
committed
refactor
1 parent d2cd2ef commit c331afc

File tree

4 files changed

+36
-24
lines changed

4 files changed

+36
-24
lines changed

gitoxide-core/src/repository/fetch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ pub(crate) mod function {
320320
err,
321321
"server sent {} tips, {} were filtered due to {} refspec(s).",
322322
map.remote_refs.len(),
323-
map.remote_refs.len() - map.mappings.len(),
323+
map.remote_refs.len().saturating_sub(map.mappings.len()),
324324
refspecs.len()
325325
)?;
326326
}

gix/src/clone/fetch/mod.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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
@@ -107,14 +110,13 @@ impl PrepareFetch {
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).
109112
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();
112115

113116
let target_ref = if use_single_branch_for_shallow {
114117
// Determine target branch from user-specified ref_name or default branch
115118
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())?)
118120
} else {
119121
// For shallow clones without a specified ref, we need to determine the default branch.
120122
// We'll connect to get HEAD information. For Protocol V2, we need to explicitly list refs.
@@ -129,7 +131,7 @@ impl PrepareFetch {
129131
refs.iter().find_map(|r| match r {
130132
gix_protocol::handshake::Ref::Symbolic {
131133
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(),
133135
_ => None,
134136
})
135137
})
@@ -143,9 +145,9 @@ impl PrepareFetch {
143145
repo.config
144146
.resolved
145147
.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())
147149
})
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"));
149151

150152
// Drop the connection explicitly to release the borrow on remote
151153
drop(connection);
@@ -156,11 +158,12 @@ impl PrepareFetch {
156158
None
157159
};
158160

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.
160163
if remote.fetch_specs.is_empty() {
161164
if let Some(target_ref) = &target_ref {
162165
// 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();
164167
remote = remote
165168
.with_refspecs(
166169
Some(format!("+{target_ref}:refs/remotes/{remote_name}/{short_name}").as_str()),

gix/src/config/tree/sections/init.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55

66
impl Init {
77
/// The `init.defaultBranch` key.
8+
// TODO: review its usage for cases where this key is not set - sometimes it's 'master', sometimes it's 'main'.
89
pub const DEFAULT_BRANCH: keys::Any = keys::Any::new("defaultBranch", &config::Tree::INIT)
910
.with_deviation("If not set, we use `main` instead of `master`");
1011
}

gix/tests/gix/clone.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ use crate::{remote, util::restricted};
44
mod blocking_io {
55
use std::{borrow::Cow, path::Path, sync::atomic::AtomicBool};
66

7+
use crate::{
8+
remote,
9+
util::{hex_to_id, restricted},
10+
};
711
use gix::{
812
bstr::BString,
913
config::tree::{Clone, Core, Init, Key},
@@ -14,11 +18,7 @@ mod blocking_io {
1418
};
1519
use gix_object::bstr::ByteSlice;
1620
use gix_ref::TargetRef;
17-
18-
use crate::{
19-
remote,
20-
util::{hex_to_id, restricted},
21-
};
21+
use gix_refspec::parse::Operation;
2222

2323
#[test]
2424
fn fetch_shallow_no_checkout_then_unshallow() -> crate::Result {
@@ -104,15 +104,14 @@ mod blocking_io {
104104

105105
// The refspec should be for a single branch (main), not a wildcard
106106
let refspec_str = refspecs[0].to_str().expect("valid utf8");
107-
assert!(
108-
!refspec_str.contains("*"),
109-
"shallow clone refspec should not use wildcard: {}",
110-
refspec_str
111-
);
112-
assert!(
113-
refspec_str.contains("refs/heads/main"),
114-
"shallow clone refspec should reference the main branch: {}",
115-
refspec_str
107+
assert_eq!(
108+
refspec_str,
109+
if cfg!(windows) {
110+
"+refs/heads/master:refs/remotes/origin/master"
111+
} else {
112+
"+refs/heads/main:refs/remotes/origin/main"
113+
},
114+
"shallow clone refspec should not use wildcard and should be the main branch: {refspec_str}"
116115
);
117116

118117
Ok(())
@@ -238,7 +237,16 @@ mod blocking_io {
238237
fn from_non_shallow_by_deepen_exclude_then_deepen_to_unshallow() -> crate::Result {
239238
let tmp = gix_testtools::tempfile::TempDir::new()?;
240239
let excluded_leaf_refs = ["g", "h", "j"];
240+
241241
let (repo, _change) = gix::prepare_clone_bare(remote::repo("base").path(), tmp.path())?
242+
.with_fetch_options(gix::remote::ref_map::Options {
243+
extra_refspecs: vec![gix::refspec::parse(
244+
"refs/heads/*:refs/remotes/origin/*".into(),
245+
Operation::Fetch,
246+
)?
247+
.into()],
248+
..Default::default()
249+
})
242250
.with_shallow(Shallow::Exclude {
243251
remote_refs: excluded_leaf_refs
244252
.into_iter()

0 commit comments

Comments
 (0)