Skip to content

Commit 24da857

Browse files
committed
fix!: make V1 shallow announcements possible (#1604)
1 parent 6c82f31 commit 24da857

File tree

8 files changed

+57
-10
lines changed

8 files changed

+57
-10
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

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

@@ -122,6 +123,7 @@ pub(crate) fn from_capabilities<'a>(
122123
pub(in crate::handshake::refs) fn parse_v1(
123124
num_initial_out_refs: usize,
124125
out_refs: &mut Vec<InternalRef>,
126+
out_shallow: &mut Vec<ShallowUpdate>,
125127
line: &BStr,
126128
) -> Result<(), Error> {
127129
let trimmed = line.trim_end();
@@ -162,7 +164,9 @@ pub(in crate::handshake::refs) fn parse_v1(
162164
let object = match gix_hash::ObjectId::from_hex(hex_hash.as_bytes()) {
163165
Ok(id) => id,
164166
Err(_) if hex_hash.as_bstr() == "shallow" => {
165-
todo!("shallow");
167+
let id = gix_hash::ObjectId::from_hex(path)?;
168+
out_shallow.push(ShallowUpdate::Shallow(id));
169+
return Ok(());
166170
}
167171
Err(err) => return Err(err.into()),
168172
};

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

+12-2
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,7 @@ dce0ea858eef7ff61ad345cc5cdac62203fb3c10 refs/tags/gix-commitgraph-v0.0.0
8888
)
8989
.await
9090
.expect("no failure from valid input");
91+
assert!(shallow.is_empty());
9192
assert_eq!(
9293
out,
9394
vec![
@@ -120,6 +121,7 @@ dce0ea858eef7ff61ad345cc5cdac62203fb3c10 refs/tags/gix-commitgraph-v0.0.0
120121

121122
#[maybe_async::test(feature = "blocking-client", async(feature = "async-client", async_std::test))]
122123
async fn extract_references_from_v1_refs_with_shallow() {
124+
use crate::fetch::response::ShallowUpdate;
123125
let input = &mut Fixture(
124126
"73a6868963993a3328e7d8fe94e5a6ac5078a944 HEAD
125127
21c9b7500cb144b3169a6537961ec2b9e865be81 MISSING_NAMESPACE_TARGET
@@ -131,7 +133,7 @@ shallow 21c9b7500cb144b3169a6537961ec2b9e865be81
131133
shallow dce0ea858eef7ff61ad345cc5cdac62203fb3c10"
132134
.as_bytes(),
133135
);
134-
let out = refs::from_v1_refs_received_as_part_of_handshake_and_capabilities(
136+
let (out, shallow) = refs::from_v1_refs_received_as_part_of_handshake_and_capabilities(
135137
input,
136138
Capabilities::from_bytes(b"\0symref=HEAD:refs/heads/main symref=MISSING_NAMESPACE_TARGET:(null)")
137139
.expect("valid capabilities")
@@ -140,6 +142,14 @@ shallow dce0ea858eef7ff61ad345cc5cdac62203fb3c10"
140142
)
141143
.await
142144
.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+
);
143153
assert_eq!(
144154
out,
145155
vec![

0 commit comments

Comments
 (0)