upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/git/subprocess.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-07 21:35:56 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-07 21:35:56 +0000
commit457e296d90e2f7c2808e216f2ef0608b70f76553 (patch)
tree8b6529cb9db3bb562842a4cfb0bf8c217ed7db1a /src/git/subprocess.rs
parent0550b3229f35ef3ee125bac47d85bbd08d1250b1 (diff)
Add Git protocol v2 support to fix modern git client compatibility
Modern git clients (2.51.0+) default to protocol v2 and send the Git-Protocol header. The server must pass this to git processes via the GIT_PROTOCOL environment variable for proper negotiation. Changes: - Extract Git-Protocol header in HTTP layer (src/http/mod.rs) - Pass git_protocol parameter through all handler functions - Set GIT_PROTOCOL env var when spawning git subprocesses - Update all tests to pass None for backward compatibility This fixes hangs/timeouts when modern git clients connect to the server. Fixes issue discovered in work/2025-01-07-pr-clone-tag-sync-investigation.md
Diffstat (limited to 'src/git/subprocess.rs')
-rw-r--r--src/git/subprocess.rs12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/git/subprocess.rs b/src/git/subprocess.rs
index 2d9a981..acee726 100644
--- a/src/git/subprocess.rs
+++ b/src/git/subprocess.rs
@@ -22,10 +22,12 @@ impl GitSubprocess {
22 /// * `service` - The Git service (upload-pack or receive-pack) 22 /// * `service` - The Git service (upload-pack or receive-pack)
23 /// * `repo_path` - Path to the bare Git repository 23 /// * `repo_path` - Path to the bare Git repository
24 /// * `advertise` - If true, run with --advertise-refs flag 24 /// * `advertise` - If true, run with --advertise-refs flag
25 /// * `git_protocol` - Optional Git protocol version (e.g., "version=2")
25 pub fn spawn( 26 pub fn spawn(
26 service: GitService, 27 service: GitService,
27 repo_path: impl AsRef<Path>, 28 repo_path: impl AsRef<Path>,
28 advertise: bool, 29 advertise: bool,
30 git_protocol: Option<&str>,
29 ) -> std::io::Result<Self> { 31 ) -> std::io::Result<Self> {
30 let repo_path = repo_path.as_ref(); 32 let repo_path = repo_path.as_ref();
31 33
@@ -52,6 +54,12 @@ impl GitSubprocess {
52 cmd.stdout(Stdio::piped()); 54 cmd.stdout(Stdio::piped());
53 cmd.stderr(Stdio::piped()); 55 cmd.stderr(Stdio::piped());
54 56
57 // Set GIT_PROTOCOL environment variable if provided
58 // This enables Git protocol v2 support for modern git clients
59 if let Some(protocol) = git_protocol {
60 cmd.env("GIT_PROTOCOL", protocol);
61 }
62
55 let child = cmd.spawn()?; 63 let child = cmd.spawn()?;
56 64
57 Ok(Self { child }) 65 Ok(Self { child })
@@ -118,7 +126,7 @@ mod tests {
118 #[tokio::test] 126 #[tokio::test]
119 async fn test_spawn_upload_pack_advertise() { 127 async fn test_spawn_upload_pack_advertise() {
120 let repo = create_bare_repo(); 128 let repo = create_bare_repo();
121 let mut proc = GitSubprocess::spawn(GitService::UploadPack, repo.path(), true) 129 let mut proc = GitSubprocess::spawn(GitService::UploadPack, repo.path(), true, None)
122 .expect("Failed to spawn git"); 130 .expect("Failed to spawn git");
123 131
124 // Should have spawned successfully 132 // Should have spawned successfully
@@ -132,7 +140,7 @@ mod tests {
132 #[tokio::test] 140 #[tokio::test]
133 async fn test_spawn_receive_pack() { 141 async fn test_spawn_receive_pack() {
134 let repo = create_bare_repo(); 142 let repo = create_bare_repo();
135 let mut proc = GitSubprocess::spawn(GitService::ReceivePack, repo.path(), false) 143 let mut proc = GitSubprocess::spawn(GitService::ReceivePack, repo.path(), false, None)
136 .expect("Failed to spawn git"); 144 .expect("Failed to spawn git");
137 145
138 assert!(proc.stdout().is_some()); 146 assert!(proc.stdout().is_some());