upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/git
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-11-21 15:35:19 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-11-21 15:35:19 +0000
commitee7e115b2d0e6a6eee42eb875199c965696017d5 (patch)
tree634ab7f960d56dc9073ebc85baf9fa6c193a32c8 /src/git
parent97e21b62eab89bab1456db7df27df8f1c85399f0 (diff)
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?
Diffstat (limited to 'src/git')
-rw-r--r--src/git/handlers.rs47
-rw-r--r--src/git/protocol.rs8
-rw-r--r--src/git/subprocess.rs2
3 files changed, 49 insertions, 8 deletions
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 @@
4 4
5use std::path::PathBuf; 5use std::path::PathBuf;
6use hyper::{body::Bytes, Response, StatusCode}; 6use hyper::{body::Bytes, Response, StatusCode};
7use http_body_util::Full;
7use tokio::io::{AsyncReadExt, AsyncWriteExt}; 8use tokio::io::{AsyncReadExt, AsyncWriteExt};
8use tracing::{debug, error, warn}; 9use tracing::{debug, error, warn};
9 10
@@ -16,7 +17,7 @@ use super::subprocess::GitSubprocess;
16pub async fn handle_info_refs( 17pub async fn handle_info_refs(
17 repo_path: PathBuf, 18 repo_path: PathBuf,
18 service: GitService, 19 service: GitService,
19) -> Result<Response<String>, GitError> { 20) -> Result<Response<Full<Bytes>>, GitError> {
20 debug!("Handling info/refs for {:?} with service {:?}", repo_path, service); 21 debug!("Handling info/refs for {:?} with service {:?}", repo_path, service);
21 22
22 // Check if repository exists 23 // Check if repository exists
@@ -34,6 +35,8 @@ pub async fn handle_info_refs(
34 35
35 // Read the output from git 36 // Read the output from git
36 let mut output = Vec::new(); 37 let mut output = Vec::new();
38 let mut stderr_output = Vec::new();
39
37 if let Some(stdout) = git.take_stdout() { 40 if let Some(stdout) = git.take_stdout() {
38 let mut stdout = stdout; 41 let mut stdout = stdout;
39 stdout.read_to_end(&mut output).await 42 stdout.read_to_end(&mut output).await
@@ -42,6 +45,15 @@ pub async fn handle_info_refs(
42 GitError::IoError(e) 45 GitError::IoError(e)
43 })?; 46 })?;
44 } 47 }
48
49 if let Some(stderr) = git.take_stderr() {
50 let mut stderr = stderr;
51 stderr.read_to_end(&mut stderr_output).await
52 .map_err(|e| {
53 error!("Failed to read git stderr: {}", e);
54 GitError::IoError(e)
55 })?;
56 }
45 57
46 // Wait for process to complete 58 // Wait for process to complete
47 let status = git.wait().await 59 let status = git.wait().await
@@ -51,7 +63,8 @@ pub async fn handle_info_refs(
51 })?; 63 })?;
52 64
53 if !status.success() { 65 if !status.success() {
54 error!("Git process failed with status: {:?}", status); 66 let stderr_str = String::from_utf8_lossy(&stderr_output);
67 error!("Git process failed with status: {:?}, stderr: {}", status, stderr_str);
55 return Err(GitError::GitFailed(status.code())); 68 return Err(GitError::GitFailed(status.code()));
56 } 69 }
57 70
@@ -70,7 +83,7 @@ pub async fn handle_info_refs(
70 .status(StatusCode::OK) 83 .status(StatusCode::OK)
71 .header("content-type", service.advertisement_content_type()) 84 .header("content-type", service.advertisement_content_type())
72 .header("cache-control", "no-cache") 85 .header("cache-control", "no-cache")
73 .body(String::from_utf8_lossy(&response_body).to_string()) 86 .body(Full::new(Bytes::from(response_body)))
74 .unwrap()) 87 .unwrap())
75} 88}
76 89
@@ -78,7 +91,7 @@ pub async fn handle_info_refs(
78pub async fn handle_upload_pack( 91pub async fn handle_upload_pack(
79 repo_path: PathBuf, 92 repo_path: PathBuf,
80 request_body: Bytes, 93 request_body: Bytes,
81) -> Result<Response<String>, GitError> { 94) -> Result<Response<Full<Bytes>>, GitError> {
82 debug!("Handling upload-pack for {:?}", repo_path); 95 debug!("Handling upload-pack for {:?}", repo_path);
83 96
84 if !repo_path.exists() { 97 if !repo_path.exists() {
@@ -99,17 +112,27 @@ pub async fn handle_upload_pack(
99 112
100 // Read response from git's stdout 113 // Read response from git's stdout
101 let mut output = Vec::new(); 114 let mut output = Vec::new();
115 let mut stderr_output = Vec::new();
116
102 if let Some(stdout) = git.take_stdout() { 117 if let Some(stdout) = git.take_stdout() {
103 let mut stdout = stdout; 118 let mut stdout = stdout;
104 stdout.read_to_end(&mut output).await 119 stdout.read_to_end(&mut output).await
105 .map_err(GitError::IoError)?; 120 .map_err(GitError::IoError)?;
106 } 121 }
122
123 if let Some(stderr) = git.take_stderr() {
124 let mut stderr = stderr;
125 stderr.read_to_end(&mut stderr_output).await
126 .map_err(GitError::IoError)?;
127 }
107 128
108 // Wait for process 129 // Wait for process
109 let status = git.wait().await 130 let status = git.wait().await
110 .map_err(GitError::IoError)?; 131 .map_err(GitError::IoError)?;
111 132
112 if !status.success() { 133 if !status.success() {
134 let stderr_str = String::from_utf8_lossy(&stderr_output);
135 error!("Git upload-pack failed: {}", stderr_str);
113 return Err(GitError::GitFailed(status.code())); 136 return Err(GitError::GitFailed(status.code()));
114 } 137 }
115 138
@@ -117,7 +140,7 @@ pub async fn handle_upload_pack(
117 .status(StatusCode::OK) 140 .status(StatusCode::OK)
118 .header("content-type", GitService::UploadPack.result_content_type()) 141 .header("content-type", GitService::UploadPack.result_content_type())
119 .header("cache-control", "no-cache") 142 .header("cache-control", "no-cache")
120 .body(String::from_utf8_lossy(&output).to_string()) 143 .body(Full::new(Bytes::from(output)))
121 .unwrap()) 144 .unwrap())
122} 145}
123 146
@@ -127,7 +150,7 @@ pub async fn handle_upload_pack(
127pub async fn handle_receive_pack( 150pub async fn handle_receive_pack(
128 repo_path: PathBuf, 151 repo_path: PathBuf,
129 request_body: Bytes, 152 request_body: Bytes,
130) -> Result<Response<String>, GitError> { 153) -> Result<Response<Full<Bytes>>, GitError> {
131 debug!("Handling receive-pack for {:?}", repo_path); 154 debug!("Handling receive-pack for {:?}", repo_path);
132 155
133 if !repo_path.exists() { 156 if !repo_path.exists() {
@@ -151,17 +174,27 @@ pub async fn handle_receive_pack(
151 174
152 // Read response from git's stdout 175 // Read response from git's stdout
153 let mut output = Vec::new(); 176 let mut output = Vec::new();
177 let mut stderr_output = Vec::new();
178
154 if let Some(stdout) = git.take_stdout() { 179 if let Some(stdout) = git.take_stdout() {
155 let mut stdout = stdout; 180 let mut stdout = stdout;
156 stdout.read_to_end(&mut output).await 181 stdout.read_to_end(&mut output).await
157 .map_err(GitError::IoError)?; 182 .map_err(GitError::IoError)?;
158 } 183 }
184
185 if let Some(stderr) = git.take_stderr() {
186 let mut stderr = stderr;
187 stderr.read_to_end(&mut stderr_output).await
188 .map_err(GitError::IoError)?;
189 }
159 190
160 // Wait for process 191 // Wait for process
161 let status = git.wait().await 192 let status = git.wait().await
162 .map_err(GitError::IoError)?; 193 .map_err(GitError::IoError)?;
163 194
164 if !status.success() { 195 if !status.success() {
196 let stderr_str = String::from_utf8_lossy(&stderr_output);
197 error!("Git receive-pack failed: {}", stderr_str);
165 return Err(GitError::GitFailed(status.code())); 198 return Err(GitError::GitFailed(status.code()));
166 } 199 }
167 200
@@ -169,7 +202,7 @@ pub async fn handle_receive_pack(
169 .status(StatusCode::OK) 202 .status(StatusCode::OK)
170 .header("content-type", GitService::ReceivePack.result_content_type()) 203 .header("content-type", GitService::ReceivePack.result_content_type())
171 .header("cache-control", "no-cache") 204 .header("cache-control", "no-cache")
172 .body(String::from_utf8_lossy(&output).to_string()) 205 .body(Full::new(Bytes::from(output)))
173 .unwrap()) 206 .unwrap())
174} 207}
175 208
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 {
157 } 157 }
158 } 158 }
159 159
160 /// Get the git command name (without "git-" prefix) for subprocess invocation
161 pub fn command_name(&self) -> &'static str {
162 match self {
163 Self::UploadPack => "upload-pack",
164 Self::ReceivePack => "receive-pack",
165 }
166 }
167
160 /// Get the content type for the service advertisement 168 /// Get the content type for the service advertisement
161 pub fn advertisement_content_type(&self) -> &'static str { 169 pub fn advertisement_content_type(&self) -> &'static str {
162 match self { 170 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 {
30 let repo_path = repo_path.as_ref(); 30 let repo_path = repo_path.as_ref();
31 31
32 let mut cmd = Command::new("git"); 32 let mut cmd = Command::new("git");
33 cmd.arg(service.as_str()); 33 cmd.arg(service.command_name());
34 34
35 if advertise { 35 if advertise {
36 cmd.arg("--advertise-refs"); 36 cmd.arg("--advertise-refs");