From ee7e115b2d0e6a6eee42eb875199c965696017d5 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Fri, 21 Nov 2025 15:35:19 +0000 Subject: fixed http clone but do we really nedd to create a blank commit? I dont think ngit-relay does that. Do we need to se the default branch or is this automatic? --- src/git/handlers.rs | 47 ++++++++++++++++++++++++++++++++++++++++------- src/git/protocol.rs | 8 ++++++++ src/git/subprocess.rs | 2 +- 3 files changed, 49 insertions(+), 8 deletions(-) (limited to 'src/git') diff --git a/src/git/handlers.rs b/src/git/handlers.rs index 0efc9d0..ac35d14 100644 --- a/src/git/handlers.rs +++ b/src/git/handlers.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use hyper::{body::Bytes, Response, StatusCode}; +use http_body_util::Full; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tracing::{debug, error, warn}; @@ -16,7 +17,7 @@ use super::subprocess::GitSubprocess; pub async fn handle_info_refs( repo_path: PathBuf, service: GitService, -) -> Result, GitError> { +) -> Result>, GitError> { debug!("Handling info/refs for {:?} with service {:?}", repo_path, service); // Check if repository exists @@ -34,6 +35,8 @@ pub async fn handle_info_refs( // Read the output from git let mut output = Vec::new(); + let mut stderr_output = Vec::new(); + if let Some(stdout) = git.take_stdout() { let mut stdout = stdout; stdout.read_to_end(&mut output).await @@ -42,6 +45,15 @@ pub async fn handle_info_refs( GitError::IoError(e) })?; } + + if let Some(stderr) = git.take_stderr() { + let mut stderr = stderr; + stderr.read_to_end(&mut stderr_output).await + .map_err(|e| { + error!("Failed to read git stderr: {}", e); + GitError::IoError(e) + })?; + } // Wait for process to complete let status = git.wait().await @@ -51,7 +63,8 @@ pub async fn handle_info_refs( })?; if !status.success() { - error!("Git process failed with status: {:?}", status); + let stderr_str = String::from_utf8_lossy(&stderr_output); + error!("Git process failed with status: {:?}, stderr: {}", status, stderr_str); return Err(GitError::GitFailed(status.code())); } @@ -70,7 +83,7 @@ pub async fn handle_info_refs( .status(StatusCode::OK) .header("content-type", service.advertisement_content_type()) .header("cache-control", "no-cache") - .body(String::from_utf8_lossy(&response_body).to_string()) + .body(Full::new(Bytes::from(response_body))) .unwrap()) } @@ -78,7 +91,7 @@ pub async fn handle_info_refs( pub async fn handle_upload_pack( repo_path: PathBuf, request_body: Bytes, -) -> Result, GitError> { +) -> Result>, GitError> { debug!("Handling upload-pack for {:?}", repo_path); if !repo_path.exists() { @@ -99,17 +112,27 @@ pub async fn handle_upload_pack( // Read response from git's stdout let mut output = Vec::new(); + let mut stderr_output = Vec::new(); + if let Some(stdout) = git.take_stdout() { let mut stdout = stdout; stdout.read_to_end(&mut output).await .map_err(GitError::IoError)?; } + + if let Some(stderr) = git.take_stderr() { + let mut stderr = stderr; + stderr.read_to_end(&mut stderr_output).await + .map_err(GitError::IoError)?; + } // Wait for process let status = git.wait().await .map_err(GitError::IoError)?; if !status.success() { + let stderr_str = String::from_utf8_lossy(&stderr_output); + error!("Git upload-pack failed: {}", stderr_str); return Err(GitError::GitFailed(status.code())); } @@ -117,7 +140,7 @@ pub async fn handle_upload_pack( .status(StatusCode::OK) .header("content-type", GitService::UploadPack.result_content_type()) .header("cache-control", "no-cache") - .body(String::from_utf8_lossy(&output).to_string()) + .body(Full::new(Bytes::from(output))) .unwrap()) } @@ -127,7 +150,7 @@ pub async fn handle_upload_pack( pub async fn handle_receive_pack( repo_path: PathBuf, request_body: Bytes, -) -> Result, GitError> { +) -> Result>, GitError> { debug!("Handling receive-pack for {:?}", repo_path); if !repo_path.exists() { @@ -151,17 +174,27 @@ pub async fn handle_receive_pack( // Read response from git's stdout let mut output = Vec::new(); + let mut stderr_output = Vec::new(); + if let Some(stdout) = git.take_stdout() { let mut stdout = stdout; stdout.read_to_end(&mut output).await .map_err(GitError::IoError)?; } + + if let Some(stderr) = git.take_stderr() { + let mut stderr = stderr; + stderr.read_to_end(&mut stderr_output).await + .map_err(GitError::IoError)?; + } // Wait for process let status = git.wait().await .map_err(GitError::IoError)?; if !status.success() { + let stderr_str = String::from_utf8_lossy(&stderr_output); + error!("Git receive-pack failed: {}", stderr_str); return Err(GitError::GitFailed(status.code())); } @@ -169,7 +202,7 @@ pub async fn handle_receive_pack( .status(StatusCode::OK) .header("content-type", GitService::ReceivePack.result_content_type()) .header("cache-control", "no-cache") - .body(String::from_utf8_lossy(&output).to_string()) + .body(Full::new(Bytes::from(output))) .unwrap()) } diff --git a/src/git/protocol.rs b/src/git/protocol.rs index 84da131..93177de 100644 --- a/src/git/protocol.rs +++ b/src/git/protocol.rs @@ -157,6 +157,14 @@ impl GitService { } } + /// Get the git command name (without "git-" prefix) for subprocess invocation + pub fn command_name(&self) -> &'static str { + match self { + Self::UploadPack => "upload-pack", + Self::ReceivePack => "receive-pack", + } + } + /// Get the content type for the service advertisement pub fn advertisement_content_type(&self) -> &'static str { match self { diff --git a/src/git/subprocess.rs b/src/git/subprocess.rs index 96eed26..dac3ace 100644 --- a/src/git/subprocess.rs +++ b/src/git/subprocess.rs @@ -30,7 +30,7 @@ impl GitSubprocess { let repo_path = repo_path.as_ref(); let mut cmd = Command::new("git"); - cmd.arg(service.as_str()); + cmd.arg(service.command_name()); if advertise { cmd.arg("--advertise-refs"); -- cgit v1.2.3