Skip to content

Commit a22621d

Browse files
committed
improve fetchspec handling to be closer to what git does.
The current implementation was a bit hacky to mimick observed behaviour. These improvements make it easier to understand and bring it closer to what git actually seems to do.
1 parent 0c7f90d commit a22621d

File tree

3 files changed

+21
-25
lines changed

3 files changed

+21
-25
lines changed

Diff for: gix/src/remote/connection/fetch/negotiate.rs

+7-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::remote::fetch;
2-
use gix_refspec::RefSpec;
32

43
/// The way the negotiation is performed
54
#[derive(Copy, Clone)]
@@ -28,19 +27,15 @@ pub(crate) fn one_round(
2827
fetch_tags: crate::remote::fetch::Tags,
2928
arguments: &mut gix_protocol::fetch::Arguments,
3029
_previous_response: Option<&gix_protocol::fetch::Response>,
31-
wants_shallow_change: Option<(&fetch::Shallow, &[RefSpec])>,
30+
shallow: Option<&fetch::Shallow>,
3231
) -> Result<bool, Error> {
3332
let tag_refspec_to_ignore = fetch_tags
3433
.to_refspec()
3534
.filter(|_| matches!(fetch_tags, crate::remote::fetch::Tags::Included));
36-
let (shallow, non_wildcard_specs_only) = wants_shallow_change
37-
.map(|(a, b)| (Some(a), Some(b)))
38-
.unwrap_or_default();
39-
40-
if let Some(shallow) = shallow {
41-
if *shallow == fetch::Shallow::Deepen(0) {
42-
return Ok(true);
43-
}
35+
if let Some(fetch::Shallow::Deepen(0)) = shallow {
36+
// Avoid deepening (relative) with zero as it seems to upset the server. Git also doesn't actually
37+
// perform the negotiation for some reason (couldn't find it in code).
38+
return Ok(true);
4439
}
4540

4641
match algo {
@@ -57,14 +52,6 @@ pub(crate) fn one_round(
5752
}) {
5853
continue;
5954
}
60-
if non_wildcard_specs_only
61-
.and_then(|refspecs| mapping.spec_index.get(refspecs, &ref_map.extra_refspecs))
62-
.map_or(false, |spec| {
63-
spec.to_ref().local().map_or(false, |ref_| ref_.contains(&b'*'))
64-
})
65-
{
66-
continue;
67-
}
6855
let have_id = mapping.local.as_ref().and_then(|name| {
6956
repo.find_reference(name)
7057
.ok()
@@ -73,7 +60,7 @@ pub(crate) fn one_round(
7360
match have_id {
7461
Some(have_id) => {
7562
if let Some(want_id) = mapping.remote.as_id() {
76-
if want_id != have_id || wants_shallow_change.is_some() {
63+
if want_id != have_id {
7764
arguments.want(want_id);
7865
arguments.have(have_id);
7966
}
@@ -88,7 +75,7 @@ pub(crate) fn one_round(
8875
}
8976
}
9077

91-
if has_missing_tracking_branch || (wants_shallow_change.is_some() && arguments.is_empty()) {
78+
if has_missing_tracking_branch || (shallow.is_some() && arguments.is_empty()) {
9279
if let Ok(Some(r)) = repo.head_ref() {
9380
if let Some(id) = r.target().try_id() {
9481
arguments.have(id);

Diff for: gix/src/remote/connection/fetch/receive_pack.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ where
118118
con.remote.fetch_tags,
119119
&mut arguments,
120120
previous_response.as_ref(),
121-
(self.shallow != Shallow::NoChange)
122-
.then(|| (&self.shallow, con.remote.refspecs(remote::Direction::Fetch))),
121+
(self.shallow != Shallow::NoChange).then_some(&self.shallow),
123122
) {
124123
Ok(_) if arguments.is_empty() => {
125124
gix_protocol::indicate_end_of_interaction(&mut con.transport).await.ok();

Diff for: gix/tests/clone/mod.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::{remote, util::restricted};
22

33
#[cfg(feature = "blocking-network-client")]
44
mod blocking_io {
5+
use gix::bstr::BString;
56
use gix::config::tree::{Clone, Core, Init, Key};
67
use gix::remote::Direction;
78
use gix_object::bstr::ByteSlice;
@@ -25,9 +26,14 @@ mod blocking_io {
2526
let called_configure_remote = called_configure_remote;
2627
move |r| {
2728
called_configure_remote.store(true, std::sync::atomic::Ordering::Relaxed);
28-
let r = r
29-
.with_refspecs(Some("+refs/tags/b-tag:refs/tags/b-tag"), gix::remote::Direction::Fetch)?
30-
.with_fetch_tags(desired_fetch_tags);
29+
let mut r = r.with_fetch_tags(desired_fetch_tags);
30+
r.replace_refspecs(
31+
[
32+
BString::from(format!("refs/heads/main:refs/remotes/{remote_name}/main")),
33+
"+refs/tags/b-tag:refs/tags/b-tag".to_owned().into(),
34+
],
35+
Direction::Fetch,
36+
)?;
3137
Ok(r)
3238
}
3339
})
@@ -111,6 +117,10 @@ mod blocking_io {
111117
let tmp = gix_testtools::tempfile::TempDir::new()?;
112118
let (repo, _change) = gix::prepare_clone_bare(remote::repo("base").path(), tmp.path())?
113119
.with_shallow(Shallow::DepthAtRemote(2.try_into()?))
120+
.configure_remote(|mut r| {
121+
r.replace_refspecs(Some("refs/heads/main:refs/remotes/origin/main"), Direction::Fetch)?;
122+
Ok(r)
123+
})
114124
.fetch_only(gix::progress::Discard, &std::sync::atomic::AtomicBool::default())?;
115125

116126
assert!(repo.is_shallow());

0 commit comments

Comments
 (0)