Skip to content

Commit c24aa44

Browse files
committed
feat: invoke git command
1 parent b66eabd commit c24aa44

File tree

5 files changed

+62
-7
lines changed

5 files changed

+62
-7
lines changed

gix-transport/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ async-client = [
6565
## Data structures implement `serde::Serialize` and `serde::Deserialize`.
6666
serde = ["dep:serde"]
6767

68-
russh = ["dep:russh", "dep:tokio"]
68+
russh = ["dep:russh", "dep:tokio", "async-client", "async-std"]
6969

7070
[[test]]
7171
name = "blocking-transport"

gix-transport/src/client/async_io/ssh/client.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use std::{ops::DerefMut, sync::Arc, task::ready};
22

33
use russh::{
4-
client::Handle,
5-
client::{Config, Handler},
4+
client::{Config, Handle, Handler},
5+
MethodSet,
66
};
77

88
pub enum AuthMode {
99
UsernamePassword { username: String, password: String },
10+
PublicKey { username: String },
1011
}
1112

1213
#[derive(Clone)]
@@ -36,11 +37,40 @@ impl Client {
3637
} => Err(super::Error::AuthenticationFailed(remaining_methods)),
3738
}
3839
}
40+
AuthMode::PublicKey { username } => {
41+
let mut agent = russh::keys::agent::client::AgentClient::connect_env().await?;
42+
let rsa_hash = handle.best_supported_rsa_hash().await?.flatten();
43+
let mut methods = MethodSet::empty();
44+
for key in agent.request_identities().await? {
45+
match handle
46+
.authenticate_publickey_with(&username, key, rsa_hash, &mut agent)
47+
.await?
48+
{
49+
russh::client::AuthResult::Success => return Ok(()),
50+
russh::client::AuthResult::Failure {
51+
remaining_methods,
52+
partial_success: _,
53+
} => methods = remaining_methods,
54+
}
55+
}
56+
Err(super::Error::AuthenticationFailed(methods))
57+
}
3958
}
4059
}
4160

42-
pub async fn open_session(&mut self) -> Result<Session, super::Error> {
61+
pub async fn open_session(
62+
&mut self,
63+
cmd: impl Into<String>,
64+
env: Vec<(String, String)>,
65+
) -> Result<Session, super::Error> {
4366
let channel = self.handle.channel_open_session().await?;
67+
68+
for (key, value) in env {
69+
channel.set_env(false, key, value).await?;
70+
}
71+
72+
channel.exec(false, cmd.into().bytes().collect::<Vec<_>>()).await?;
73+
4474
let stream = channel.into_stream();
4575
Ok(Session {
4676
stream: Arc::new(std::sync::Mutex::new(stream)),

gix-transport/src/client/async_io/ssh/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,14 @@ pub enum Error {
88
AuthenticationFailed(MethodSet),
99
#[error(transparent)]
1010
Ssh(#[from] russh::Error),
11+
#[error(transparent)]
12+
Keys(#[from] russh::keys::Error),
13+
#[error(transparent)]
14+
Agent(#[from] russh::AgentAuthError),
15+
}
16+
17+
impl From<Error> for crate::client::Error {
18+
fn from(err: Error) -> Self {
19+
Self::NativeSshError(err)
20+
}
1121
}

gix-transport/src/client/async_io/ssh/mod.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,26 @@ impl Transport for NativeSsh {
7373
username: username.clone(),
7474
password: password.clone(),
7575
},
76-
None => return Err(crate::client::Error::AuthenticationUnsupported),
76+
None => client::AuthMode::PublicKey {
77+
username: self
78+
.url
79+
.user()
80+
.map(std::string::ToString::to_string)
81+
.unwrap_or_default(),
82+
},
7783
};
7884

7985
let mut client = client::Client::connect(host, port, auth_mode).await?;
80-
let session = client.open_session().await?;
86+
87+
let session = client
88+
.open_session(
89+
format!("{} {}", service.as_str(), self.url.path),
90+
vec![(
91+
"GIT_PROTOCOL".to_string(),
92+
format!("version={}", self.desired_version as usize),
93+
)],
94+
)
95+
.await?;
8196

8297
let connection = crate::client::git::Connection::new(
8398
session.clone(),

gix-transport/src/client/non_io_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ mod error {
149149
#[error(transparent)]
150150
SshInvocation(SshInvocationError),
151151
#[error(transparent)]
152-
NativeSshError(#[from] NativeSshError),
152+
NativeSshError(NativeSshError),
153153
#[error("The repository path '{path}' could be mistaken for a command-line argument")]
154154
AmbiguousPath { path: BString },
155155
}

0 commit comments

Comments
 (0)