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-01-08 00:50:54 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-08 00:50:54 +0000
commitf75e1c59aacf5ce668fd327e4e3d827511661c2a (patch)
tree867926c7503e7c587e86c67896a9e7347600447b /src/git
parent3f14f998d64b5fa15bdddd7570b4f72874eb9f29 (diff)
chore: cargo fmt
Diffstat (limited to 'src/git')
-rw-r--r--src/git/authorization.rs4
-rw-r--r--src/git/process.rs66
-rw-r--r--src/git/sync.rs40
3 files changed, 61 insertions, 49 deletions
diff --git a/src/git/authorization.rs b/src/git/authorization.rs
index fbddb98..7502a52 100644
--- a/src/git/authorization.rs
+++ b/src/git/authorization.rs
@@ -134,11 +134,11 @@ pub async fn authorize_push(
134 e 134 e
135 ))); 135 )));
136 } 136 }
137 137
138 // Create placeholder for git-data-first scenario 138 // Create placeholder for git-data-first scenario
139 // This allows cleanup if the PR event never arrives 139 // This allows cleanup if the PR event never arrives
140 purgatory.add_pr_placeholder(event_id_hex.to_string(), new_oid.clone()); 140 purgatory.add_pr_placeholder(event_id_hex.to_string(), new_oid.clone());
141 141
142 debug!( 142 debug!(
143 "Created placeholder for {} - awaiting PR event (will expire in 30min if event doesn't arrive)", 143 "Created placeholder for {} - awaiting PR event (will expire in 30min if event doesn't arrive)",
144 event_id_hex 144 event_id_hex
diff --git a/src/git/process.rs b/src/git/process.rs
index d052c04..215b423 100644
--- a/src/git/process.rs
+++ b/src/git/process.rs
@@ -6,12 +6,15 @@
6//! - When events are released from purgatory (purgatory sync) 6//! - When events are released from purgatory (purgatory sync)
7//! - When git pushes trigger purgatory releases (receive-pack handler) 7//! - When git pushes trigger purgatory releases (receive-pack handler)
8 8
9use std::path::Path;
10use nostr_sdk::Event;
11use crate::git::authorization::{collect_authorized_maintainers, RepositoryData};
12use crate::git::sync::{align_repository_with_state, sync_pr_refs_to_tagged_owner_repos, copy_missing_oids_between_repos};
13use crate::git; 9use crate::git;
10use crate::git::authorization::{collect_authorized_maintainers, RepositoryData};
11use crate::git::sync::{
12 align_repository_with_state, copy_missing_oids_between_repos,
13 sync_pr_refs_to_tagged_owner_repos,
14};
14use crate::nostr::events::RepositoryState; 15use crate::nostr::events::RepositoryState;
16use nostr_sdk::Event;
17use std::path::Path;
15 18
16/// Result of processing a state event with git data 19/// Result of processing a state event with git data
17#[derive(Debug, Default, Clone)] 20#[derive(Debug, Default, Clone)]
@@ -68,19 +71,19 @@ pub fn process_state_with_git_data(
68 git_data_path: &Path, 71 git_data_path: &Path,
69) -> ProcessStateResult { 72) -> ProcessStateResult {
70 let mut result = ProcessStateResult::default(); 73 let mut result = ProcessStateResult::default();
71 74
72 let state_author = state.event.pubkey.to_hex(); 75 let state_author = state.event.pubkey.to_hex();
73 76
74 // Collect authorized maintainers per owner 77 // Collect authorized maintainers per owner
75 let by_owner = collect_authorized_maintainers(&db_repo_data.announcements); 78 let by_owner = collect_authorized_maintainers(&db_repo_data.announcements);
76 79
77 // Step 1: Identify owner repos that the state event author is maintainer for 80 // Step 1: Identify owner repos that the state event author is maintainer for
78 let authorized_owners: Vec<&String> = by_owner 81 let authorized_owners: Vec<&String> = by_owner
79 .iter() 82 .iter()
80 .filter(|(_, maintainers)| maintainers.contains(&state_author)) 83 .filter(|(_, maintainers)| maintainers.contains(&state_author))
81 .map(|(owner, _)| owner) 84 .map(|(owner, _)| owner)
82 .collect(); 85 .collect();
83 86
84 if authorized_owners.is_empty() { 87 if authorized_owners.is_empty() {
85 tracing::debug!( 88 tracing::debug!(
86 identifier = %state.identifier, 89 identifier = %state.identifier,
@@ -89,18 +92,18 @@ pub fn process_state_with_git_data(
89 ); 92 );
90 return result; 93 return result;
91 } 94 }
92 95
93 // Process each owner repo that authorizes this state event author 96 // Process each owner repo that authorizes this state event author
94 for owner in &authorized_owners { 97 for owner in &authorized_owners {
95 let maintainers = by_owner.get(*owner).unwrap(); 98 let maintainers = by_owner.get(*owner).unwrap();
96 99
97 // Step 2: Check if this state event is the latest authorized for this owner 100 // Step 2: Check if this state event is the latest authorized for this owner
98 let is_latest = crate::git::sync::is_latest_authorized_state_public( 101 let is_latest = crate::git::sync::is_latest_authorized_state_public(
99 state, 102 state,
100 maintainers, 103 maintainers,
101 &db_repo_data.states, 104 &db_repo_data.states,
102 ); 105 );
103 106
104 if !is_latest { 107 if !is_latest {
105 tracing::debug!( 108 tracing::debug!(
106 identifier = %state.identifier, 109 identifier = %state.identifier,
@@ -109,7 +112,7 @@ pub fn process_state_with_git_data(
109 ); 112 );
110 continue; 113 continue;
111 } 114 }
112 115
113 // Find the announcement for this owner 116 // Find the announcement for this owner
114 let Some(announcement) = db_repo_data 117 let Some(announcement) = db_repo_data
115 .announcements 118 .announcements
@@ -118,9 +121,9 @@ pub fn process_state_with_git_data(
118 else { 121 else {
119 continue; 122 continue;
120 }; 123 };
121 124
122 let target_repo_path = git_data_path.join(announcement.repo_path()); 125 let target_repo_path = git_data_path.join(announcement.repo_path());
123 126
124 // Step 3: Check git repo exists for that owner 127 // Step 3: Check git repo exists for that owner
125 if !target_repo_path.exists() { 128 if !target_repo_path.exists() {
126 tracing::debug!( 129 tracing::debug!(
@@ -131,14 +134,12 @@ pub fn process_state_with_git_data(
131 ); 134 );
132 continue; 135 continue;
133 } 136 }
134 137
135 // Step 4: Copy all required OIDs to that repo (unless it's source_repo_path) 138 // Step 4: Copy all required OIDs to that repo (unless it's source_repo_path)
136 if target_repo_path != source_repo_path { 139 if target_repo_path != source_repo_path {
137 if let Err(e) = copy_missing_oids_between_repos( 140 if let Err(e) =
138 source_repo_path, 141 copy_missing_oids_between_repos(source_repo_path, &target_repo_path, state)
139 &target_repo_path, 142 {
140 state,
141 ) {
142 tracing::warn!( 143 tracing::warn!(
143 identifier = %state.identifier, 144 identifier = %state.identifier,
144 source = %source_repo_path.display(), 145 source = %source_repo_path.display(),
@@ -150,14 +151,14 @@ pub fn process_state_with_git_data(
150 continue; // Skip this owner repo 151 continue; // Skip this owner repo
151 } 152 }
152 } 153 }
153 154
154 // Step 5: Reset the git state in that repo to match the state event 155 // Step 5: Reset the git state in that repo to match the state event
155 let align_result = align_repository_with_state(&target_repo_path, state); 156 let align_result = align_repository_with_state(&target_repo_path, state);
156 result.repos_synced += 1; 157 result.repos_synced += 1;
157 result.refs_created += align_result.refs_created; 158 result.refs_created += align_result.refs_created;
158 result.refs_updated += align_result.refs_updated; 159 result.refs_updated += align_result.refs_updated;
159 result.refs_deleted += align_result.refs_deleted; 160 result.refs_deleted += align_result.refs_deleted;
160 161
161 tracing::info!( 162 tracing::info!(
162 identifier = %state.identifier, 163 identifier = %state.identifier,
163 owner = %owner, 164 owner = %owner,
@@ -169,7 +170,7 @@ pub fn process_state_with_git_data(
169 "Aligned repository with state" 170 "Aligned repository with state"
170 ); 171 );
171 } 172 }
172 173
173 result 174 result
174} 175}
175 176
@@ -205,13 +206,13 @@ pub fn process_pr_with_git_data(
205 source_owner_pubkey: &str, 206 source_owner_pubkey: &str,
206) -> ProcessPrResult { 207) -> ProcessPrResult {
207 let mut result = ProcessPrResult::default(); 208 let mut result = ProcessPrResult::default();
208 209
209 let event_id = event.id.to_hex(); 210 let event_id = event.id.to_hex();
210 211
211 // Sync PR ref to owner repos using tagged maintainer logic 212 // Sync PR ref to owner repos using tagged maintainer logic
212 let pr_refs = vec![(event_id.clone(), commit.to_string())]; 213 let pr_refs = vec![(event_id.clone(), commit.to_string())];
213 let pr_events = vec![event.clone()]; 214 let pr_events = vec![event.clone()];
214 215
215 let sync_result = sync_pr_refs_to_tagged_owner_repos( 216 let sync_result = sync_pr_refs_to_tagged_owner_repos(
216 source_repo_path, 217 source_repo_path,
217 &pr_refs, 218 &pr_refs,
@@ -222,13 +223,10 @@ pub fn process_pr_with_git_data(
222 ); 223 );
223 result.repos_synced += sync_result.repos_synced; 224 result.repos_synced += sync_result.repos_synced;
224 result.refs_created += sync_result.refs_created; 225 result.refs_created += sync_result.refs_created;
225 result.errors.extend( 226 result
226 sync_result 227 .errors
227 .errors 228 .extend(sync_result.errors.into_iter().map(|(_, e)| e));
228 .into_iter() 229
229 .map(|(_, e)| e),
230 );
231
232 // Create the ref in the source repo if it doesn't exist 230 // Create the ref in the source repo if it doesn't exist
233 let ref_name = format!("refs/nostr/{}", event_id); 231 let ref_name = format!("refs/nostr/{}", event_id);
234 if git::get_ref_commit(source_repo_path, &ref_name).is_none() { 232 if git::get_ref_commit(source_repo_path, &ref_name).is_none() {
@@ -250,6 +248,6 @@ pub fn process_pr_with_git_data(
250 ); 248 );
251 } 249 }
252 } 250 }
253 251
254 result 252 result
255} 253}
diff --git a/src/git/sync.rs b/src/git/sync.rs
index 5e2d3f2..06013a5 100644
--- a/src/git/sync.rs
+++ b/src/git/sync.rs
@@ -837,13 +837,27 @@ pub async fn process_newly_available_git_data(
837 ); 837 );
838 838
839 // Process state events from purgatory 839 // Process state events from purgatory
840 let state_result = 840 let state_result = process_purgatory_state_events(
841 process_purgatory_state_events(&identifier, source_repo_path, database, local_relay, purgatory, git_data_path).await; 841 &identifier,
842 source_repo_path,
843 database,
844 local_relay,
845 purgatory,
846 git_data_path,
847 )
848 .await;
842 result.merge(state_result); 849 result.merge(state_result);
843 850
844 // Process PR events from purgatory 851 // Process PR events from purgatory
845 let pr_result = 852 let pr_result = process_purgatory_pr_events(
846 process_purgatory_pr_events(&identifier, source_repo_path, database, local_relay, purgatory, git_data_path).await; 853 &identifier,
854 source_repo_path,
855 database,
856 local_relay,
857 purgatory,
858 git_data_path,
859 )
860 .await;
847 result.merge(pr_result); 861 result.merge(pr_result);
848 862
849 if result.released_any() { 863 if result.released_any() {
@@ -1113,7 +1127,9 @@ async fn process_purgatory_pr_events(
1113 error = %e, 1127 error = %e,
1114 "Failed to fetch repository data for PR events" 1128 "Failed to fetch repository data for PR events"
1115 ); 1129 );
1116 result.errors.push(format!("Failed to fetch repo data: {}", e)); 1130 result
1131 .errors
1132 .push(format!("Failed to fetch repo data: {}", e));
1117 return result; 1133 return result;
1118 } 1134 }
1119 }; 1135 };
@@ -1137,8 +1153,8 @@ async fn process_purgatory_pr_events(
1137 } 1153 }
1138 1154
1139 // Extract owner pubkey 1155 // Extract owner pubkey
1140 let owner_pubkey = extract_owner_from_repo_path(source_repo_path, git_data_path) 1156 let owner_pubkey =
1141 .unwrap_or_default(); 1157 extract_owner_from_repo_path(source_repo_path, git_data_path).unwrap_or_default();
1142 1158
1143 // Use unified processing function 1159 // Use unified processing function
1144 let process_result = crate::git::process::process_pr_with_git_data( 1160 let process_result = crate::git::process::process_pr_with_git_data(
@@ -1192,7 +1208,9 @@ async fn process_purgatory_pr_events(
1192 error = %e, 1208 error = %e,
1193 "Failed to save PR event to database" 1209 "Failed to save PR event to database"
1194 ); 1210 );
1195 result.errors.push(format!("Failed to save PR event: {}", e)); 1211 result
1212 .errors
1213 .push(format!("Failed to save PR event: {}", e));
1196 } 1214 }
1197 } 1215 }
1198 } 1216 }
@@ -1527,11 +1545,7 @@ mod tests {
1527 } 1545 }
1528 1546
1529 // Helper function to create a test state event with specific timestamp 1547 // Helper function to create a test state event with specific timestamp
1530 fn create_test_state_event( 1548 fn create_test_state_event(keys: &Keys, identifier: &str, created_at: u64) -> RepositoryState {
1531 keys: &Keys,
1532 identifier: &str,
1533 created_at: u64,
1534 ) -> RepositoryState {
1535 create_test_state_event_with_nonce(keys, identifier, created_at, "") 1549 create_test_state_event_with_nonce(keys, identifier, created_at, "")
1536 } 1550 }
1537 1551