upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/git/handlers.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-11-28 09:19:06 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-11-28 09:19:06 +0000
commit4da51a8adb94f2979c0a911157f26596c1ee2cb5 (patch)
tree72c7e2d7347ae39fb6e7db06771a01beeddc37d3 /src/git/handlers.rs
parente41126732fb75ec66a979c09544076ba92373680 (diff)
sync HEAD on state event and git data push
Diffstat (limited to 'src/git/handlers.rs')
-rw-r--r--src/git/handlers.rs47
1 files changed, 45 insertions, 2 deletions
diff --git a/src/git/handlers.rs b/src/git/handlers.rs
index 27bec76..73f72f3 100644
--- a/src/git/handlers.rs
+++ b/src/git/handlers.rs
@@ -13,6 +13,9 @@ use super::authorization::{
13}; 13};
14use super::protocol::{GitService, PktLine}; 14use super::protocol::{GitService, PktLine};
15use super::subprocess::GitSubprocess; 15use super::subprocess::GitSubprocess;
16use super::{try_set_head_if_available};
17
18use crate::nostr::events::RepositoryState;
16 19
17/// Handle GET /info/refs?service=git-{upload,receive}-pack 20/// Handle GET /info/refs?service=git-{upload,receive}-pack
18/// 21///
@@ -163,6 +166,9 @@ pub struct PushAuthParams {
163/// This includes GRASP authorization validation according to GRASP-01: 166/// This includes GRASP authorization validation according to GRASP-01:
164/// "MUST accept pushes via this service that match the latest repo state announcement 167/// "MUST accept pushes via this service that match the latest repo state announcement
165/// on the relay, respecting the recursive maintainer set." 168/// on the relay, respecting the recursive maintainer set."
169///
170/// Also per GRASP-01: "MUST set repository HEAD per repository state announcement
171/// as soon as the git data related to that branch has been received."
166pub async fn handle_receive_pack( 172pub async fn handle_receive_pack(
167 repo_path: PathBuf, 173 repo_path: PathBuf,
168 request_body: Bytes, 174 request_body: Bytes,
@@ -174,14 +180,17 @@ pub async fn handle_receive_pack(
174 return Err(GitError::RepositoryNotFound); 180 return Err(GitError::RepositoryNotFound);
175 } 181 }
176 182
183 // Keep track of state for HEAD setting after push
184 let mut authorized_state: Option<RepositoryState> = None;
185
177 // GRASP Authorization Check 186 // GRASP Authorization Check
178 if let Some(params) = auth_params { 187 if let Some(ref params) = auth_params {
179 info!( 188 info!(
180 "Authorizing push for {}/{} via {}", 189 "Authorizing push for {}/{} via {}",
181 params.owner_npub, params.identifier, params.relay_url 190 params.owner_npub, params.identifier, params.relay_url
182 ); 191 );
183 192
184 match authorize_push(&params, &request_body).await { 193 match authorize_push(params, &request_body).await {
185 Ok(auth_result) => { 194 Ok(auth_result) => {
186 if !auth_result.authorized { 195 if !auth_result.authorized {
187 warn!( 196 warn!(
@@ -196,6 +205,8 @@ pub async fn handle_receive_pack(
196 params.identifier, 205 params.identifier,
197 auth_result.maintainers.len() 206 auth_result.maintainers.len()
198 ); 207 );
208 // Save the state for HEAD setting after push
209 authorized_state = auth_result.state;
199 } 210 }
200 Err(e) => { 211 Err(e) => {
201 warn!( 212 warn!(
@@ -246,6 +257,38 @@ pub async fn handle_receive_pack(
246 return Err(GitError::GitFailed(status.code())); 257 return Err(GitError::GitFailed(status.code()));
247 } 258 }
248 259
260 // GRASP-01: Set HEAD after git data is received
261 // "MUST set repository HEAD per repository state announcement
262 // as soon as the git data related to that branch has been received."
263 if let Some(state) = authorized_state {
264 if let Some(head_ref) = &state.head {
265 if let Some(branch_name) = state.get_head_branch() {
266 if let Some(commit) = state.get_branch_commit(branch_name) {
267 match try_set_head_if_available(&repo_path, head_ref, commit) {
268 Ok(true) => {
269 info!(
270 "Set HEAD to {} after push to {:?}",
271 head_ref, repo_path
272 );
273 }
274 Ok(false) => {
275 debug!(
276 "HEAD commit {} not found after push, HEAD not updated",
277 commit
278 );
279 }
280 Err(e) => {
281 warn!(
282 "Failed to set HEAD after push: {}",
283 e
284 );
285 }
286 }
287 }
288 }
289 }
290 }
291
249 Ok(Response::builder() 292 Ok(Response::builder()
250 .status(StatusCode::OK) 293 .status(StatusCode::OK)
251 .header("content-type", GitService::ReceivePack.result_content_type()) 294 .header("content-type", GitService::ReceivePack.result_content_type())