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>2026-02-03 14:50:22 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-03 15:18:23 +0000
commit874a8abe1d076cfafd9baf919ec23d7d58200698 (patch)
treedce0d0d36bddc496ff32f8555a8790d8dc7be7e4 /src/git
parent9fd4350c57bbe986ebf65bf3ea4c996572e81884 (diff)
parent92a9a3bfe0bc522e8ae411991a366a3a6310d525 (diff)
Merge relay.ngit.dev migration: bug fixes and migration tooling
This merge includes critical bug fixes and comprehensive migration tooling developed during the relay.ngit.dev migration effort. Bug Fixes: - Fix git protocol error handling to return HTTP 200 with ERR pkt-line - Fix naughty list false positives and DNS failure identification - Fix database query filters in load_existing_events (remove .since()) - Fix OID fetch tracking to distinguish 0 OIDs from successful fetches - Fix purgatory event source tracking for filtered expiry logging - Implement OID retry logic for 'not our ref' errors Migration Tools & Documentation: - Complete 5-phase migration analysis pipeline with orchestration script - Phase 1: Event fetching from source relay - Phase 2: Git sync verification - Phase 3: Categorization and relay comparison - Phase 4: Log extraction (parse failures, purgatory expiry) - Phase 5: Action classification for migration decisions - Comprehensive migration guide with lessons learned - Troubleshooting guide for permission and corruption issues Configuration: - Add NGIT_LOG_LEVEL configuration option - Update git throttle limits to 60/minute - Improve logging throughout for better observability
Diffstat (limited to 'src/git')
-rw-r--r--src/git/handlers.rs66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/git/handlers.rs b/src/git/handlers.rs
index 017eee4..e3a6ad4 100644
--- a/src/git/handlers.rs
+++ b/src/git/handlers.rs
@@ -99,6 +99,42 @@ pub async fn handle_info_refs(
99 .unwrap()) 99 .unwrap())
100} 100}
101 101
102/// Build an HTTP 200 OK response with an ERR pkt-line for git protocol errors.
103///
104/// Per the git smart HTTP protocol spec, protocol-level errors (like "not our ref")
105/// should be returned as HTTP 200 OK with the error message in pkt-line format:
106/// `PKT-LINE("ERR" SP explanation-text)`
107///
108/// This allows git clients to properly parse and display the error message.
109fn build_git_protocol_error_response(
110 service: GitService,
111 error_message: &str,
112) -> Response<Full<Bytes>> {
113 // Format: "ERR <message>\n"
114 let err_content = format!("ERR {}\n", error_message.trim());
115 let err_pktline = PktLine::data(err_content.as_bytes()).encode();
116
117 Response::builder()
118 .status(StatusCode::OK)
119 .header("content-type", service.result_content_type())
120 .header("cache-control", "no-cache")
121 .body(Full::new(Bytes::from(err_pktline)))
122 .unwrap()
123}
124
125/// Check if a git process failure is a protocol error (vs transport error).
126///
127/// Protocol errors are communicated via stderr when git exits with code 128.
128/// These should be returned to the client as HTTP 200 with ERR pkt-line.
129///
130/// Transport errors (process spawn failures, I/O errors, signals) should
131/// remain as HTTP 500 errors.
132fn is_git_protocol_error(exit_code: Option<i32>, stderr: &[u8]) -> bool {
133 // Git uses exit code 128 for protocol/usage errors
134 // If there's stderr content, it's a protocol error message
135 exit_code == Some(128) && !stderr.is_empty()
136}
137
102/// Handle POST /git-upload-pack (clone/fetch) 138/// Handle POST /git-upload-pack (clone/fetch)
103pub async fn handle_upload_pack( 139pub async fn handle_upload_pack(
104 repo_path: PathBuf, 140 repo_path: PathBuf,
@@ -150,6 +186,21 @@ pub async fn handle_upload_pack(
150 186
151 if !status.success() { 187 if !status.success() {
152 let stderr_str = String::from_utf8_lossy(&stderr_output); 188 let stderr_str = String::from_utf8_lossy(&stderr_output);
189
190 // Check if this is a git protocol error (exit code 128 with stderr)
191 // Protocol errors should be returned as HTTP 200 with ERR pkt-line
192 if is_git_protocol_error(status.code(), &stderr_output) {
193 warn!(
194 "Git upload-pack protocol error (returning ERR pkt-line): {}",
195 stderr_str
196 );
197 return Ok(build_git_protocol_error_response(
198 GitService::UploadPack,
199 &stderr_str,
200 ));
201 }
202
203 // Transport errors (spawn failures, signals, etc.) remain as HTTP 500
153 error!("Git upload-pack failed: {}", stderr_str); 204 error!("Git upload-pack failed: {}", stderr_str);
154 return Err(GitError::GitFailed(status.code())); 205 return Err(GitError::GitFailed(status.code()));
155 } 206 }
@@ -277,6 +328,21 @@ pub async fn handle_receive_pack(
277 328
278 if !status.success() { 329 if !status.success() {
279 let stderr_str = String::from_utf8_lossy(&stderr_output); 330 let stderr_str = String::from_utf8_lossy(&stderr_output);
331
332 // Check if this is a git protocol error (exit code 128 with stderr)
333 // Protocol errors should be returned as HTTP 200 with ERR pkt-line
334 if is_git_protocol_error(status.code(), &stderr_output) {
335 warn!(
336 "Git receive-pack protocol error (returning ERR pkt-line): {}",
337 stderr_str
338 );
339 return Ok(build_git_protocol_error_response(
340 GitService::ReceivePack,
341 &stderr_str,
342 ));
343 }
344
345 // Transport errors (spawn failures, signals, etc.) remain as HTTP 500
280 error!("Git receive-pack failed: {}", stderr_str); 346 error!("Git receive-pack failed: {}", stderr_str);
281 return Err(GitError::GitFailed(status.code())); 347 return Err(GitError::GitFailed(status.code()));
282 } 348 }