diff --git a/gitoxide-core/src/pack/receive.rs b/gitoxide-core/src/pack/receive.rs index 288133ca1c6..2a1ccea79f6 100644 --- a/gitoxide-core/src/pack/receive.rs +++ b/gitoxide-core/src/pack/receive.rs @@ -4,6 +4,7 @@ use std::{ sync::{atomic::AtomicBool, Arc}, }; +use crate::{net, pack::receive::protocol::fetch::negotiate, OutputFormat}; #[cfg(feature = "async-client")] use gix::protocol::transport::client::async_io::connect; #[cfg(feature = "blocking-client")] @@ -23,8 +24,6 @@ pub use gix::{ NestedProgress, Progress, }; -use crate::{net, pack::receive::protocol::fetch::negotiate, OutputFormat}; - pub const PROGRESS_RANGE: std::ops::RangeInclusive = 1..=3; pub struct Context { pub thread_limit: Option, @@ -65,7 +64,7 @@ where .is_some(); let agent = gix::protocol::agent(gix::env::agent()); - let mut handshake = gix::protocol::fetch::handshake( + let mut handshake: gix::protocol::Handshake = gix::protocol::fetch::handshake( &mut transport.inner, gix::protocol::credentials::builtin, vec![("agent".into(), Some(agent.clone()))], @@ -82,18 +81,21 @@ where }) .collect::>()?; let user_agent = ("agent", Some(agent.clone().into())); - let refmap = gix::protocol::fetch::RefMap::new( - &mut progress, - &fetch_refspecs, - gix::protocol::fetch::Context { - handshake: &mut handshake, - transport: &mut transport.inner, - user_agent: user_agent.clone(), + + let context = gix::protocol::fetch::refmap::init::Context { + fetch_refspecs: fetch_refspecs.clone(), + extra_refspecs: vec![], + }; + let refmap = handshake + .fetch_or_extract_refmap( + &mut progress, + &mut transport.inner, + user_agent.clone(), trace_packetlines, - }, - gix::protocol::fetch::refmap::init::Options::default(), - ) - .await?; + true, + context, + ) + .await?; if refmap.mappings.is_empty() && !refmap.remote_refs.is_empty() { return Err(Error::NoMapping { diff --git a/gix-protocol/src/fetch/handshake.rs b/gix-protocol/src/fetch/handshake.rs index 0c5dde26d62..83367d5778a 100644 --- a/gix-protocol/src/fetch/handshake.rs +++ b/gix-protocol/src/fetch/handshake.rs @@ -6,10 +6,7 @@ use maybe_async::maybe_async; use crate::transport::client::async_io::Transport; #[cfg(feature = "blocking-client")] use crate::transport::client::blocking_io::Transport; -use crate::{ - credentials, - handshake::{Error, Outcome}, -}; +use crate::{credentials, handshake::Error, Handshake}; /// Perform a handshake with the server on the other side of `transport`, with `authenticate` being used if authentication /// turns out to be required. `extra_parameters` are the parameters `(name, optional value)` to add to the handshake, @@ -22,7 +19,7 @@ pub async fn upload_pack( authenticate: AuthFn, extra_parameters: Vec<(String, Option)>, progress: &mut impl Progress, -) -> Result +) -> Result where AuthFn: FnMut(credentials::helper::Action) -> credentials::protocol::Result, T: Transport, diff --git a/gix-protocol/src/fetch/mod.rs b/gix-protocol/src/fetch/mod.rs index 99f8df15162..a273ab694a6 100644 --- a/gix-protocol/src/fetch/mod.rs +++ b/gix-protocol/src/fetch/mod.rs @@ -5,7 +5,7 @@ /// /// * [handshake](handshake()) /// * **ls-refs** -/// * [get available refs by refspecs](RefMap::new()) +/// * [get available refs by refspecs](RefMap::fetch()) /// * **fetch pack** /// * `negotiate` until a pack can be received (TBD) /// * [officially terminate the connection](crate::indicate_end_of_interaction()) diff --git a/gix-protocol/src/fetch/negotiate.rs b/gix-protocol/src/fetch/negotiate.rs index 1cd8ba9c666..7480aea9960 100644 --- a/gix-protocol/src/fetch/negotiate.rs +++ b/gix-protocol/src/fetch/negotiate.rs @@ -111,7 +111,7 @@ pub struct Round { /// * `graph` /// - The commit-graph for use by the `negotiator` - we populate it with tips to initialize the graph traversal. /// * `ref_map` -/// - The references known on the remote, as previously obtained with [`RefMap::new()`]. +/// - The references known on the remote, as previously obtained with [`RefMap::fetch()`]. /// * `shallow` /// - How to deal with shallow repositories. It does affect how negotiations are performed. /// * `mapping_is_ignored` diff --git a/gix-protocol/src/fetch/refmap/init.rs b/gix-protocol/src/fetch/refmap/init.rs index ac005be60dd..abcf027cfb1 100644 --- a/gix-protocol/src/fetch/refmap/init.rs +++ b/gix-protocol/src/fetch/refmap/init.rs @@ -1,21 +1,22 @@ -use std::collections::HashSet; +use std::{borrow::Cow, collections::HashSet}; -use bstr::{BString, ByteVec}; +use bstr::{BString, ByteSlice, ByteVec}; use gix_features::progress::Progress; +use gix_transport::client::Capabilities; #[cfg(feature = "async-client")] use crate::transport::client::async_io::Transport; #[cfg(feature = "blocking-client")] use crate::transport::client::blocking_io::Transport; use crate::{ - fetch, fetch::{ refmap::{Mapping, Source, SpecIndex}, RefMap, }, + handshake::Ref, }; -/// The error returned by [`RefMap::new()`]. +/// The error returned by [`RefMap::fetch()`]. #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { @@ -27,96 +28,82 @@ pub enum Error { ListRefs(#[from] crate::ls_refs::Error), } -/// For use in [`RefMap::new()`]. +/// For use in [`RefMap::fetch()`]. #[derive(Debug, Clone)] -pub struct Options { - /// Use a two-component prefix derived from the ref-spec's source, like `refs/heads/` to let the server pre-filter refs - /// with great potential for savings in traffic and local CPU time. Defaults to `true`. - pub prefix_from_spec_as_filter_on_remote: bool, +pub struct Context { + /// All explicit refspecs to identify references on the remote that you are interested in. + /// Note that these are copied to [`RefMap::refspecs`] for convenience, as `RefMap::mappings` refer to them by index. + pub fetch_refspecs: Vec, /// A list of refspecs to use as implicit refspecs which won't be saved or otherwise be part of the remote in question. /// /// This is useful for handling `remote..tagOpt` for example. pub extra_refspecs: Vec, } -impl Default for Options { - fn default() -> Self { - Options { - prefix_from_spec_as_filter_on_remote: true, - extra_refspecs: Vec::new(), - } +impl Context { + fn aggregate_refspecs(&self) -> Vec { + let mut all_refspecs = self.fetch_refspecs.clone(); + all_refspecs.extend(self.extra_refspecs.iter().cloned()); + all_refspecs } } impl RefMap { - /// Create a new instance by obtaining all references on the remote that have been filtered through our remote's + /// Create a new instance by obtaining all references on the remote that have been filtered through our remote's specs /// for _fetching_. /// - /// A [context](fetch::Context) is provided to bundle what would be additional parameters, - /// and [options](Options) are used to further configure the call. - /// /// * `progress` is used if `ls-refs` is invoked on the remote. Always the case when V2 is used. - /// * `fetch_refspecs` are all explicit refspecs to identify references on the remote that you are interested in. - /// Note that these are copied to [`RefMap::refspecs`] for convenience, as `RefMap::mappings` refer to them by index. + /// * `capabilities` are the capabilities of the server, obtained by a [handshake](crate::handshake()). + /// * `transport` is a way to communicate with the server to obtain the reference listing. + /// * `user_agent` is passed to the server. + /// * `trace_packetlines` traces all packet lines if `true`, for debugging primarily. + /// * `prefix_from_spec_as_filter_on_remote` + /// - Use a two-component prefix derived from the ref-spec's source, like `refs/heads/` to let the server pre-filter refs + /// with great potential for savings in traffic and local CPU time. + /// * `context` to provide more [configuration](Context). #[allow(clippy::result_large_err)] #[maybe_async::maybe_async] - pub async fn new( + pub async fn fetch( mut progress: impl Progress, - fetch_refspecs: &[gix_refspec::RefSpec], - fetch::Context { - handshake, - transport, - user_agent, - trace_packetlines, - }: fetch::Context<'_, T>, - Options { - prefix_from_spec_as_filter_on_remote, - extra_refspecs, - }: Options, + capabilities: &Capabilities, + transport: &mut T, + user_agent: (&'static str, Option>), + trace_packetlines: bool, + prefix_from_spec_as_filter_on_remote: bool, + context: Context, ) -> Result where T: Transport, { let _span = gix_trace::coarse!("gix_protocol::fetch::RefMap::new()"); - let null = gix_hash::ObjectId::null(gix_hash::Kind::Sha1); // OK to hardcode Sha1, it's not supposed to match, ever. + let all_refspecs = context.aggregate_refspecs(); + let remote_refs = crate::ls_refs( + transport, + capabilities, + |_capabilities, arguments| { + push_prefix_arguments(prefix_from_spec_as_filter_on_remote, arguments, &all_refspecs); + Ok(crate::ls_refs::Action::Continue) + }, + &mut progress, + trace_packetlines, + user_agent, + ) + .await?; - let all_refspecs = { - let mut s: Vec<_> = fetch_refspecs.to_vec(); - s.extend(extra_refspecs.clone()); - s - }; - let remote_refs = match handshake.refs.take() { - Some(refs) => refs, - None => { - crate::ls_refs( - transport, - &handshake.capabilities, - |_capabilities, arguments, features| { - features.push(user_agent); - if prefix_from_spec_as_filter_on_remote { - let mut seen = HashSet::new(); - for spec in &all_refspecs { - let spec = spec.to_ref(); - if seen.insert(spec.instruction()) { - let mut prefixes = Vec::with_capacity(1); - spec.expand_prefixes(&mut prefixes); - for mut prefix in prefixes { - prefix.insert_str(0, "ref-prefix "); - arguments.push(prefix); - } - } - } - } - Ok(crate::ls_refs::Action::Continue) - }, - &mut progress, - trace_packetlines, - ) - .await? - } - }; + Self::from_refs(remote_refs, capabilities, context) + } + + /// Create a ref-map from already obtained `remote_refs`. Use `context` to pass in refspecs. + /// `capabilities` are used to determine the object format. + pub fn from_refs(remote_refs: Vec, capabilities: &Capabilities, context: Context) -> Result { + let all_refspecs = context.aggregate_refspecs(); + let Context { + fetch_refspecs, + extra_refspecs, + } = context; let num_explicit_specs = fetch_refspecs.len(); let group = gix_refspec::MatchGroup::from_fetch_specs(all_refspecs.iter().map(gix_refspec::RefSpec::to_ref)); + let null = gix_hash::ObjectId::null(gix_hash::Kind::Sha1); // OK to hardcode Sha1, it's not supposed to match, ever. let (res, fixes) = group .match_lhs(remote_refs.iter().map(|r| { let (full_ref_name, target, object) = r.unpack(); @@ -150,24 +137,9 @@ impl RefMap { }) .collect(); - let object_hash = extract_object_format(handshake)?; - Ok(RefMap { - mappings, - refspecs: fetch_refspecs.to_vec(), - extra_refspecs, - fixes, - remote_refs, - object_hash, - }) - } -} - -/// Assume sha1 if server says nothing, otherwise configure anything beyond sha1 in the local repo configuration -#[allow(clippy::result_large_err)] -fn extract_object_format(outcome: &crate::handshake::Outcome) -> Result { - use bstr::ByteSlice; - let object_hash = - if let Some(object_format) = outcome.capabilities.capability("object-format").and_then(|c| c.value()) { + // Assume sha1 if server says nothing, otherwise configure anything beyond sha1 in the local repo configuration + let object_hash = if let Some(object_format) = capabilities.capability("object-format").and_then(|c| c.value()) + { let object_format = object_format.to_str().map_err(|_| Error::UnknownObjectFormat { format: object_format.into(), })?; @@ -178,5 +150,37 @@ fn extract_object_format(outcome: &crate::handshake::Outcome) -> Result, + all_refspecs: &[gix_refspec::RefSpec], +) { + if !prefix_from_spec_as_filter_on_remote { + return; + } + + let mut seen = HashSet::new(); + for spec in all_refspecs { + let spec = spec.to_ref(); + if seen.insert(spec.instruction()) { + let mut prefixes = Vec::with_capacity(1); + spec.expand_prefixes(&mut prefixes); + for mut prefix in prefixes { + prefix.insert_str(0, "ref-prefix "); + arguments.push(prefix); + } + } + } } diff --git a/gix-protocol/src/fetch/response/mod.rs b/gix-protocol/src/fetch/response/mod.rs index 1bc3fa163a1..804e07f7d4a 100644 --- a/gix-protocol/src/fetch/response/mod.rs +++ b/gix-protocol/src/fetch/response/mod.rs @@ -185,7 +185,7 @@ impl Response { } /// Append the given `updates` which may have been obtained from a - /// (handshake::Outcome)[crate::handshake::Outcome::v1_shallow_updates]. + /// (handshake::Outcome)[crate::Handshake::v1_shallow_updates]. /// /// In V2, these are received as part of the pack, but V1 sends them early, so we /// offer to re-integrate them here. diff --git a/gix-protocol/src/fetch/types.rs b/gix-protocol/src/fetch/types.rs index f7d3415a783..549451f4703 100644 --- a/gix-protocol/src/fetch/types.rs +++ b/gix-protocol/src/fetch/types.rs @@ -18,18 +18,18 @@ pub struct Options<'a> { pub reject_shallow_remote: bool, } -/// For use in [`RefMap::new()`] and [`fetch`](crate::fetch()). +/// For use in [`RefMap::fetch()`] and [`fetch`](crate::fetch()). #[cfg(feature = "handshake")] pub struct Context<'a, T> { /// The outcome of the handshake performed with the remote. /// /// Note that it's mutable as depending on the protocol, it may contain refs that have been sent unconditionally. - pub handshake: &'a mut crate::handshake::Outcome, + pub handshake: &'a mut crate::Handshake, /// The transport to use when making an `ls-refs` or `fetch` call. /// /// This is always done if the underlying protocol is V2, which is implied by the absence of refs in the `handshake` outcome. pub transport: &'a mut T, - /// How to self-identify during the `ls-refs` call in [`RefMap::new()`] or the `fetch` call in [`fetch()`](crate::fetch()). + /// How to self-identify during the `ls-refs` call in [`RefMap::fetch()`] or the `fetch` call in [`fetch()`](crate::fetch()). /// /// This could be read from the `gitoxide.userAgent` configuration variable. pub user_agent: (&'static str, Option>), @@ -39,10 +39,7 @@ pub struct Context<'a, T> { #[cfg(feature = "fetch")] mod with_fetch { - use crate::{ - fetch, - fetch::{negotiate, refmap}, - }; + use crate::fetch::{self, negotiate, refmap}; /// For use in [`fetch`](crate::fetch()). pub struct NegotiateContext<'a, 'b, 'c, Objects, Alternates, AlternatesOut, AlternatesErr, Find> @@ -126,7 +123,7 @@ mod with_fetch { /// [`refmap::SpecIndex::ExplicitInRemote`] in [`refmap::Mapping`]. pub refspecs: Vec, /// Refspecs which have been added implicitly due to settings of the `remote`, usually pre-initialized from - /// [`extra_refspecs` in RefMap options](refmap::init::Options). + /// [`extra_refspecs` in RefMap options](refmap::init::Context). /// They are referred to by [`refmap::SpecIndex::Implicit`] in [`refmap::Mapping`]. /// /// They are never persisted nor are they typically presented to the user. diff --git a/gix-protocol/src/handshake/function.rs b/gix-protocol/src/handshake/function.rs index a4b9261c38a..a4ee366b3d6 100644 --- a/gix-protocol/src/handshake/function.rs +++ b/gix-protocol/src/handshake/function.rs @@ -2,11 +2,12 @@ use gix_features::{progress, progress::Progress}; use gix_transport::{client, Service}; use maybe_async::maybe_async; -use super::{Error, Outcome}; +use super::Error; #[cfg(feature = "async-client")] use crate::transport::client::async_io::{SetServiceResponse, Transport}; #[cfg(feature = "blocking-client")] use crate::transport::client::blocking_io::{SetServiceResponse, Transport}; +use crate::Handshake; use crate::{credentials, handshake::refs}; /// Perform a handshake with the server on the other side of `transport`, with `authenticate` being used if authentication @@ -21,7 +22,7 @@ pub async fn handshake( mut authenticate: AuthFn, extra_parameters: Vec<(String, Option)>, progress: &mut impl Progress, -) -> Result +) -> Result where AuthFn: FnMut(credentials::helper::Action) -> credentials::protocol::Result, T: Transport, @@ -103,7 +104,7 @@ where .map(|(refs, shallow)| (Some(refs), Some(shallow))) .unwrap_or_default(); - Ok(Outcome { + Ok(Handshake { server_protocol_version, refs, v1_shallow_updates, diff --git a/gix-protocol/src/handshake/mod.rs b/gix-protocol/src/handshake/mod.rs index 64ba19aa0eb..2a6a08911cc 100644 --- a/gix-protocol/src/handshake/mod.rs +++ b/gix-protocol/src/handshake/mod.rs @@ -50,20 +50,70 @@ pub enum Ref { }, } -/// The result of the [`handshake()`][super::handshake()] function. -#[derive(Default, Debug, Clone)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg(feature = "handshake")] -pub struct Outcome { - /// The protocol version the server responded with. It might have downgraded the desired version. - pub server_protocol_version: gix_transport::Protocol, - /// The references reported as part of the `Protocol::V1` handshake, or `None` otherwise as V2 requires a separate request. - pub refs: Option>, - /// Shallow updates as part of the `Protocol::V1`, to shallow a particular object. - /// Note that unshallowing isn't supported here. - pub v1_shallow_updates: Option>, - /// The server capabilities. - pub capabilities: gix_transport::client::Capabilities, +pub(crate) mod hero { + use crate::handshake::Ref; + + /// The result of the [`handshake()`](crate::handshake()) function. + #[derive(Default, Debug, Clone)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct Handshake { + /// The protocol version the server responded with. It might have downgraded the desired version. + pub server_protocol_version: gix_transport::Protocol, + /// The references reported as part of the `Protocol::V1` handshake, or `None` otherwise as V2 requires a separate request. + pub refs: Option>, + /// Shallow updates as part of the `Protocol::V1`, to shallow a particular object. + /// Note that unshallowing isn't supported here. + pub v1_shallow_updates: Option>, + /// The server capabilities. + pub capabilities: gix_transport::client::Capabilities, + } + + #[cfg(feature = "fetch")] + mod fetch { + #[cfg(feature = "async-client")] + use crate::transport::client::async_io::Transport; + #[cfg(feature = "blocking-client")] + use crate::transport::client::blocking_io::Transport; + use crate::Handshake; + use gix_features::progress::Progress; + use std::borrow::Cow; + + impl Handshake { + /// Obtain a [refmap](crate::fetch::RefMap) either from this instance, taking it out in the process, if the handshake was + /// created from a V1 connection, or use `transport` to fetch the refmap as a separate command invocation. + #[allow(clippy::result_large_err)] + #[maybe_async::maybe_async] + pub async fn fetch_or_extract_refmap( + &mut self, + mut progress: impl Progress, + transport: &mut T, + user_agent: (&'static str, Option>), + trace_packetlines: bool, + prefix_from_spec_as_filter_on_remote: bool, + refmap_context: crate::fetch::refmap::init::Context, + ) -> Result + where + T: Transport, + { + Ok(match self.refs.take() { + Some(refs) => crate::fetch::RefMap::from_refs(refs, &self.capabilities, refmap_context)?, + None => { + crate::fetch::RefMap::fetch( + &mut progress, + &self.capabilities, + transport, + user_agent, + trace_packetlines, + prefix_from_spec_as_filter_on_remote, + refmap_context, + ) + .await? + } + }) + } + } + } } #[cfg(feature = "handshake")] diff --git a/gix-protocol/src/lib.rs b/gix-protocol/src/lib.rs index 8c75512928d..9765b102d61 100644 --- a/gix-protocol/src/lib.rs +++ b/gix-protocol/src/lib.rs @@ -61,6 +61,8 @@ pub mod handshake; #[cfg(any(feature = "blocking-client", feature = "async-client"))] #[cfg(feature = "handshake")] pub use handshake::function::handshake; +#[cfg(feature = "handshake")] +pub use handshake::hero::Handshake; /// pub mod ls_refs; diff --git a/gix-protocol/src/ls_refs.rs b/gix-protocol/src/ls_refs.rs index 3a435c5cd53..d9fd8c95c5d 100644 --- a/gix-protocol/src/ls_refs.rs +++ b/gix-protocol/src/ls_refs.rs @@ -60,25 +60,24 @@ pub(crate) mod function { indicate_end_of_interaction, Command, }; - /// Invoke an ls-refs V2 command on `transport`, which requires a prior handshake that yielded - /// server `capabilities`. `prepare_ls_refs(capabilities, arguments, features)` can be used to alter the _ls-refs_. `progress` is used to provide feedback. - /// Note that `prepare_ls_refs()` is expected to add the `(agent, Some(name))` to the list of `features`. + /// Invoke a ls-refs V2 command on `transport`, which requires a prior handshake that yielded + /// server `capabilities`. `prepare_ls_refs(capabilities, arguments)` can be used to alter the _ls-refs_. + /// `progress` is used to provide feedback. + /// The `agent` information will be added to the features sent to the server. /// If `trace` is `true`, all packetlines received or sent will be passed to the facilities of the `gix-trace` crate. #[maybe_async] pub async fn ls_refs( mut transport: impl Transport, capabilities: &Capabilities, - prepare_ls_refs: impl FnOnce( - &Capabilities, - &mut Vec, - &mut Vec<(&str, Option>)>, - ) -> std::io::Result, + prepare_ls_refs: impl FnOnce(&Capabilities, &mut Vec) -> std::io::Result, progress: &mut impl Progress, trace: bool, + agent: (&'static str, Option>), ) -> Result, Error> { let _span = gix_features::trace::detail!("gix_protocol::ls_refs()", capabilities = ?capabilities); let ls_refs = Command::LsRefs; let mut ls_features = ls_refs.default_features(gix_transport::Protocol::V2, capabilities); + ls_features.push(agent); let mut ls_args = ls_refs.initial_v2_arguments(&ls_features); if capabilities .capability("ls-refs") @@ -87,7 +86,7 @@ pub(crate) mod function { { ls_args.push("unborn".into()); } - let refs = match prepare_ls_refs(capabilities, &mut ls_args, &mut ls_features) { + let refs = match prepare_ls_refs(capabilities, &mut ls_args) { Ok(Action::Skip) => Vec::new(), Ok(Action::Continue) => { ls_refs.validate_argument_prefixes( diff --git a/gix-protocol/tests/protocol/fetch/_impl.rs b/gix-protocol/tests/protocol/fetch/_impl.rs index e3d7077d195..77866afda1b 100644 --- a/gix-protocol/tests/protocol/fetch/_impl.rs +++ b/gix-protocol/tests/protocol/fetch/_impl.rs @@ -74,7 +74,7 @@ mod fetch_fn { P: NestedProgress + 'static, P::SubProgress: 'static, { - let gix_protocol::handshake::Outcome { + let gix_protocol::Handshake { server_protocol_version: protocol_version, refs, v1_shallow_updates: _ignored_shallow_updates_as_it_is_deprecated, @@ -94,13 +94,10 @@ mod fetch_fn { gix_protocol::ls_refs( &mut transport, &capabilities, - |a, b, c| { - let res = delegate.prepare_ls_refs(a, b, c); - c.push(("agent", Some(Cow::Owned(agent.clone())))); - res - }, + |a, b| delegate.prepare_ls_refs(a, b), &mut progress, trace, + ("agent", Some(Cow::Owned(agent.clone()))), ) .await? } @@ -240,7 +237,6 @@ mod delegate { &mut self, _server: &Capabilities, _arguments: &mut Vec, - _features: &mut Vec<(&str, Option>)>, ) -> std::io::Result { Ok(ls_refs::Action::Continue) } @@ -310,9 +306,8 @@ mod delegate { &mut self, _server: &Capabilities, _arguments: &mut Vec, - _features: &mut Vec<(&str, Option>)>, ) -> io::Result { - self.deref_mut().prepare_ls_refs(_server, _arguments, _features) + self.deref_mut().prepare_ls_refs(_server, _arguments) } fn prepare_fetch( @@ -344,9 +339,8 @@ mod delegate { &mut self, _server: &Capabilities, _arguments: &mut Vec, - _features: &mut Vec<(&str, Option>)>, ) -> io::Result { - self.deref_mut().prepare_ls_refs(_server, _arguments, _features) + self.deref_mut().prepare_ls_refs(_server, _arguments) } fn prepare_fetch( diff --git a/gix-protocol/tests/protocol/fetch/mod.rs b/gix-protocol/tests/protocol/fetch/mod.rs index 03f69bed8d8..6725959a58f 100644 --- a/gix-protocol/tests/protocol/fetch/mod.rs +++ b/gix-protocol/tests/protocol/fetch/mod.rs @@ -106,7 +106,6 @@ impl DelegateBlocking for CloneRefInWantDelegate { &mut self, _server: &Capabilities, _arguments: &mut Vec, - _features: &mut Vec<(&str, Option>)>, ) -> io::Result { Ok(ls_refs::Action::Skip) } @@ -150,7 +149,6 @@ impl DelegateBlocking for LsRemoteDelegate { &mut self, _server: &Capabilities, _arguments: &mut Vec, - _features: &mut Vec<(&str, Option>)>, ) -> std::io::Result { match self.abort_with.take() { Some(err) => Err(err), diff --git a/gix-transport/Cargo.toml b/gix-transport/Cargo.toml index 507bc758aec..a73c202b379 100644 --- a/gix-transport/Cargo.toml +++ b/gix-transport/Cargo.toml @@ -18,8 +18,6 @@ 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 = [ diff --git a/gix/src/remote/connection/fetch/mod.rs b/gix/src/remote/connection/fetch/mod.rs index 91838be08b5..6efb6be4f73 100644 --- a/gix/src/remote/connection/fetch/mod.rs +++ b/gix/src/remote/connection/fetch/mod.rs @@ -76,7 +76,7 @@ pub struct Outcome { /// The result of the initial mapping of references, the prerequisite for any fetch. pub ref_map: RefMap, /// The outcome of the handshake with the server. - pub handshake: gix_protocol::handshake::Outcome, + pub handshake: gix_protocol::Handshake, /// The status of the operation to indicate what happened. pub status: Status, } diff --git a/gix/src/remote/connection/mod.rs b/gix/src/remote/connection/mod.rs index 9155a880ed2..c5322c519f0 100644 --- a/gix/src/remote/connection/mod.rs +++ b/gix/src/remote/connection/mod.rs @@ -20,7 +20,7 @@ where pub(crate) authenticate: Option>, pub(crate) transport_options: Option>, pub(crate) transport: gix_protocol::SendFlushOnDrop, - pub(crate) handshake: Option, + pub(crate) handshake: Option, pub(crate) trace: bool, } diff --git a/gix/src/remote/connection/ref_map.rs b/gix/src/remote/connection/ref_map.rs index a66813ec0d0..51b550a7e8a 100644 --- a/gix/src/remote/connection/ref_map.rs +++ b/gix/src/remote/connection/ref_map.rs @@ -92,7 +92,7 @@ where mut self, progress: impl Progress, options: Options, - ) -> Result<(fetch::RefMap, gix_protocol::handshake::Outcome), Error> { + ) -> Result<(fetch::RefMap, gix_protocol::Handshake), Error> { let refmap = self.ref_map_by_ref(progress, options).await?; let handshake = self .handshake @@ -143,29 +143,29 @@ where if let Some(config) = self.transport_options.as_ref() { self.transport.inner.configure(&**config)?; } - let mut handshake = gix_protocol::fetch::handshake( + let mut handshake: gix_protocol::Handshake = gix_protocol::fetch::handshake( &mut self.transport.inner, authenticate, handshake_parameters, &mut progress, ) .await?; - let refmap = gix_protocol::fetch::RefMap::new( - progress, - &self.remote.fetch_specs, - gix_protocol::fetch::Context { - handshake: &mut handshake, - transport: &mut self.transport.inner, - user_agent: self.remote.repo.config.user_agent_tuple(), - trace_packetlines: self.trace, - }, - gix_protocol::fetch::refmap::init::Options { + + let context = fetch::refmap::init::Context { + fetch_refspecs: self.remote.fetch_specs.clone(), + extra_refspecs, + }; + let ref_map = handshake + .fetch_or_extract_refmap( + progress, + &mut self.transport.inner, + self.remote.repo.config.user_agent_tuple(), + self.trace, prefix_from_spec_as_filter_on_remote, - extra_refspecs, - }, - ) - .await?; + context, + ) + .await?; self.handshake = Some(handshake); - Ok(refmap) + Ok(ref_map) } }