git_internal/protocol/
ssh.rs

1/// SSH transport adapter for Git protocol
2///
3/// This module provides SSH-specific handling for Git smart protocol operations.
4/// It's a thin wrapper around the core GitProtocol that handles SSH command
5/// execution and data streaming.
6use super::core::{AuthenticationService, GitProtocol, RepositoryAccess};
7use super::types::{ProtocolError, ProtocolStream};
8
9/// SSH Git protocol handler
10pub struct SshGitHandler<R: RepositoryAccess, A: AuthenticationService> {
11    protocol: GitProtocol<R, A>,
12}
13
14impl<R: RepositoryAccess, A: AuthenticationService> SshGitHandler<R, A> {
15    /// Create a new SSH Git handler
16    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    /// Authenticate SSH session using username and public key
23    /// Call this once after SSH handshake, before running Git commands
24    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    /// Handle git-upload-pack command (for clone/fetch)
33    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    /// Handle git-receive-pack command (for push)
41    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    /// Handle info/refs request for SSH
49    pub async fn handle_info_refs(&mut self, service: &str) -> Result<Vec<u8>, ProtocolError> {
50        self.protocol.info_refs(service).await
51    }
52}
53
54/// SSH-specific utility functions
55/// Parse SSH command line into command and arguments
56pub 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
68/// Check if command is a valid Git SSH command
69pub fn is_git_ssh_command(command: &str) -> bool {
70    matches!(command, "git-upload-pack" | "git-receive-pack")
71}
72
73/// Extract repository path from SSH command arguments
74pub fn extract_repo_path_from_args(args: &[String]) -> Option<&str> {
75    args.first().map(|s| s.as_str())
76}