Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
RUSTSEC-2024-0335
Merged lorenz opened 1 year ago

See https://rustsec.org/advisories/RUSTSEC-2024-0335.

Solution is to upgrade gix-transport to ≥ 0.42.

8 files changed +137 -114 b2992814 a4e10f03
modified Cargo.lock
@@ -428,15 +428,6 @@ dependencies = [
]

[[package]]
-
name = "btoi"
-
version = "0.4.3"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad"
-
dependencies = [
-
 "num-traits",
-
]
-

-
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -821,21 +812,9 @@ dependencies = [

[[package]]
name = "faster-hex"
-
version = "0.8.1"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "239f7bfb930f820ab16a9cd95afc26f88264cf6905c960b340a615384aa3338a"
-
dependencies = [
-
 "serde",
-
]
-

-
[[package]]
-
name = "faster-hex"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183"
-
dependencies = [
-
 "serde",
-
]

[[package]]
name = "fastrand"
@@ -1024,13 +1003,13 @@ dependencies = [

[[package]]
name = "gix-actor"
-
version = "0.28.1"
+
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "2eadca029ef716b4378f7afb19f7ee101fde9e58ba1f1445971315ac866db417"
+
checksum = "45c3a3bde455ad2ee8ba8a195745241ce0b770a8a26faae59fcf409d01b28c46"
dependencies = [
 "bstr",
-
 "btoi",
 "gix-date",
+
 "gix-utils",
 "itoa",
 "thiserror",
 "winnow",
@@ -1047,24 +1026,27 @@ dependencies = [

[[package]]
name = "gix-command"
-
version = "0.2.10"
+
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3c576cfbf577f72c097b5f88aedea502cd62952bdc1fb3adcab4531d5525a4c7"
+
checksum = "f90009020dc4b3de47beed28e1334706e0a330ddd17f5cfeb097df3b15a54b77"
dependencies = [
 "bstr",
+
 "gix-path",
+
 "gix-trace",
+
 "shell-words",
]

[[package]]
name = "gix-commitgraph"
-
version = "0.22.1"
+
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "85a7007ba021f059803afaf6f8a48872422abc20550ac12ede6ddea2936cec36"
+
checksum = "f7b102311085da4af18823413b5176d7c500fb2272eaf391cfa8635d8bcb12c4"
dependencies = [
 "bstr",
 "gix-chunk",
 "gix-features",
 "gix-hash",
-
 "memmap2 0.9.4",
+
 "memmap2",
 "thiserror",
]

@@ -1083,9 +1065,9 @@ dependencies = [

[[package]]
name = "gix-credentials"
-
version = "0.21.0"
+
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "1c5c5d74069b842a1861e581027ac6b7ad9ff66f5911c89b9f45484d7ebda6a4"
+
checksum = "5c70146183bd3c7119329a3c7392d1aa0e0adbe48d727f4df31828fe6d8fdaa1"
dependencies = [
 "bstr",
 "gix-command",
@@ -1093,6 +1075,7 @@ dependencies = [
 "gix-path",
 "gix-prompt",
 "gix-sec",
+
 "gix-trace",
 "gix-url",
 "thiserror",
]
@@ -1111,10 +1094,11 @@ dependencies = [

[[package]]
name = "gix-diff"
-
version = "0.37.0"
+
version = "0.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "931394f69fb8c9ed6afc0aae3487bd869e936339bcc13ed8884472af072e0554"
+
checksum = "a5fbc24115b957346cd23fb0f47d830eb799c46c89cdcf2f5acc9bf2938c2d01"
dependencies = [
+
 "bstr",
 "gix-hash",
 "gix-object",
 "thiserror",
@@ -1122,14 +1106,15 @@ dependencies = [

[[package]]
name = "gix-features"
-
version = "0.36.1"
+
version = "0.38.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4d46a4a5c6bb5bebec9c0d18b65ada20e6517dbd7cf855b87dd4bbdce3a771b2"
+
checksum = "db4254037d20a247a0367aa79333750146a369719f0c6617fec4f5752cc62b37"
dependencies = [
 "crc32fast",
 "flate2",
 "gix-hash",
 "gix-trace",
+
 "gix-utils",
 "libc",
 "prodash",
 "sha1_smol",
@@ -1139,28 +1124,29 @@ dependencies = [

[[package]]
name = "gix-fs"
-
version = "0.8.1"
+
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "20e86eb040f5776a5ade092282e51cdcad398adb77d948b88d17583c2ae4e107"
+
checksum = "e2184c40e7910529677831c8b481acf788ffd92427ed21fad65b6aa637e631b8"
dependencies = [
 "gix-features",
+
 "gix-utils",
]

[[package]]
name = "gix-hash"
-
version = "0.13.3"
+
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "1f8cf8c2266f63e582b7eb206799b63aa5fa68ee510ad349f637dfe2d0653de0"
+
checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e"
dependencies = [
-
 "faster-hex 0.9.0",
+
 "faster-hex",
 "thiserror",
]

[[package]]
name = "gix-hashtable"
-
version = "0.4.1"
+
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "feb61880816d7ec4f0b20606b498147d480860ddd9133ba542628df2f548d3ca"
+
checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242"
dependencies = [
 "gix-hash",
 "hashbrown",
@@ -1169,16 +1155,16 @@ dependencies = [

[[package]]
name = "gix-object"
-
version = "0.38.0"
+
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "740f2a44267f58770a1cb3a3d01d14e67b089c7136c48d4bddbb3cfd2bf86a51"
+
checksum = "3d4f8efae72030df1c4a81d02dbe2348e748d9b9a11e108ed6efbd846326e051"
dependencies = [
 "bstr",
-
 "btoi",
 "gix-actor",
 "gix-date",
 "gix-features",
 "gix-hash",
+
 "gix-utils",
 "gix-validate",
 "itoa",
 "smallvec",
@@ -1188,13 +1174,14 @@ dependencies = [

[[package]]
name = "gix-odb"
-
version = "0.54.0"
+
version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8630b56cb80d8fa684d383dad006a66401ee8314e12fbf0e566ddad8c115143b"
+
checksum = "e8bbb43d2fefdc4701ffdf9224844d05b136ae1b9a73c2f90710c8dd27a93503"
dependencies = [
 "arc-swap",
 "gix-date",
 "gix-features",
+
 "gix-fs",
 "gix-hash",
 "gix-object",
 "gix-pack",
@@ -1207,9 +1194,9 @@ dependencies = [

[[package]]
name = "gix-pack"
-
version = "0.44.0"
+
version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "1431ba2e30deff1405920693d54ab231c88d7c240dd6ccc936ee223d8f8697c3"
+
checksum = "b58bad27c7677fa6b587aab3a1aca0b6c97373bd371a0a4290677c838c9bcaf1"
dependencies = [
 "gix-chunk",
 "gix-diff",
@@ -1220,7 +1207,7 @@ dependencies = [
 "gix-path",
 "gix-tempfile",
 "gix-traverse",
-
 "memmap2 0.7.1",
+
 "memmap2",
 "parking_lot",
 "smallvec",
 "thiserror",
@@ -1228,12 +1215,13 @@ dependencies = [

[[package]]
name = "gix-packetline"
-
version = "0.16.7"
+
version = "0.17.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8a8384b1e964151aff0d5632dd9b191059d07dff358b96bd940f1b452600d7ab"
+
checksum = "b70486beda0903b6d5b65dfa6e40585098cdf4e6365ca2dff4f74c387354a515"
dependencies = [
 "bstr",
-
 "faster-hex 0.8.1",
+
 "faster-hex",
+
 "gix-trace",
 "thiserror",
]

@@ -1252,9 +1240,9 @@ dependencies = [

[[package]]
name = "gix-prompt"
-
version = "0.7.0"
+
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5c9a913769516f5e9d937afac206fb76428e3d7238e538845842887fda584678"
+
checksum = "f5325eb17ce7b5e5d25dec5c2315d642a09d55b9888b3bf46b7d72e1621a55d8"
dependencies = [
 "gix-command",
 "gix-config-value",
@@ -1265,17 +1253,17 @@ dependencies = [

[[package]]
name = "gix-protocol"
-
version = "0.41.1"
+
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "391e3feabdfa5f90dad6673ce59e3291ac28901b2ff248d86c5a7fbde0391e0e"
+
checksum = "aed3bb6179835a3250403baa9d7022579e559fc45f2efc416d9de1a14b5acf11"
dependencies = [
 "bstr",
-
 "btoi",
 "gix-credentials",
 "gix-date",
 "gix-features",
 "gix-hash",
 "gix-transport",
+
 "gix-utils",
 "maybe-async",
 "thiserror",
 "winnow",
@@ -1294,9 +1282,9 @@ dependencies = [

[[package]]
name = "gix-revwalk"
-
version = "0.9.0"
+
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a16d8c892e4cd676d86f0265bf9d40cefd73d8d94f86b213b8b77d50e77efae0"
+
checksum = "e0a7d393ae814eeaae41a333c0ff684b243121cc61ccdc5bbe9897094588047d"
dependencies = [
 "gix-commitgraph",
 "gix-date",
@@ -1321,9 +1309,9 @@ dependencies = [

[[package]]
name = "gix-tempfile"
-
version = "11.0.1"
+
version = "13.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "388dd29114a86ec69b28d1e26d6d63a662300ecf61ab3f4cc578f7d7dc9e7e23"
+
checksum = "a761d76594f4443b675e85928e4902dec333273836bd386906f01e7e346a0d11"
dependencies = [
 "gix-fs",
 "libc",
@@ -1340,9 +1328,9 @@ checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e"

[[package]]
name = "gix-transport"
-
version = "0.38.0"
+
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "2f209a93364e24f20319751bc11092272e2f3fe82bb72592b2822679cf5be752"
+
checksum = "9d2f783b2fe86bf2a8cf1f3b8669d65b01ab4932f32cc0101d3893e1b16a3bd6"
dependencies = [
 "bstr",
 "gix-command",
@@ -1356,10 +1344,11 @@ dependencies = [

[[package]]
name = "gix-traverse"
-
version = "0.34.0"
+
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "14d050ec7d4e1bb76abf0636cf4104fb915b70e54e3ced9a4427c999100ff38a"
+
checksum = "f4029ec209b0cc480d209da3837a42c63801dd8548f09c1f4502c60accb62aeb"
dependencies = [
+
 "bitflags 2.5.0",
 "gix-commitgraph",
 "gix-date",
 "gix-hash",
@@ -1372,9 +1361,9 @@ dependencies = [

[[package]]
name = "gix-url"
-
version = "0.25.2"
+
version = "0.27.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "0c427a1a11ccfa53a4a2da47d9442c2241deee63a154bc15cc14b8312fbc4005"
+
checksum = "0db829ebdca6180fbe32be7aed393591df6db4a72dbbc0b8369162390954d1cf"
dependencies = [
 "bstr",
 "gix-features",
@@ -1802,15 +1791,6 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"

[[package]]
name = "memmap2"
-
version = "0.7.1"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
-
dependencies = [
-
 "libc",
-
]
-

-
[[package]]
-
name = "memmap2"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
@@ -2268,9 +2248,9 @@ dependencies = [

[[package]]
name = "prodash"
-
version = "26.2.2"
+
version = "28.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "794b5bf8e2d19b53dcdcec3e4bba628e20f5b6062503ba89281fa7037dd7bbcf"
+
checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79"

[[package]]
name = "qcheck"
@@ -2941,6 +2921,12 @@ dependencies = [
]

[[package]]
+
name = "shell-words"
+
version = "1.1.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
+

+
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3966,9 +3952,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

[[package]]
name = "winnow"
-
version = "0.5.40"
+
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
+
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
dependencies = [
 "memchr",
]
modified radicle-fetch/Cargo.toml
@@ -10,13 +10,13 @@ edition = "2021"
[dependencies]
bstr = { version = "1.3" }
either = { version = "1.9.0" }
-
gix-actor = { version = "0.28.0" }
-
gix-features = { version = "0.36", features = ["progress"] }
-
gix-hash = { version = "0.13.1" }
-
gix-odb = { version = "0.54" }
-
gix-pack = { version = "0.44" }
-
gix-protocol = { version = "0.41.1", features = ["blocking-client"] }
-
gix-transport = { version = "0.38", features = ["blocking-client"] }
+
gix-actor = { version = "0.31.1" }
+
gix-features = { version = "0.38.1", features = ["progress"] }
+
gix-hash = { version = "0.14.2" }
+
gix-odb = { version = "0.60.0" }
+
gix-pack = { version = "0.50.0" }
+
gix-protocol = { version = "0.45", features = ["blocking-client"] }
+
gix-transport = { version = "0.42", features = ["blocking-client"] }
log = { version = "0.4.17", features = ["std"] }
nonempty = { version = "0.9.0" }
radicle-git-ext = { version = "0.7.0", features = ["bstr"] }
modified radicle-fetch/src/git.rs
@@ -17,6 +17,6 @@ pub(crate) mod oid {

    /// Convert from an [`Oid`] to an [`ObjectId`].
    pub fn to_object_id(oid: Oid) -> ObjectId {
-
        ObjectId::from(oid.as_bytes())
+
        ObjectId::from(gix_hash::oid::from_bytes_unchecked(oid.as_ref()))
    }
}
modified radicle-fetch/src/lib.rs
@@ -55,6 +55,7 @@ pub fn pull<S>(
    limit: FetchLimit,
    remote: PublicKey,
    refs_at: Option<Vec<RefsAt>>,
+
    trace: bool,
) -> Result<FetchResult, Error>
where
    S: transport::ConnectionStream,
@@ -64,13 +65,13 @@ where
    if local == remote {
        return Err(Error::ReplicateSelf);
    }
-
    let handshake = perform_handshake(handle)?;
+
    let handshake = perform_handshake(handle, trace)?;
    let state = FetchState::default();

    // N.b. ensure that we ignore the local peer's key.
    handle.blocked.extend([local]);
    let result = state
-
        .run(handle, &handshake, limit, remote, refs_at)
+
        .run(handle, &handshake, limit, remote, refs_at, trace)
        .map_err(Error::Protocol);

    log::debug!(
@@ -90,6 +91,7 @@ pub fn clone<S>(
    handle: &mut Handle<S>,
    limit: FetchLimit,
    remote: PublicKey,
+
    trace: bool,
) -> Result<FetchResult, Error>
where
    S: transport::ConnectionStream,
@@ -98,10 +100,10 @@ where
    if *handle.local() == remote {
        return Err(Error::ReplicateSelf);
    }
-
    let handshake = perform_handshake(handle)?;
+
    let handshake = perform_handshake(handle, trace)?;
    let state = FetchState::default();
    let result = state
-
        .run(handle, &handshake, limit, remote, None)
+
        .run(handle, &handshake, limit, remote, None, trace)
        .map_err(Error::Protocol);
    let elapsed = start.elapsed().as_millis();
    let rid = handle.repo.id();
@@ -123,11 +125,11 @@ where
    result
}

-
fn perform_handshake<S>(handle: &mut Handle<S>) -> Result<handshake::Outcome, Error>
+
fn perform_handshake<S>(handle: &mut Handle<S>, trace: bool) -> Result<handshake::Outcome, Error>
where
    S: transport::ConnectionStream,
{
-
    handle.transport.handshake().map_err(|err| {
+
    handle.transport.handshake(trace).map_err(|err| {
        log::warn!(target: "fetch", "Failed to perform handshake: {err}");
        Error::Handshake { err }
    })
modified radicle-fetch/src/state.rs
@@ -214,6 +214,7 @@ impl FetchState {
        handle: &mut Handle<S>,
        handshake: &handshake::Outcome,
        step: &F,
+
        trace: bool,
    ) -> Result<BTreeSet<PublicKey>, error::Step>
    where
        S: transport::ConnectionStream,
@@ -222,7 +223,7 @@ impl FetchState {
        let refs = match step.ls_refs() {
            Some(refs) => handle
                .transport
-
                .ls_refs(refs.into(), handshake)?
+
                .ls_refs(refs.into(), handshake, trace)?
                .into_iter()
                .filter_map(|r| step.ref_filter(r))
                .collect::<Vec<_>>(),
@@ -235,7 +236,7 @@ impl FetchState {
        if !wants_haves.wants.is_empty() {
            handle
                .transport
-
                .fetch(wants_haves, handle.interrupt.clone(), handshake)?;
+
                .fetch(wants_haves, handle.interrupt.clone(), handshake, trace)?;
        } else {
            log::trace!(target: "fetch", "Nothing to fetch")
        };
@@ -289,6 +290,7 @@ impl FetchState {
        limit: &FetchLimit,
        remote: PublicKey,
        refs_at: Option<Vec<RefsAt>>,
+
        trace: bool,
    ) -> Result<sigrefs::RemoteRefs, error::Protocol>
    where
        S: transport::ConnectionStream,
@@ -303,7 +305,7 @@ impl FetchState {
                    limit: limit.special,
                };
                log::trace!(target: "fetch", "{sigrefs_at:?}");
-
                self.run_stage(handle, handshake, &sigrefs_at)?;
+
                self.run_stage(handle, handshake, &sigrefs_at, trace)?;
                let remotes = refs_at.iter().map(|r| &r.remote);

                let signed_refs = sigrefs::RemoteRefs::load(&self.as_cached(handle), remotes)?;
@@ -321,7 +323,7 @@ impl FetchState {
                    limit: limit.special,
                };
                log::trace!(target: "fetch", "{special_refs:?}");
-
                let fetched = self.run_stage(handle, handshake, &special_refs)?;
+
                let fetched = self.run_stage(handle, handshake, &special_refs, trace)?;

                let signed_refs = sigrefs::RemoteRefs::load(
                    &self.as_cached(handle),
@@ -355,6 +357,7 @@ impl FetchState {
        limit: FetchLimit,
        remote: PublicKey,
        refs_at: Option<Vec<RefsAt>>,
+
        trace: bool,
    ) -> Result<FetchResult, error::Protocol>
    where
        S: transport::ConnectionStream,
@@ -370,6 +373,7 @@ impl FetchState {
                remote,
                limit: limit.special,
            },
+
            trace,
        )?;
        log::debug!(target: "fetch", "Fetched rad/id ({}ms)", start.elapsed().as_millis());

@@ -409,6 +413,7 @@ impl FetchState {
            &limit,
            remote,
            refs_at,
+
            trace,
        )?;
        log::debug!(
            target: "fetch",
@@ -422,7 +427,7 @@ impl FetchState {
            remotes: signed_refs,
            limit: limit.refs,
        };
-
        self.run_stage(handle, handshake, &data_refs)?;
+
        self.run_stage(handle, handshake, &data_refs, trace)?;
        log::debug!(
            target: "fetch",
            "Fetched data refs for {} remotes ({}ms)",
modified radicle-fetch/src/transport.rs
@@ -80,11 +80,17 @@ where
    }

    /// Perform the handshake with the server side.
-
    pub(crate) fn handshake(&mut self) -> io::Result<handshake::Outcome> {
+
    pub(crate) fn handshake(&mut self, trace: bool) -> io::Result<handshake::Outcome> {
        log::trace!(target: "fetch", "Performing handshake for {}", self.repo);
        let (read, write) = self.stream.open().map_err(io_other)?;
        gix_protocol::fetch::handshake(
-
            &mut Connection::new(read, write, FetchConnection::AllowReuse, self.repo.clone()),
+
            &mut Connection::new(
+
                read,
+
                write,
+
                FetchConnection::AllowReuse,
+
                self.repo.clone(),
+
                trace,
+
            ),
            |_| Ok(None),
            vec![],
            &mut progress::Discard,
@@ -97,6 +103,7 @@ where
        &mut self,
        mut prefixes: Vec<BString>,
        handshake: &handshake::Outcome,
+
        trace: bool,
    ) -> io::Result<Vec<handshake::Ref>> {
        prefixes.sort();
        prefixes.dedup();
@@ -108,8 +115,15 @@ where
                repo: self.repo.clone(),
            },
            handshake,
-
            Connection::new(read, write, FetchConnection::AllowReuse, self.repo.clone()),
+
            Connection::new(
+
                read,
+
                write,
+
                FetchConnection::AllowReuse,
+
                self.repo.clone(),
+
                trace,
+
            ),
            &mut progress::Discard,
+
            trace,
        )
        .map_err(io_other)
    }
@@ -120,6 +134,7 @@ where
        wants_haves: WantsHaves,
        interrupt: Arc<AtomicBool>,
        handshake: &handshake::Outcome,
+
        trace: bool,
    ) -> io::Result<()> {
        log::trace!(
            target: "fetch",
@@ -136,8 +151,15 @@ where
                    interrupt,
                },
                handshake,
-
                Connection::new(read, write, FetchConnection::AllowReuse, self.repo.clone()),
+
                Connection::new(
+
                    read,
+
                    write,
+
                    FetchConnection::AllowReuse,
+
                    self.repo.clone(),
+
                    trace,
+
                ),
                &mut progress::Discard,
+
                trace,
            )
            .map_err(io_other)?
        };
@@ -191,7 +213,7 @@ where
    R: io::Read,
    W: io::Write,
{
-
    pub fn new(read: R, write: W, mode: FetchConnection, repo: BString) -> Self {
+
    pub fn new(read: R, write: W, mode: FetchConnection, repo: BString, trace: bool) -> Self {
        Self {
            inner: client::git::Connection::new(
                read,
@@ -200,6 +222,7 @@ where
                repo,
                None::<(String, Option<u16>)>,
                client::git::ConnectMode::Daemon,
+
                trace,
            ),
            mode,
        }
@@ -229,8 +252,9 @@ where
        &mut self,
        write_mode: client::WriteMode,
        on_into_read: client::MessageKind,
+
        trace: bool,
    ) -> Result<client::RequestWriter<'_>, client::Error> {
-
        self.inner.request(write_mode, on_into_read)
+
        self.inner.request(write_mode, on_into_read, trace)
    }

    fn to_url(&self) -> std::borrow::Cow<'_, bstr::BStr> {
@@ -253,7 +277,10 @@ where
    }
}

-
fn indicate_end_of_interaction<R, W>(transport: &mut Connection<R, W>) -> Result<(), client::Error>
+
fn indicate_end_of_interaction<R, W>(
+
    transport: &mut Connection<R, W>,
+
    trace: bool,
+
) -> Result<(), client::Error>
where
    R: io::Read,
    W: io::Write,
@@ -261,7 +288,7 @@ where
    // An empty request marks the (early) end of the interaction. Only relevant in stateful transports though.
    if transport.connection_persists_across_multiple_requests() {
        transport
-
            .request(client::WriteMode::Binary, client::MessageKind::Flush)?
+
            .request(client::WriteMode::Binary, client::MessageKind::Flush, trace)?
            .into_read()?;
    }
    Ok(())
modified radicle-fetch/src/transport/fetch.rs
@@ -59,7 +59,7 @@ impl PackWriter {
        P: NestedProgress,
        P::SubProgress: 'static,
    {
-
        use gix_odb::FindExt as _;
+
        use gix_pack::FindExt as _;

        let options = pack::bundle::write::Options {
            // N.b. use all cores. Can make configurable if needed
@@ -191,6 +191,7 @@ pub(crate) fn run<P, R, W>(
    handshake: &handshake::Outcome,
    mut conn: Connection<R, W>,
    progress: &mut P,
+
    trace: bool,
) -> Result<FetchOut, Error>
where
    P: NestedProgress,
@@ -226,7 +227,7 @@ where
        // N.b. we always return Action::Continue
        Ok(fetch::Action::Cancel) => unreachable!(),
        Err(err) => {
-
            indicate_end_of_interaction(&mut conn)?;
+
            indicate_end_of_interaction(&mut conn, trace)?;
            return Err(err.into());
        }
    }
@@ -234,7 +235,7 @@ where
    gix_protocol::fetch::Response::check_required_features(*protocol, &features)?;
    let sideband_all = features.iter().any(|(n, _)| *n == "sideband-all");
    features.push(("agent", Some(Cow::Owned(agent))));
-
    let mut args = fetch::Arguments::new(*protocol, features);
+
    let mut args = fetch::Arguments::new(*protocol, features, trace);

    let mut previous_response = None::<fetch::Response>;
    let mut round = 1;
@@ -247,7 +248,7 @@ where
        if sideband_all {
            setup_remote_progress(progress, &mut reader);
        }
-
        let response = fetch::Response::from_line_reader(*protocol, &mut reader, true)?;
+
        let response = fetch::Response::from_line_reader(*protocol, &mut reader, true, trace)?;
        previous_response = if response.has_pack() {
            progress.step();
            if !sideband_all {
@@ -286,7 +287,7 @@ where
    if matches!(protocol, Protocol::V2)
        && matches!(conn.mode, FetchConnection::TerminateOnSuccessfulCompletion)
    {
-
        indicate_end_of_interaction(&mut conn)?;
+
        indicate_end_of_interaction(&mut conn, trace)?;
    }

    log::trace!(target: "fetch", "fetched refs: {:?}", delegate.out.refs);
modified radicle-fetch/src/transport/ls_refs.rs
@@ -109,6 +109,7 @@ pub(crate) fn run<R, W>(
    handshake: &handshake::Outcome,
    mut conn: Connection<R, W>,
    progress: &mut impl Progress,
+
    trace: bool,
) -> Result<Vec<Ref>, ls_refs::Error>
where
    R: io::Read,
@@ -162,11 +163,12 @@ where
                } else {
                    Some(args.into_iter())
                },
+
                trace,
            )?;
            handshake::refs::from_v2_refs(&mut remote_refs)?
        }
        Err(err) => {
-
            indicate_end_of_interaction(&mut conn)?;
+
            indicate_end_of_interaction(&mut conn, trace)?;
            return Err(err.into());
        }
    };