Skip to content

Commit db37b1a

Browse files
committed
feat: Add fetch::Arguments::is_stateless() to aid proper use of arguments.
When arguments are used, haves are reset every round in stateless protocols, while everything else is repeated. However, this also means that previously confirmed common commits aren't repeated unless this is specifically implemented by the user of `Arguments`. That caller can now easily determine if negotiations have to be compensated for. Please note that `Arguments` explicitly doesn't implement repeating of all prior arguments, which would also repeat a lot of *in-vain* haves.
1 parent 6e12806 commit db37b1a

File tree

3 files changed

+22
-0
lines changed

3 files changed

+22
-0
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ impl Arguments {
7878
pub fn can_use_include_tag(&self) -> bool {
7979
self.supports_include_tag
8080
}
81+
/// Return true if we will use a stateless mode of operation, which can be decided in conjunction with `transport_is_stateless`.
82+
///
83+
/// * we are always stateless if the transport is stateless, i.e. doesn't support multiple interactions with a single connection.
84+
/// * we are always stateless if the protocol version is `2`
85+
/// * otherwise we may be stateful.
86+
pub fn is_stateless(&self, transport_is_stateless: bool) -> bool {
87+
#[cfg(any(feature = "async-client", feature = "blocking-client"))]
88+
let res = transport_is_stateless || self.version == gix_transport::Protocol::V2;
89+
#[cfg(not(any(feature = "async-client", feature = "blocking-client")))]
90+
let res = transport_is_stateless;
91+
res
92+
}
8193

8294
/// Add the given `id` pointing to a commit to the 'want' list.
8395
///

gix-protocol/src/fetch/tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ mod arguments {
298298
let mut out = Vec::new();
299299
let mut t = transport(&mut out, true);
300300
let mut arguments = arguments_v2(["feature-a", "shallow"].iter().copied());
301+
assert!(arguments.is_stateless(true), "V2 is stateless…");
302+
assert!(arguments.is_stateless(false), "…in all cases");
301303

302304
arguments.deepen(1);
303305
arguments.deepen_relative();

gix-protocol/tests/fetch/response.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ mod v1 {
149149
async fn all() -> crate::Result {
150150
let (caps, _) = Capabilities::from_bytes(&b"7814e8a05a59c0cf5fb186661d1551c75d1299b5 HEAD\0multi_ack thin-pack filter side-band side-band-64k ofs-delta shallow deepen-since deepen-not deepen-relative no-progress include-tag multi_ack_detailed symref=HEAD:refs/heads/master object-format=sha1 agent=git/2.28.0"[..])?;
151151
let mut args = fetch::Arguments::new(Protocol::V1, Command::Fetch.default_features(Protocol::V1, &caps));
152+
assert!(
153+
args.is_stateless(true /* transport is stateless */),
154+
"V1 is stateless if the transport is connection oriented"
155+
);
156+
assert!(
157+
!args.is_stateless(false /* transport is stateless */),
158+
"otherwise V1 is stateful"
159+
);
152160
assert!(args.can_use_shallow());
153161
assert!(args.can_use_deepen());
154162
assert!(args.can_use_deepen_not());

0 commit comments

Comments
 (0)