diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-07 21:35:56 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-07 21:35:56 +0000 |
| commit | 457e296d90e2f7c2808e216f2ef0608b70f76553 (patch) | |
| tree | 8b6529cb9db3bb562842a4cfb0bf8c217ed7db1a /src/git/subprocess.rs | |
| parent | 0550b3229f35ef3ee125bac47d85bbd08d1250b1 (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.rs | 12 |
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()); |