Skip to content

Commit

Permalink
FAIL: try to make the transport configurable after being boxed, but… (#…
Browse files Browse the repository at this point in the history
…450)

…that would force it to be 'static, which is something we excplicitly
cannot have. We need references to be contained within, if I remember
correctly.
  • Loading branch information
Byron committed Sep 22, 2022
1 parent 0dc7206 commit 5bef0a0
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 3 deletions.
26 changes: 26 additions & 0 deletions git-repository/src/remote/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod access {
remote::{connection::CredentialsFn, Connection},
Remote,
};
use std::any::Any;

/// Builder
impl<'a, 'repo, T, P> Connection<'a, 'repo, T, P> {
Expand Down Expand Up @@ -62,6 +63,31 @@ mod access {
pub fn remote(&self) -> &Remote<'repo> {
self.remote
}

/// Return the connection's transport.
pub fn transport(&self) -> &T {
&self.transport
}
}

/// Access to the transport if it can be downcast to a particular type.
impl<'a, 'repo, T, P> Connection<'a, 'repo, T, P>
where
T: crate::protocol::transport::client::Transport + 'static,
{
/// Try to cast our transport `T` into `U`, and pass it to `f` to allow any kind of configuration.
///
/// Note that if the case fails and `f` is not called at all, `false` is returned.
pub fn configure_transport<U: 'static, E>(
&mut self,
f: impl FnOnce(&mut U) -> Result<(), E>,
) -> Result<bool, E> {
let transport = (&mut self.transport) as &mut dyn Any;
match transport.downcast_mut::<U>() {
Some(transport) => f(transport).map(|_| true),
None => Ok(false),
}
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions git-repository/src/remote/connection/ref_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ where
&mut credentials_storage
}
};
let transport = &mut self.transport;
let mut outcome =
git_protocol::fetch::handshake(&mut self.transport, authenticate, extra_parameters, &mut self.progress)
.await?;
git_protocol::fetch::handshake(&mut *transport, authenticate, extra_parameters, &mut self.progress).await?;
let refs = match outcome.refs.take() {
Some(refs) => refs,
None => {
let specs = &self.remote.fetch_specs;
git_protocol::fetch::refs(
&mut self.transport,
transport,
outcome.server_protocol_version,
&outcome.capabilities,
|_capabilities, arguments, _features| {
Expand Down
5 changes: 5 additions & 0 deletions git-transport/src/client/blocking_io/file.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::any::Any;
use std::process::{self, Command, Stdio};

use bstr::{BString, ByteSlice};
Expand Down Expand Up @@ -83,6 +84,10 @@ impl SpawnProcessOnDemand {
}

impl client::TransportWithoutIO for SpawnProcessOnDemand {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

fn request(
&mut self,
write_mode: WriteMode,
Expand Down
5 changes: 5 additions & 0 deletions git-transport/src/client/blocking_io/http/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::any::Any;
use std::{
borrow::Cow,
convert::Infallible,
Expand Down Expand Up @@ -99,6 +100,10 @@ fn append_url(base: &str, suffix: &str) -> String {
}

impl<H: Http> client::TransportWithoutIO for Transport<H> {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

fn set_identity(&mut self, identity: git_sec::identity::Account) -> Result<(), client::Error> {
self.identity = Some(identity);
Ok(())
Expand Down
5 changes: 5 additions & 0 deletions git-transport/src/client/git/blocking_io.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::any::Any;
use std::io::Write;

use bstr::BString;
Expand All @@ -13,6 +14,10 @@ where
R: std::io::Read,
W: std::io::Write,
{
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

fn request(
&mut self,
write_mode: client::WriteMode,
Expand Down
14 changes: 14 additions & 0 deletions git-transport/src/client/traits.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::any::Any;
use std::ops::{Deref, DerefMut};

#[cfg(any(feature = "blocking-client", feature = "async-client"))]
Expand All @@ -7,6 +8,11 @@ use crate::{client::Error, Protocol};
/// This trait represents all transport related functions that don't require any input/output to be done which helps
/// implementation to share more code across blocking and async programs.
pub trait TransportWithoutIO {
/// Cast this type as dyn trait to allow casting it back to a known concrete type.
///
/// This is useful for configuration after a boxed transport implementation has been crated.
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;

/// If the handshake or subsequent reads failed with [std::io::ErrorKind::PermissionDenied], use this method to
/// inform the transport layer about the identity to use for subsequent calls.
/// If authentication continues to fail even with an identity set, consider communicating this to the provider
Expand Down Expand Up @@ -50,6 +56,10 @@ pub trait TransportWithoutIO {

// Would be nice if the box implementation could auto-forward to all implemented traits.
impl<T: TransportWithoutIO + ?Sized> TransportWithoutIO for Box<T> {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

fn set_identity(&mut self, identity: git_sec::identity::Account) -> Result<(), Error> {
self.deref_mut().set_identity(identity)
}
Expand All @@ -73,6 +83,10 @@ impl<T: TransportWithoutIO + ?Sized> TransportWithoutIO for Box<T> {
}

impl<T: TransportWithoutIO + ?Sized> TransportWithoutIO for &mut T {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

fn set_identity(&mut self, identity: git_sec::identity::Account) -> Result<(), Error> {
self.deref_mut().set_identity(identity)
}
Expand Down

0 comments on commit 5bef0a0

Please sign in to comment.