diff --git a/gix-protocol/tests/protocol/fetch/arguments.rs b/gix-protocol/tests/protocol/fetch/arguments.rs index da5e37d50ac..52b82075c67 100644 --- a/gix-protocol/tests/protocol/fetch/arguments.rs +++ b/gix-protocol/tests/protocol/fetch/arguments.rs @@ -2,6 +2,10 @@ use bstr::ByteSlice; use gix_transport::Protocol; use crate::fetch; +#[cfg(feature = "async-client")] +use gix_transport::client::git::async_io::Connection; +#[cfg(feature = "blocking-client")] +use gix_transport::client::git::blocking_io::Connection; fn arguments_v1(features: impl IntoIterator) -> fetch::Arguments { fetch::Arguments::new(Protocol::V1, features.into_iter().map(|n| (n, None)).collect(), false) @@ -140,12 +144,9 @@ mod impls { } } -fn transport( - out: &mut Vec, - stateful: bool, -) -> Transport>> { +fn transport(out: &mut Vec, stateful: bool) -> Transport>> { Transport { - inner: gix_transport::client::git::Connection::new( + inner: Connection::new( &[], out, Protocol::V1, // does not matter diff --git a/gix-protocol/tests/protocol/fetch/mod.rs b/gix-protocol/tests/protocol/fetch/mod.rs index 355afbb2850..03f69bed8d8 100644 --- a/gix-protocol/tests/protocol/fetch/mod.rs +++ b/gix-protocol/tests/protocol/fetch/mod.rs @@ -302,9 +302,9 @@ pub fn transport( path: &str, desired_version: gix_transport::Protocol, mode: gix_transport::client::git::ConnectMode, -) -> gix_transport::client::git::Connection { +) -> gix_transport::client::git::async_io::Connection { let response = fixture_bytes(path); - gix_transport::client::git::Connection::new( + gix_transport::client::git::async_io::Connection::new( Cursor::new(response), out, desired_version, @@ -321,9 +321,9 @@ pub fn transport( path: &str, version: gix_transport::Protocol, mode: gix_transport::client::git::ConnectMode, -) -> gix_transport::client::git::Connection { +) -> gix_transport::client::git::blocking_io::Connection { let response = fixture_bytes(path); - gix_transport::client::git::Connection::new( + gix_transport::client::git::blocking_io::Connection::new( Cursor::new(response), out, version, diff --git a/gix-transport/Cargo.toml b/gix-transport/Cargo.toml index 80f3f2a4ccb..507bc758aec 100644 --- a/gix-transport/Cargo.toml +++ b/gix-transport/Cargo.toml @@ -18,6 +18,8 @@ doctest = false default = [] ## If set, blocking implementations of the typical git transports become available in `crate::client::blocking_io` +## +## If used in conjunction with an async implementation, this one takes precedence. blocking-client = ["gix-packetline/blocking-io"] ## Implies `blocking-client`, and adds support for the http and https transports. http-client = [ @@ -27,10 +29,12 @@ http-client = [ "gix-credentials", ] ## Implies `http-client`, and adds support for the http and https transports using the Rust bindings for `libcurl`. +## +## If used in conjunction with other blocking implementations like `http-client-reqwest`, this one takes precedence. http-client-curl = ["curl", "http-client"] ## Implies `http-client-curl` and enables `rustls` for creating `https://` connections. http-client-curl-rust-tls = ["http-client-curl", "curl/rustls"] -### Implies `http-client` and adds support for http and https transports using the blocking version of `reqwest`. +## Implies `http-client` and adds support for http and https transports using the blocking version of `reqwest`. http-client-reqwest = ["reqwest", "http-client"] ## Stacks with `blocking-http-transport-reqwest` and enables `https://` via the `rustls` crate. http-client-reqwest-rust-tls = ["http-client-reqwest", "reqwest/rustls-tls"] @@ -59,7 +63,7 @@ async-client = [ #! ### Other ## Data structures implement `serde::Serialize` and `serde::Deserialize`. -serde = ["dep:serde"] +serde = ["dep:serde", "bstr/serde"] [[test]] name = "blocking-transport" diff --git a/gix-transport/src/client/async_io/connect.rs b/gix-transport/src/client/async_io/connect.rs index 6b094328e4b..cd5a3a7fda1 100644 --- a/gix-transport/src/client/async_io/connect.rs +++ b/gix-transport/src/client/async_io/connect.rs @@ -2,7 +2,7 @@ pub use crate::client::non_io_types::connect::{Error, Options}; #[cfg(feature = "async-std")] pub(crate) mod function { - use crate::client::{async_io::Transport, git, non_io_types::connect::Error}; + use crate::client::{async_io::Transport, git::async_io::Connection, non_io_types::connect::Error}; /// A general purpose connector connecting to a repository identified by the given `url`. /// @@ -26,7 +26,7 @@ pub(crate) mod function { } let path = std::mem::take(&mut url.path); Box::new( - git::Connection::new_tcp( + Connection::new_tcp( url.host().expect("host is present in url"), url.port, path, diff --git a/gix-transport/src/client/blocking_io/connect.rs b/gix-transport/src/client/blocking_io/connect.rs index d96f3e4e7bd..ffc4c5b2a53 100644 --- a/gix-transport/src/client/blocking_io/connect.rs +++ b/gix-transport/src/client/blocking_io/connect.rs @@ -3,7 +3,7 @@ pub use crate::client::non_io_types::connect::{Error, Options}; pub(crate) mod function { #[cfg(feature = "http-client-curl")] use crate::client::blocking_io::http::curl::Curl; - #[cfg(feature = "http-client-reqwest")] + #[cfg(all(feature = "http-client-reqwest", not(feature = "http-client-curl")))] use crate::client::blocking_io::http::reqwest::Remote as Reqwest; use crate::client::{blocking_io::Transport, non_io_types::connect::Error}; diff --git a/gix-transport/src/client/blocking_io/http/mod.rs b/gix-transport/src/client/blocking_io/http/mod.rs index 454af724a55..df4bda43512 100644 --- a/gix-transport/src/client/blocking_io/http/mod.rs +++ b/gix-transport/src/client/blocking_io/http/mod.rs @@ -19,7 +19,8 @@ use crate::{ http::options::{HttpVersion, SslVersionRangeInclusive}, ExtendedBufRead, HandleProgress, RequestWriter, SetServiceResponse, }, - capabilities, Capabilities, MessageKind, + capabilities::blocking_recv::Handshake, + MessageKind, }, packetline::{blocking_io::StreamingPeekableIter, PacketLineRef}, Protocol, Service, @@ -402,11 +403,11 @@ impl blocking_io::Transport for Transport { line_reader.as_read().read_to_end(&mut Vec::new())?; } - let capabilities::recv::Outcome { + let Handshake { capabilities, refs, protocol: actual_protocol, - } = Capabilities::from_lines_with_version_detection(line_reader)?; + } = Handshake::from_lines_with_version_detection(line_reader)?; self.actual_version = actual_protocol; self.service = Some(service); Ok(SetServiceResponse { diff --git a/gix-transport/src/client/capabilities.rs b/gix-transport/src/client/capabilities.rs index ddb3682d070..79bf34a6347 100644 --- a/gix-transport/src/client/capabilities.rs +++ b/gix-transport/src/client/capabilities.rs @@ -165,9 +165,9 @@ impl Capabilities { } } -#[cfg(feature = "blocking-client")] /// -pub mod recv { +#[cfg(feature = "blocking-client")] +pub mod blocking_recv { use std::io; use bstr::ByteVec; @@ -178,8 +178,8 @@ pub mod recv { Protocol, }; - /// Success outcome of [`Capabilities::from_lines_with_version_detection`]. - pub struct Outcome<'a> { + /// The information provided by the server upon first connection. + pub struct Handshake<'a> { /// The [`Capabilities`] the remote advertised. pub capabilities: Capabilities, /// The remote refs as a [`io::BufRead`]. @@ -191,14 +191,14 @@ pub mod recv { pub protocol: Protocol, } - impl Capabilities { + impl Handshake<'_> { /// Read the capabilities and version advertisement from the given packetline reader. /// /// If [`Protocol::V1`] was requested, or the remote decided to downgrade, the remote refs - /// advertisement will also be included in the [`Outcome`]. + /// advertisement will also be included in the [`Handshake`]. pub fn from_lines_with_version_detection( rd: &mut StreamingPeekableIter, - ) -> Result, client::Error> { + ) -> Result, client::Error> { // NOTE that this is vitally important - it is turned on and stays on for all following requests so // we automatically abort if the server sends an ERR line anywhere. // We are sure this can't clash with binary data when sent due to the way the PACK @@ -214,13 +214,13 @@ pub mod recv { Protocol::V1 => { let (capabilities, delimiter_position) = Capabilities::from_bytes(line.0)?; rd.peek_buffer_replace_and_truncate(delimiter_position, b'\n'); - Outcome { + Handshake { capabilities, refs: Some(Box::new(rd.as_read())), protocol: Protocol::V1, } } - Protocol::V2 => Outcome { + Protocol::V2 => Handshake { capabilities: { let mut rd = rd.as_read(); let mut buf = Vec::new(); @@ -243,7 +243,7 @@ pub mod recv { }, } } - None => Outcome { + None => Handshake { capabilities: Capabilities::default(), refs: Some(Box::new(rd.as_read())), protocol: Protocol::V0, @@ -253,10 +253,10 @@ pub mod recv { } } -#[cfg(all(feature = "async-client", not(feature = "blocking-client")))] -#[allow(missing_docs)] /// -pub mod recv { +#[cfg(feature = "async-client")] +#[allow(missing_docs)] +pub mod async_recv { use bstr::ByteVec; use futures_io::AsyncRead; @@ -266,8 +266,8 @@ pub mod recv { Protocol, }; - /// Success outcome of [`Capabilities::from_lines_with_version_detection`]. - pub struct Outcome<'a> { + /// The information provided by the server upon first connection. + pub struct Handshake<'a> { /// The [`Capabilities`] the remote advertised. pub capabilities: Capabilities, /// The remote refs as an [`AsyncBufRead`]. @@ -279,14 +279,14 @@ pub mod recv { pub protocol: Protocol, } - impl Capabilities { + impl Handshake<'_> { /// Read the capabilities and version advertisement from the given packetline reader. /// /// If [`Protocol::V1`] was requested, or the remote decided to downgrade, the remote refs - /// advertisement will also be included in the [`Outcome`]. + /// advertisement will also be included in the [`Handshake`]. pub async fn from_lines_with_version_detection( rd: &mut StreamingPeekableIter, - ) -> Result, client::Error> { + ) -> Result, client::Error> { // NOTE that this is vitally important - it is turned on and stays on for all following requests so // we automatically abort if the server sends an ERR line anywhere. // We are sure this can't clash with binary data when sent due to the way the PACK @@ -302,13 +302,13 @@ pub mod recv { Protocol::V1 => { let (capabilities, delimiter_position) = Capabilities::from_bytes(line.0)?; rd.peek_buffer_replace_and_truncate(delimiter_position, b'\n'); - Outcome { + Handshake { capabilities, refs: Some(Box::new(rd.as_read())), protocol: Protocol::V1, } } - Protocol::V2 => Outcome { + Protocol::V2 => Handshake { capabilities: { let mut rd = rd.as_read(); let mut buf = Vec::new(); @@ -331,7 +331,7 @@ pub mod recv { }, } } - None => Outcome { + None => Handshake { capabilities: Capabilities::default(), refs: Some(Box::new(rd.as_read())), protocol: Protocol::V0, diff --git a/gix-transport/src/client/git/async_io.rs b/gix-transport/src/client/git/async_io.rs index 9ecbfd84976..74feeddc7fb 100644 --- a/gix-transport/src/client/git/async_io.rs +++ b/gix-transport/src/client/git/async_io.rs @@ -9,9 +9,8 @@ use crate::{ client::{ self, async_io::{RequestWriter, SetServiceResponse}, - capabilities, + capabilities::async_recv::Handshake, git::{self, ConnectionState}, - Capabilities, }, packetline::{ async_io::{StreamingPeekableIter, Writer}, @@ -97,11 +96,11 @@ where line_writer.flush().await?; } - let capabilities::recv::Outcome { + let Handshake { capabilities, refs, protocol: actual_protocol, - } = Capabilities::from_lines_with_version_detection(&mut self.line_provider).await?; + } = Handshake::from_lines_with_version_detection(&mut self.line_provider).await?; Ok(SetServiceResponse { actual_protocol, capabilities, @@ -164,9 +163,12 @@ mod async_net { use async_std::net::TcpStream; - use crate::client::{git, Error}; + use crate::client::{ + git::{async_io::Connection, ConnectMode}, + Error, + }; - impl git::Connection { + impl Connection { /// Create a new TCP connection using the `git` protocol of `desired_version`, and make a connection to `host` /// at `port` for accessing the repository at `path` on the server side. /// If `trace` is `true`, all packetlines received or sent will be passed to the facilities of the `gix-trace` crate. @@ -176,20 +178,20 @@ mod async_net { path: bstr::BString, desired_version: crate::Protocol, trace: bool, - ) -> Result, Error> { + ) -> Result { let read = async_std::io::timeout( Duration::from_secs(5), TcpStream::connect(&(host, port.unwrap_or(9418))), ) .await?; let write = read.clone(); - Ok(git::Connection::new( + Ok(Self::new( read, write, desired_version, path, None::<(String, _)>, - git::ConnectMode::Daemon, + ConnectMode::Daemon, trace, )) } diff --git a/gix-transport/src/client/git/blocking_io.rs b/gix-transport/src/client/git/blocking_io.rs index 22ae7318455..92fe5b61a95 100644 --- a/gix-transport/src/client/git/blocking_io.rs +++ b/gix-transport/src/client/git/blocking_io.rs @@ -6,9 +6,8 @@ use crate::{ client::{ self, blocking_io::{RequestWriter, SetServiceResponse}, - capabilities, + capabilities::blocking_recv::Handshake, git::{self, ConnectionState}, - Capabilities, }, packetline::{ blocking_io::{StreamingPeekableIter, Writer}, @@ -92,11 +91,11 @@ where line_writer.flush()?; } - let capabilities::recv::Outcome { + let Handshake { capabilities, refs, protocol: actual_protocol, - } = Capabilities::from_lines_with_version_detection(&mut self.line_provider)?; + } = Handshake::from_lines_with_version_detection(&mut self.line_provider)?; Ok(SetServiceResponse { actual_protocol, capabilities, diff --git a/gix-transport/src/client/git/mod.rs b/gix-transport/src/client/git/mod.rs index 37d6193f5d5..02179060ca4 100644 --- a/gix-transport/src/client/git/mod.rs +++ b/gix-transport/src/client/git/mod.rs @@ -161,12 +161,10 @@ mod message { } } -#[cfg(all(feature = "async-client", not(feature = "blocking-client")))] -pub(crate) mod async_io; -#[cfg(all(feature = "async-client", not(feature = "blocking-client")))] -pub use async_io::Connection; +/// +#[cfg(feature = "async-client")] +pub mod async_io; +/// #[cfg(feature = "blocking-client")] -pub(crate) mod blocking_io; -#[cfg(feature = "blocking-client")] -pub use blocking_io::{connect, Connection}; +pub mod blocking_io; diff --git a/gix-transport/src/client/mod.rs b/gix-transport/src/client/mod.rs index 4b8aee804cb..038030a2855 100644 --- a/gix-transport/src/client/mod.rs +++ b/gix-transport/src/client/mod.rs @@ -1,5 +1,5 @@ /// -#[cfg(all(feature = "async-client", not(feature = "blocking-client")))] +#[cfg(feature = "async-client")] pub mod async_io; mod traits; diff --git a/gix-transport/tests/client/capabilities.rs b/gix-transport/tests/client/capabilities.rs index cd7d9405e00..6b6d356e8f4 100644 --- a/gix-transport/tests/client/capabilities.rs +++ b/gix-transport/tests/client/capabilities.rs @@ -3,6 +3,10 @@ use bstr::ByteSlice; use gix_packetline::async_io::{encode, StreamingPeekableIter}; #[cfg(all(feature = "blocking-client", not(feature = "async-client")))] use gix_packetline::blocking_io::{encode, StreamingPeekableIter}; +#[cfg(all(feature = "async-client", not(feature = "blocking-client")))] +use gix_transport::client::capabilities::async_recv::Handshake; +#[cfg(all(feature = "blocking-client", not(feature = "async-client")))] +use gix_transport::client::capabilities::blocking_recv::Handshake; use gix_transport::client::Capabilities; #[test] @@ -59,7 +63,7 @@ async fn from_lines_with_version_detection_v0() -> crate::Result { let mut buf = Vec::::new(); encode::flush_to_write(&mut buf).await?; let mut stream = StreamingPeekableIter::new(buf.as_slice(), &[gix_packetline::PacketLineRef::Flush], false); - let caps = Capabilities::from_lines_with_version_detection(&mut stream) + let caps = Handshake::from_lines_with_version_detection(&mut stream) .await .expect("we can parse V0 as very special case, useful for testing stateful connections in other crates") .capabilities; diff --git a/gix-transport/tests/client/git.rs b/gix-transport/tests/client/git.rs index 88c9699aebc..9afee70146c 100644 --- a/gix-transport/tests/client/git.rs +++ b/gix-transport/tests/client/git.rs @@ -10,9 +10,15 @@ use bstr::ByteSlice; use futures_lite::{AsyncBufReadExt, AsyncWriteExt, StreamExt}; use gix_packetline::read::ProgressAction; #[cfg(feature = "async-client")] -use gix_transport::client::async_io::{Transport, TransportV2Ext}; +use gix_transport::client::{ + async_io::{Transport, TransportV2Ext}, + git::async_io::Connection, +}; #[cfg(feature = "blocking-client")] -use gix_transport::client::blocking_io::{Transport, TransportV2Ext}; +use gix_transport::client::{ + blocking_io::{Transport, TransportV2Ext}, + git::blocking_io::Connection, +}; use gix_transport::{ client, client::{git, TransportWithoutIO}, @@ -25,7 +31,7 @@ use crate::fixture_bytes; async fn handshake_v1_and_request() -> crate::Result { let mut out = Vec::new(); let server_response = fixture_bytes("v1/clone.response"); - let c = git::Connection::new( + let c = Connection::new( server_response.as_slice(), &mut out, Protocol::V1, @@ -157,7 +163,7 @@ async fn handshake_v1_and_request() -> crate::Result { async fn push_v1_simulated() -> crate::Result { let mut out = Vec::new(); let server_response = fixture_bytes("v1/push.response"); - let mut c = git::Connection::new( + let mut c = Connection::new( server_response.as_slice(), &mut out, Protocol::V1, @@ -223,7 +229,7 @@ async fn push_v1_simulated() -> crate::Result { async fn handshake_v1_process_mode() -> crate::Result { let mut out = Vec::new(); let server_response = fixture_bytes("v1/clone.response"); - let mut c = git::Connection::new( + let mut c = Connection::new( server_response.as_slice(), &mut out, Protocol::V1, @@ -246,7 +252,7 @@ async fn handshake_v1_process_mode() -> crate::Result { async fn handshake_v2_downgrade_to_v1() -> crate::Result { let mut out = Vec::new(); let input = fixture_bytes("v1/clone.response"); - let mut c = git::Connection::new( + let mut c = Connection::new( input.as_slice(), &mut out, Protocol::V2, @@ -293,7 +299,7 @@ async fn handshake_v2_and_request() -> crate::Result { async fn handshake_v2_and_request_inner() -> crate::Result { let mut out = Vec::new(); let input = fixture_bytes("v2/clone.response"); - let mut c = git::Connection::new( + let mut c = Connection::new( input.as_slice(), &mut out, Protocol::V2, diff --git a/justfile b/justfile index 81ab31ac8d9..eeb7a76229e 100755 --- a/justfile +++ b/justfile @@ -45,10 +45,10 @@ check: cargo check --workspace cargo check --no-default-features --features small cargo check -p gix-packetline --all-features 2>/dev/null + cargo check -p gix-transport --all-features 2>/dev/null # assure compile error occurs ! cargo check --features lean-async 2>/dev/null ! cargo check -p gitoxide-core --all-features 2>/dev/null - ! cargo check -p gix-transport --all-features 2>/dev/null ! cargo check -p gix-protocol --all-features 2>/dev/null # warning happens if nothing found, no exit code :/ cargo --color=never tree -p gix --no-default-features -e normal -i imara-diff \