From d1f9c63f8a79dcb00766d94edda80ed9add724ea Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 2 Aug 2023 13:36:24 +0200 Subject: [PATCH] feat: add `fetch::Arguments::add_feature()` for unconditional additions of arguments that are supposed to be features. This differentiation is important to support V1 and V2 correctly, which have a different notion of features with V1 special-casing them, and V2 just sees everything as arguments. --- .../src/fetch/arguments/blocking_io.rs | 4 +-- gix-protocol/src/fetch/arguments/mod.rs | 32 ++++++++++++------- gix-protocol/src/fetch/tests.rs | 5 +++ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/gix-protocol/src/fetch/arguments/blocking_io.rs b/gix-protocol/src/fetch/arguments/blocking_io.rs index 571792148f1..c946d46e144 100644 --- a/gix-protocol/src/fetch/arguments/blocking_io.rs +++ b/gix-protocol/src/fetch/arguments/blocking_io.rs @@ -45,9 +45,7 @@ impl Arguments { } transport.invoke( Command::Fetch.as_str(), - self.features - .iter() - .filter_map(|(k, v)| v.as_ref().map(|v| (*k, Some(v.as_ref())))), + self.features.iter().filter(|(_, v)| v.is_some()).cloned(), Some(std::mem::replace(&mut self.args, retained_state).into_iter()), ) } diff --git a/gix-protocol/src/fetch/arguments/mod.rs b/gix-protocol/src/fetch/arguments/mod.rs index d887492b4a9..50145bb1504 100644 --- a/gix-protocol/src/fetch/arguments/mod.rs +++ b/gix-protocol/src/fetch/arguments/mod.rs @@ -165,20 +165,30 @@ impl Arguments { pub fn use_include_tag(&mut self) { debug_assert!(self.supports_include_tag, "'include-tag' feature required"); if self.supports_include_tag { - match self.version { - gix_transport::Protocol::V0 | gix_transport::Protocol::V1 => { - let features = self - .features_for_first_want - .as_mut() - .expect("call use_include_tag before want()"); - features.push("include-tag".into()) - } - gix_transport::Protocol::V2 => { - self.args.push("include-tag".into()); - } + self.add_feature("include-tag"); + } + } + + /// Add the given `feature`, unconditionally. + /// + /// Note that sending an unknown or unsupported feature may cause the remote to terminate + /// the connection. Use this method if you know what you are doing *and* there is no specialized + /// method for this, e.g. [`Self::use_include_tag()`]. + pub fn add_feature(&mut self, feature: &str) { + match self.version { + gix_transport::Protocol::V0 | gix_transport::Protocol::V1 => { + let features = self + .features_for_first_want + .as_mut() + .expect("call add_feature before first want()"); + features.push(feature.into()) + } + gix_transport::Protocol::V2 => { + self.args.push(feature.into()); } } } + fn prefixed(&mut self, prefix: &str, value: impl fmt::Display) { self.args.push(format!("{prefix}{value}").into()); } diff --git a/gix-protocol/src/fetch/tests.rs b/gix-protocol/src/fetch/tests.rs index 80dc752dd2d..93cf6e8db78 100644 --- a/gix-protocol/src/fetch/tests.rs +++ b/gix-protocol/src/fetch/tests.rs @@ -319,6 +319,7 @@ mod arguments { assert!(arguments.is_stateless(true), "V2 is stateless…"); assert!(arguments.is_stateless(false), "…in all cases"); + arguments.add_feature("no-progress"); arguments.deepen(1); arguments.deepen_relative(); arguments.want(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c907")); @@ -329,6 +330,7 @@ mod arguments { b"0012command=fetch 0001000ethin-pack 000eofs-delta +0010no-progress 000ddeepen 1 0014deepen-relative 0032want 7b333369de1221f9bfbbe03a3a13e9a09bc1c907 @@ -347,6 +349,7 @@ mod arguments { let mut t = transport(&mut out, *is_stateful); let mut arguments = arguments_v2(Some("shallow")); + arguments.add_feature("no-progress"); arguments.deepen(1); arguments.deepen_since(12345); arguments.shallow(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff")); @@ -362,6 +365,7 @@ mod arguments { b"0012command=fetch 0001000ethin-pack 000eofs-delta +0010no-progress 000ddeepen 1 0017deepen-since 12345 0035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff @@ -371,6 +375,7 @@ mod arguments { 00000012command=fetch 0001000ethin-pack 000eofs-delta +0010no-progress 000ddeepen 1 0017deepen-since 12345 0035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff