git_internal/protocol/
ssh.rs1use super::core::{AuthenticationService, GitProtocol, RepositoryAccess};
7use super::types::{ProtocolError, ProtocolStream};
8
9pub struct SshGitHandler<R: RepositoryAccess, A: AuthenticationService> {
11 protocol: GitProtocol<R, A>,
12}
13
14impl<R: RepositoryAccess, A: AuthenticationService> SshGitHandler<R, A> {
15 pub fn new(repo_access: R, auth_service: A) -> Self {
17 let mut protocol = GitProtocol::new(repo_access, auth_service);
18 protocol.set_transport(super::types::TransportProtocol::Ssh);
19 Self { protocol }
20 }
21
22 pub async fn authenticate_ssh(
25 &self,
26 username: &str,
27 public_key: &[u8],
28 ) -> Result<(), ProtocolError> {
29 self.protocol.authenticate_ssh(username, public_key).await
30 }
31
32 pub async fn handle_upload_pack(
34 &mut self,
35 request_data: &[u8],
36 ) -> Result<ProtocolStream, ProtocolError> {
37 self.protocol.upload_pack(request_data).await
38 }
39
40 pub async fn handle_receive_pack(
42 &mut self,
43 request_stream: ProtocolStream,
44 ) -> Result<ProtocolStream, ProtocolError> {
45 self.protocol.receive_pack(request_stream).await
46 }
47
48 pub async fn handle_info_refs(&mut self, service: &str) -> Result<Vec<u8>, ProtocolError> {
50 self.protocol.info_refs(service).await
51 }
52}
53
54pub fn parse_ssh_command(command_line: &str) -> Option<(String, Vec<String>)> {
57 let parts: Vec<&str> = command_line.split_whitespace().collect();
58 if parts.is_empty() {
59 return None;
60 }
61
62 let command = parts[0].to_string();
63 let args = parts[1..].iter().map(|s| s.to_string()).collect();
64
65 Some((command, args))
66}
67
68pub fn is_git_ssh_command(command: &str) -> bool {
70 matches!(command, "git-upload-pack" | "git-receive-pack")
71}
72
73pub fn extract_repo_path_from_args(args: &[String]) -> Option<&str> {
75 args.first().map(|s| s.as_str())
76}