Skip to content

Commit 612896d

Browse files
authored
Merge pull request #1604 from Byron/protocol-shallow-v1
shallow points in V1
2 parents 73a7d15 + 0d3b480 commit 612896d

File tree

9 files changed

+119
-12
lines changed

9 files changed

+119
-12
lines changed

gix-protocol/src/fetch/response/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,15 @@ impl Response {
203203
&self.shallows
204204
}
205205

206+
/// Append the given `updates` which may have been obtained from a
207+
/// (handshake::Outcome)[crate::handshake::Outcome::v1_shallow_updates].
208+
///
209+
/// In V2, these are received as part of the pack, but V1 sends them early, so we
210+
/// offer to re-integrate them here.
211+
pub fn append_v1_shallow_updates(&mut self, updates: Option<Vec<ShallowUpdate>>) {
212+
self.shallows.extend(updates.into_iter().flatten());
213+
}
214+
206215
/// Return all wanted-refs [parsed previously][Response::from_line_reader()].
207216
pub fn wanted_refs(&self) -> &[WantedRef] {
208217
&self.wanted_refs

gix-protocol/src/fetch_fn.rs

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ where
7171
let crate::handshake::Outcome {
7272
server_protocol_version: protocol_version,
7373
refs,
74+
v1_shallow_updates: _ignored_shallow_updates_as_it_is_deprecated,
7475
capabilities,
7576
} = crate::fetch::handshake(
7677
&mut transport,

gix-protocol/src/handshake/function.rs

+5
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,14 @@ where
9595
(actual_protocol, parsed_refs, capabilities)
9696
}; // this scope is needed, see https://github.com/rust-lang/rust/issues/76149
9797

98+
let (refs, v1_shallow_updates) = refs
99+
.map(|(refs, shallow)| (Some(refs), Some(shallow)))
100+
.unwrap_or_default();
101+
98102
Ok(Outcome {
99103
server_protocol_version,
100104
refs,
105+
v1_shallow_updates,
101106
capabilities,
102107
})
103108
}

gix-protocol/src/handshake/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ pub enum Ref {
5454
pub struct Outcome {
5555
/// The protocol version the server responded with. It might have downgraded the desired version.
5656
pub server_protocol_version: gix_transport::Protocol,
57-
/// The references reported as part of the Protocol::V1 handshake, or `None` otherwise as V2 requires a separate request.
57+
/// The references reported as part of the `Protocol::V1` handshake, or `None` otherwise as V2 requires a separate request.
5858
pub refs: Option<Vec<Ref>>,
59+
/// Shallow updates as part of the `Protocol::V1`, to shallow a particular object.
60+
/// Note that unshallowing isn't supported here.
61+
pub v1_shallow_updates: Option<Vec<ShallowUpdate>>,
5962
/// The server capabilities.
6063
pub capabilities: Capabilities,
6164
}
@@ -93,6 +96,7 @@ mod error {
9396
}
9497
}
9598
}
99+
use crate::fetch::response::ShallowUpdate;
96100
pub use error::Error;
97101

98102
pub(crate) mod function;

gix-protocol/src/handshake/refs/async_io.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::fetch::response::ShallowUpdate;
12
use crate::handshake::{refs, refs::parse::Error, Ref};
23

34
/// Parse refs from the given input line by line. Protocol V2 is required for this to succeed.
@@ -26,8 +27,9 @@ pub async fn from_v2_refs(in_refs: &mut dyn gix_transport::client::ReadlineBufRe
2627
pub async fn from_v1_refs_received_as_part_of_handshake_and_capabilities<'a>(
2728
in_refs: &mut dyn gix_transport::client::ReadlineBufRead,
2829
capabilities: impl Iterator<Item = gix_transport::client::capabilities::Capability<'a>>,
29-
) -> Result<Vec<Ref>, refs::parse::Error> {
30+
) -> Result<(Vec<Ref>, Vec<ShallowUpdate>), refs::parse::Error> {
3031
let mut out_refs = refs::shared::from_capabilities(capabilities)?;
32+
let mut out_shallow = Vec::new();
3133
let number_of_possible_symbolic_refs_for_lookup = out_refs.len();
3234

3335
while let Some(line) = in_refs
@@ -37,7 +39,12 @@ pub async fn from_v1_refs_received_as_part_of_handshake_and_capabilities<'a>(
3739
.transpose()?
3840
.and_then(|l| l.as_bstr())
3941
{
40-
refs::shared::parse_v1(number_of_possible_symbolic_refs_for_lookup, &mut out_refs, line)?;
42+
refs::shared::parse_v1(
43+
number_of_possible_symbolic_refs_for_lookup,
44+
&mut out_refs,
45+
&mut out_shallow,
46+
line,
47+
)?;
4148
}
42-
Ok(out_refs.into_iter().map(Into::into).collect())
49+
Ok((out_refs.into_iter().map(Into::into).collect(), out_shallow))
4350
}

gix-protocol/src/handshake/refs/blocking_io.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::fetch::response::ShallowUpdate;
12
use crate::handshake::{refs, refs::parse::Error, Ref};
23

34
/// Parse refs from the given input line by line. Protocol V2 is required for this to succeed.
@@ -20,12 +21,18 @@ pub fn from_v2_refs(in_refs: &mut dyn gix_transport::client::ReadlineBufRead) ->
2021
pub fn from_v1_refs_received_as_part_of_handshake_and_capabilities<'a>(
2122
in_refs: &mut dyn gix_transport::client::ReadlineBufRead,
2223
capabilities: impl Iterator<Item = gix_transport::client::capabilities::Capability<'a>>,
23-
) -> Result<Vec<Ref>, Error> {
24+
) -> Result<(Vec<Ref>, Vec<ShallowUpdate>), Error> {
2425
let mut out_refs = refs::shared::from_capabilities(capabilities)?;
26+
let mut out_shallow = Vec::new();
2527
let number_of_possible_symbolic_refs_for_lookup = out_refs.len();
2628

2729
while let Some(line) = in_refs.readline().transpose()?.transpose()?.and_then(|l| l.as_bstr()) {
28-
refs::shared::parse_v1(number_of_possible_symbolic_refs_for_lookup, &mut out_refs, line)?;
30+
refs::shared::parse_v1(
31+
number_of_possible_symbolic_refs_for_lookup,
32+
&mut out_refs,
33+
&mut out_shallow,
34+
line,
35+
)?;
2936
}
30-
Ok(out_refs.into_iter().map(Into::into).collect())
37+
Ok((out_refs.into_iter().map(Into::into).collect(), out_shallow))
3138
}

gix-protocol/src/handshake/refs/shared.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use bstr::{BStr, BString, ByteSlice};
2-
1+
use crate::fetch::response::ShallowUpdate;
32
use crate::handshake::{refs::parse::Error, Ref};
3+
use bstr::{BStr, BString, ByteSlice};
44

55
impl From<InternalRef> for Ref {
66
fn from(v: InternalRef) -> Self {
@@ -123,6 +123,7 @@ pub(crate) fn from_capabilities<'a>(
123123
pub(in crate::handshake::refs) fn parse_v1(
124124
num_initial_out_refs: usize,
125125
out_refs: &mut Vec<InternalRef>,
126+
out_shallow: &mut Vec<ShallowUpdate>,
126127
line: &BStr,
127128
) -> Result<(), Error> {
128129
let trimmed = line.trim_end();
@@ -160,7 +161,15 @@ pub(in crate::handshake::refs) fn parse_v1(
160161
});
161162
}
162163
None => {
163-
let object = gix_hash::ObjectId::from_hex(hex_hash.as_bytes())?;
164+
let object = match gix_hash::ObjectId::from_hex(hex_hash.as_bytes()) {
165+
Ok(id) => id,
166+
Err(_) if hex_hash.as_bstr() == "shallow" => {
167+
let id = gix_hash::ObjectId::from_hex(path)?;
168+
out_shallow.push(ShallowUpdate::Shallow(id));
169+
return Ok(());
170+
}
171+
Err(err) => return Err(err.into()),
172+
};
164173
match out_refs
165174
.iter()
166175
.take(num_initial_out_refs)

gix-protocol/src/handshake/refs/tests.rs

+63-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ dce0ea858eef7ff61ad345cc5cdac62203fb3c10 refs/tags/gix-commitgraph-v0.0.0
7979
21c9b7500cb144b3169a6537961ec2b9e865be81 refs/tags/gix-commitgraph-v0.0.0^{}"
8080
.as_bytes(),
8181
);
82-
let out = refs::from_v1_refs_received_as_part_of_handshake_and_capabilities(
82+
let (out, shallow) = refs::from_v1_refs_received_as_part_of_handshake_and_capabilities(
8383
input,
8484
Capabilities::from_bytes(b"\0symref=HEAD:refs/heads/main symref=MISSING_NAMESPACE_TARGET:(null)")
8585
.expect("valid capabilities")
@@ -88,6 +88,68 @@ dce0ea858eef7ff61ad345cc5cdac62203fb3c10 refs/tags/gix-commitgraph-v0.0.0
8888
)
8989
.await
9090
.expect("no failure from valid input");
91+
assert!(shallow.is_empty());
92+
assert_eq!(
93+
out,
94+
vec![
95+
Ref::Symbolic {
96+
full_ref_name: "HEAD".into(),
97+
target: "refs/heads/main".into(),
98+
tag: None,
99+
object: oid("73a6868963993a3328e7d8fe94e5a6ac5078a944")
100+
},
101+
Ref::Direct {
102+
full_ref_name: "MISSING_NAMESPACE_TARGET".into(),
103+
object: oid("21c9b7500cb144b3169a6537961ec2b9e865be81")
104+
},
105+
Ref::Direct {
106+
full_ref_name: "refs/heads/main".into(),
107+
object: oid("73a6868963993a3328e7d8fe94e5a6ac5078a944")
108+
},
109+
Ref::Direct {
110+
full_ref_name: "refs/pull/13/head".into(),
111+
object: oid("8e472f9ccc7d745927426cbb2d9d077de545aa4e")
112+
},
113+
Ref::Peeled {
114+
full_ref_name: "refs/tags/gix-commitgraph-v0.0.0".into(),
115+
tag: oid("dce0ea858eef7ff61ad345cc5cdac62203fb3c10"),
116+
object: oid("21c9b7500cb144b3169a6537961ec2b9e865be81")
117+
},
118+
]
119+
);
120+
}
121+
122+
#[maybe_async::test(feature = "blocking-client", async(feature = "async-client", async_std::test))]
123+
async fn extract_references_from_v1_refs_with_shallow() {
124+
use crate::fetch::response::ShallowUpdate;
125+
let input = &mut Fixture(
126+
"73a6868963993a3328e7d8fe94e5a6ac5078a944 HEAD
127+
21c9b7500cb144b3169a6537961ec2b9e865be81 MISSING_NAMESPACE_TARGET
128+
73a6868963993a3328e7d8fe94e5a6ac5078a944 refs/heads/main
129+
8e472f9ccc7d745927426cbb2d9d077de545aa4e refs/pull/13/head
130+
dce0ea858eef7ff61ad345cc5cdac62203fb3c10 refs/tags/gix-commitgraph-v0.0.0
131+
21c9b7500cb144b3169a6537961ec2b9e865be81 refs/tags/gix-commitgraph-v0.0.0^{}
132+
shallow 21c9b7500cb144b3169a6537961ec2b9e865be81
133+
shallow dce0ea858eef7ff61ad345cc5cdac62203fb3c10"
134+
.as_bytes(),
135+
);
136+
let (out, shallow) = refs::from_v1_refs_received_as_part_of_handshake_and_capabilities(
137+
input,
138+
Capabilities::from_bytes(b"\0symref=HEAD:refs/heads/main symref=MISSING_NAMESPACE_TARGET:(null)")
139+
.expect("valid capabilities")
140+
.0
141+
.iter(),
142+
)
143+
.await
144+
.expect("no failure from valid input");
145+
146+
assert_eq!(
147+
shallow,
148+
vec![
149+
ShallowUpdate::Shallow(oid("21c9b7500cb144b3169a6537961ec2b9e865be81")),
150+
ShallowUpdate::Shallow(oid("dce0ea858eef7ff61ad345cc5cdac62203fb3c10"))
151+
]
152+
);
91153
assert_eq!(
92154
out,
93155
vec![

gix/src/remote/connection/fetch/receive_pack.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ where
100100
});
101101
}
102102

103+
let v1_shallow_updates = self.ref_map.handshake.v1_shallow_updates.take();
103104
let handshake = &self.ref_map.handshake;
104105
let protocol_version = handshake.server_protocol_version;
105106

@@ -253,7 +254,9 @@ where
253254
drop(graph_repo);
254255
drop(negotiate_span);
255256

256-
let previous_response = previous_response.expect("knowledge of a pack means a response was received");
257+
let mut previous_response =
258+
previous_response.expect("knowledge of a pack means a response was received");
259+
previous_response.append_v1_shallow_updates(v1_shallow_updates);
257260
if !previous_response.shallow_updates().is_empty() && shallow_lock.is_none() {
258261
let reject_shallow_remote = repo
259262
.config

0 commit comments

Comments
 (0)