upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/nostr/policy/pr_event.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-07 23:31:38 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-07 23:31:38 +0000
commitc67ebe6f33bfa191f17eb0df24d3ee18092c74e1 (patch)
treeb86911bbb406f4aa0253b1cf1e0a82aed16c972b /src/nostr/policy/pr_event.rs
parent4dc0ed66a0bd3b4b00804bb13adf93b207bb5fc4 (diff)
refactor: unify event processing logic
Eliminates code duplication by extracting core event processing into reusable functions. All state and PR event processing now uses the same unified logic from src/git/process.rs. Changes: - Add src/git/process.rs with unified processing functions - process_state_with_git_data() for state events - process_pr_with_git_data() for PR events - Pure functions with comprehensive result types - Refactor policy handlers to use unified processing - src/nostr/policy/state.rs: Remove ~70 lines of duplicated logic - src/nostr/policy/pr_event.rs: Remove ~40 lines of duplicated logic - Refactor purgatory processing to use unified functions - src/git/sync.rs: Remove ~125 lines of duplicated logic - Make extract_owner_from_repo_path() public for reuse Benefits: - DRY: Single source of truth for event processing - Testable: Pure functions with clear contracts - Maintainable: Changes happen in one place - Consistent: All code paths use same logic All 217 unit tests + 40 integration tests pass (257/257).
Diffstat (limited to 'src/nostr/policy/pr_event.rs')
-rw-r--r--src/nostr/policy/pr_event.rs132
1 files changed, 42 insertions, 90 deletions
diff --git a/src/nostr/policy/pr_event.rs b/src/nostr/policy/pr_event.rs
index ff3bade..9942a6a 100644
--- a/src/nostr/policy/pr_event.rs
+++ b/src/nostr/policy/pr_event.rs
@@ -27,7 +27,7 @@ impl PrEventPolicy {
27 /// 2. Commit existence in referenced repositories 27 /// 2. Commit existence in referenced repositories
28 /// 3. Deletion of incorrect refs/nostr/<event-id> refs 28 /// 3. Deletion of incorrect refs/nostr/<event-id> refs
29 /// 4. Deletion of incorrect placeholders 29 /// 4. Deletion of incorrect placeholders
30 /// 5. Copying git data to all referenced repositories when found 30 /// 5. Processing PR event with unified function
31 /// 31 ///
32 /// # Returns 32 /// # Returns
33 /// - `Ok(true)` if git data ready (commit exists and is synced to all repos) 33 /// - `Ok(true)` if git data ready (commit exists and is synced to all repos)
@@ -64,7 +64,6 @@ impl PrEventPolicy {
64 ); 64 );
65 // Remove placeholder - event processing will continue normally 65 // Remove placeholder - event processing will continue normally
66 self.ctx.purgatory.remove_pr(&event_id); 66 self.ctx.purgatory.remove_pr(&event_id);
67 // Continue to validate and sync refs across all repos
68 } else { 67 } else {
69 // Placeholder has different commit - incoming event supersedes 68 // Placeholder has different commit - incoming event supersedes
70 tracing::info!( 69 tracing::info!(
@@ -75,8 +74,7 @@ impl PrEventPolicy {
75 ); 74 );
76 // Remove incorrect placeholder 75 // Remove incorrect placeholder
77 self.ctx.purgatory.remove_pr(&event_id); 76 self.ctx.purgatory.remove_pr(&event_id);
78 // Delete incorrect git data (refs/nostr/<event-id>) from all repos 77 // Delete incorrect git data (refs/nostr/<event-id>) will be handled below
79 // This will be handled below when we validate refs
80 } 78 }
81 } 79 }
82 80
@@ -87,9 +85,8 @@ impl PrEventPolicy {
87 return Ok(false); 85 return Ok(false);
88 } 86 }
89 87
90 // delete incorrect refs/nostr/<event-id> 88 // Delete incorrect refs/nostr/<event-id>
91 for repo_path in &repo_paths { 89 for repo_path in &repo_paths {
92 // First, validate/delete any incorrect refs/nostr/<event-id>
93 match git::validate_nostr_ref(repo_path, &event_id, &commit) { 90 match git::validate_nostr_ref(repo_path, &event_id, &commit) {
94 Ok(true) => { 91 Ok(true) => {
95 tracing::info!( 92 tracing::info!(
@@ -110,10 +107,9 @@ impl PrEventPolicy {
110 } 107 }
111 } 108 }
112 109
113 // find location of correct git data (if exists) 110 // Find location of correct git data (if exists)
114 let mut source_repo: Option<std::path::PathBuf> = None; 111 let mut source_repo: Option<std::path::PathBuf> = None;
115 for repo_path in &repo_paths { 112 for repo_path in &repo_paths {
116 // Check if commit exists in this repository
117 if git::commit_exists(repo_path, &commit) { 113 if git::commit_exists(repo_path, &commit) {
118 source_repo = Some(repo_path.clone()); 114 source_repo = Some(repo_path.clone());
119 tracing::debug!( 115 tracing::debug!(
@@ -125,59 +121,50 @@ impl PrEventPolicy {
125 } 121 }
126 } 122 }
127 123
128 // Copy commit to all other referenced repositories
129 if let Some(source_repo) = source_repo { 124 if let Some(source_repo) = source_repo {
130 for repo_path in &repo_paths { 125 // Extract identifier
131 if repo_path == &source_repo { 126 let identifier = crate::git::sync::extract_identifier_from_pr_event(event)
132 // Skip source repo 127 .ok_or_else(|| anyhow::anyhow!("No identifier in PR event"))?;
133 continue; 128
134 } 129 // Fetch repository data
130 let db_repo_data = fetch_repository_data(&self.ctx.database, &identifier).await?;
131
132 // Extract owner pubkey from source repo path
133 let owner_pubkey = crate::git::sync::extract_owner_from_repo_path(
134 &source_repo,
135 &self.ctx.git_data_path,
136 )
137 .unwrap_or_default();
138
139 // Use unified processing function
140 let result = crate::git::process::process_pr_with_git_data(
141 event,
142 &commit,
143 &source_repo,
144 &db_repo_data,
145 &self.ctx.git_data_path,
146 &owner_pubkey,
147 );
135 148
136 // Check if repository exists 149 tracing::info!(
137 if !repo_path.exists() { 150 identifier = %identifier,
138 tracing::debug!( 151 event_id = %event_id,
139 "Repository {} does not exist, skipping sync", 152 repos_synced = result.repos_synced,
140 repo_path.display() 153 refs_created = result.refs_created,
141 ); 154 "Processed PR event with git data already available"
142 continue; 155 );
143 }
144 156
145 // Check if commit already exists 157 if !result.errors.is_empty() {
146 if git::commit_exists(repo_path, &commit) { 158 for error in &result.errors {
147 tracing::debug!( 159 tracing::warn!(
148 "Commit {} already exists in {}, skipping sync", 160 identifier = %identifier,
149 commit, 161 event_id = %event_id,
150 repo_path.display() 162 error = %error,
163 "Error processing PR event"
151 ); 164 );
152 continue;
153 }
154
155 // Fetch commit from source repo to target repo
156 tracing::info!(
157 "Syncing commit {} from {} to {}",
158 commit,
159 source_repo.display(),
160 repo_path.display()
161 );
162
163 match self.copy_commit(&source_repo, repo_path, &commit).await {
164 Ok(()) => {
165 tracing::info!(
166 "Successfully synced commit {} to {}",
167 commit,
168 repo_path.display()
169 );
170 }
171 Err(e) => {
172 tracing::warn!(
173 "Failed to sync commit {} to {}: {}",
174 commit,
175 repo_path.display(),
176 e
177 );
178 }
179 } 165 }
180 } 166 }
167
181 Ok(true) 168 Ok(true)
182 } else { 169 } else {
183 tracing::debug!( 170 tracing::debug!(
@@ -250,40 +237,5 @@ impl PrEventPolicy {
250 237
251 Ok(repo_paths) 238 Ok(repo_paths)
252 } 239 }
253 /// Copy a commit from source repository to target repository
254 ///
255 /// Uses `git fetch` to copy a specific commit between local repositories.
256 ///
257 /// # Arguments
258 /// * `source_repo` - Path to repository containing the commit
259 /// * `target_repo` - Path to repository to receive the commit
260 /// * `commit` - Commit hash to copy
261 ///
262 /// # Returns
263 /// Ok(()) on success, Err with error message on failure
264 async fn copy_commit(
265 &self,
266 source_repo: &std::path::Path,
267 target_repo: &std::path::Path,
268 commit: &str,
269 ) -> Result<(), String> {
270 use std::process::Command;
271
272 let output = Command::new("git")
273 .args([
274 "fetch",
275 source_repo.to_str().ok_or("Invalid source path")?,
276 commit,
277 ])
278 .current_dir(target_repo)
279 .output()
280 .map_err(|e| format!("Failed to execute git fetch: {}", e))?;
281 240
282 if !output.status.success() {
283 let stderr = String::from_utf8_lossy(&output.stderr);
284 return Err(format!("git fetch failed: {}", stderr));
285 }
286
287 Ok(())
288 }
289} 241}