upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/git/authorization.rs6
-rw-r--r--src/git/sync.rs45
-rw-r--r--src/nostr/policy/pr_event.rs6
-rw-r--r--src/purgatory/sync/context.rs17
-rw-r--r--src/purgatory/sync/functions.rs6
5 files changed, 45 insertions, 35 deletions
diff --git a/src/git/authorization.rs b/src/git/authorization.rs
index 0e9a8ba..bf49800 100644
--- a/src/git/authorization.rs
+++ b/src/git/authorization.rs
@@ -234,7 +234,7 @@ pub struct RepositoryData {
234/// 234///
235/// This performs a single database query to fetch both announcement and state events, 235/// This performs a single database query to fetch both announcement and state events,
236/// which is more efficient than separate queries. 236/// which is more efficient than separate queries.
237pub async fn fetch_repository_data( 237pub async fn fetch_repository_data_excluding_purgatory(
238 database: &SharedDatabase, 238 database: &SharedDatabase,
239 identifier: &str, 239 identifier: &str,
240) -> Result<RepositoryData> { 240) -> Result<RepositoryData> {
@@ -298,7 +298,7 @@ pub async fn fetch_repository_data_with_purgatory(
298 identifier: &str, 298 identifier: &str,
299) -> Result<RepositoryData> { 299) -> Result<RepositoryData> {
300 // First, fetch from database 300 // First, fetch from database
301 let mut repo_data = fetch_repository_data(database, identifier).await?; 301 let mut repo_data = fetch_repository_data_excluding_purgatory(database, identifier).await?;
302 302
303 // Then, add announcements from purgatory 303 // Then, add announcements from purgatory
304 let purgatory_announcements = purgatory.get_announcements_by_identifier(identifier); 304 let purgatory_announcements = purgatory.get_announcements_by_identifier(identifier);
@@ -511,7 +511,7 @@ pub async fn get_authorization_from_db(
511 identifier: &str, 511 identifier: &str,
512) -> Result<AuthorizationResult> { 512) -> Result<AuthorizationResult> {
513 // Fetch all repository data with a single query 513 // Fetch all repository data with a single query
514 let repo_data = fetch_repository_data(database, identifier).await?; 514 let repo_data = fetch_repository_data_excluding_purgatory(database, identifier).await?;
515 515
516 if repo_data.announcements.is_empty() { 516 if repo_data.announcements.is_empty() {
517 return Ok(AuthorizationResult::denied( 517 return Ok(AuthorizationResult::denied(
diff --git a/src/git/sync.rs b/src/git/sync.rs
index 0d9a6b5..9a02ad4 100644
--- a/src/git/sync.rs
+++ b/src/git/sync.rs
@@ -38,8 +38,8 @@ use tracing::{debug, info, warn};
38use nostr_sdk::Event; 38use nostr_sdk::Event;
39 39
40use crate::git::authorization::{ 40use crate::git::authorization::{
41 collect_authorized_maintainers, fetch_repository_data, fetch_repository_data_with_purgatory, 41 collect_authorized_maintainers, fetch_repository_data_excluding_purgatory,
42 RepositoryData, 42 fetch_repository_data_with_purgatory, RepositoryData,
43}; 43};
44use crate::git::{self, oid_exists}; 44use crate::git::{self, oid_exists};
45use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase}; 45use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase};
@@ -933,20 +933,21 @@ async fn process_purgatory_state_events(
933 // IMPORTANT: Use fetch_repository_data_with_purgatory to include announcements 933 // IMPORTANT: Use fetch_repository_data_with_purgatory to include announcements
934 // that may still be in purgatory (not yet promoted). This ensures authorization 934 // that may still be in purgatory (not yet promoted). This ensures authorization
935 // works correctly even if the announcement promotion happens in the same batch. 935 // works correctly even if the announcement promotion happens in the same batch.
936 let mut db_repo_data = match fetch_repository_data_with_purgatory(database, purgatory, identifier).await { 936 let mut db_repo_data =
937 Ok(data) => data, 937 match fetch_repository_data_with_purgatory(database, purgatory, identifier).await {
938 Err(e) => { 938 Ok(data) => data,
939 warn!( 939 Err(e) => {
940 identifier = %identifier, 940 warn!(
941 error = %e, 941 identifier = %identifier,
942 "Failed to fetch repository data for purgatory state events" 942 error = %e,
943 ); 943 "Failed to fetch repository data for purgatory state events"
944 result 944 );
945 .errors 945 result
946 .push(format!("Failed to fetch repo data: {}", e)); 946 .errors
947 return result; 947 .push(format!("Failed to fetch repo data: {}", e));
948 } 948 return result;
949 }; 949 }
950 };
950 951
951 // Process each state event in chronological order 952 // Process each state event in chronological order
952 for entry in &purgatory_states { 953 for entry in &purgatory_states {
@@ -1231,7 +1232,7 @@ async fn process_purgatory_pr_events(
1231 // NOTE: Only fetch from database, NOT purgatory. PR events should only be 1232 // NOTE: Only fetch from database, NOT purgatory. PR events should only be
1232 // released from purgatory when the announcement has been promoted (validated). 1233 // released from purgatory when the announcement has been promoted (validated).
1233 // This ensures we don't accept PR events for announcements that fail validation. 1234 // This ensures we don't accept PR events for announcements that fail validation.
1234 let db_repo_data = match fetch_repository_data(database, identifier).await { 1235 let db_repo_data = match fetch_repository_data_excluding_purgatory(database, identifier).await {
1235 Ok(data) => data, 1236 Ok(data) => data,
1236 Err(e) => { 1237 Err(e) => {
1237 warn!( 1238 warn!(
@@ -1372,7 +1373,9 @@ async fn process_purgatory_announcements(
1372 error = %e, 1373 error = %e,
1373 "Failed to parse owner pubkey" 1374 "Failed to parse owner pubkey"
1374 ); 1375 );
1375 result.errors.push(format!("Failed to parse owner pubkey: {}", e)); 1376 result
1377 .errors
1378 .push(format!("Failed to parse owner pubkey: {}", e));
1376 return result; 1379 return result;
1377 } 1380 }
1378 }; 1381 };
@@ -1450,10 +1453,8 @@ async fn process_purgatory_announcements(
1450 } 1453 }
1451 1454
1452 // Re-process events from hot cache 1455 // Re-process events from hot cache
1453 let dummy_addr = SocketAddr::new( 1456 let dummy_addr =
1454 IpAddr::V4(Ipv4Addr::LOCALHOST), 1457 SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0);
1455 0,
1456 );
1457 for hot_event in hot_events { 1458 for hot_event in hot_events {
1458 info!( 1459 info!(
1459 event_id = %hot_event.id, 1460 event_id = %hot_event.id,
diff --git a/src/nostr/policy/pr_event.rs b/src/nostr/policy/pr_event.rs
index 072e445..52747a4 100644
--- a/src/nostr/policy/pr_event.rs
+++ b/src/nostr/policy/pr_event.rs
@@ -7,7 +7,7 @@ use nostr_relay_builder::prelude::Event;
7 7
8use super::PolicyContext; 8use super::PolicyContext;
9use crate::git; 9use crate::git;
10use crate::git::authorization::{collect_authorized_maintainers, fetch_repository_data}; 10use crate::git::authorization::{collect_authorized_maintainers, fetch_repository_data_excluding_purgatory};
11 11
12/// Policy for validating PR and PR Update events 12/// Policy for validating PR and PR Update events
13#[derive(Clone)] 13#[derive(Clone)]
@@ -131,7 +131,7 @@ impl PrEventPolicy {
131 // only be accepted for announcements that have been promoted (validated). 131 // only be accepted for announcements that have been promoted (validated).
132 // If the announcement is still in purgatory, the PR event should also go 132 // If the announcement is still in purgatory, the PR event should also go
133 // to purgatory and wait for the announcement to be promoted. 133 // to purgatory and wait for the announcement to be promoted.
134 let db_repo_data = fetch_repository_data(&self.ctx.database, &identifier).await?; 134 let db_repo_data = fetch_repository_data_excluding_purgatory(&self.ctx.database, &identifier).await?;
135 135
136 // Extract owner pubkey from source repo path 136 // Extract owner pubkey from source repo path
137 let owner_pubkey = crate::git::sync::extract_owner_from_repo_path( 137 let owner_pubkey = crate::git::sync::extract_owner_from_repo_path(
@@ -211,7 +211,7 @@ impl PrEventPolicy {
211 // only be accepted for announcements that have been promoted (validated). 211 // only be accepted for announcements that have been promoted (validated).
212 // If the announcement is still in purgatory, the PR event should also go 212 // If the announcement is still in purgatory, the PR event should also go
213 // to purgatory and wait for the announcement to be promoted. 213 // to purgatory and wait for the announcement to be promoted.
214 let db_repo_data = fetch_repository_data(&self.ctx.database, identifier).await?; 214 let db_repo_data = fetch_repository_data_excluding_purgatory(&self.ctx.database, identifier).await?;
215 215
216 // 3. Extract list of maintainers from "a 30617:<maintainer>:<identifier>" tags 216 // 3. Extract list of maintainers from "a 30617:<maintainer>:<identifier>" tags
217 let mut maintainer_pubkeys = std::collections::HashSet::new(); 217 let mut maintainer_pubkeys = std::collections::HashSet::new();
diff --git a/src/purgatory/sync/context.rs b/src/purgatory/sync/context.rs
index 8297515..1bba961 100644
--- a/src/purgatory/sync/context.rs
+++ b/src/purgatory/sync/context.rs
@@ -87,7 +87,10 @@ pub trait SyncContext: Send + Sync {
87 /// 87 ///
88 /// # Returns 88 /// # Returns
89 /// Repository data including announcements and state events 89 /// Repository data including announcements and state events
90 async fn fetch_repository_data(&self, identifier: &str) -> Result<RepositoryData>; 90 async fn fetch_repository_data_with_purgatory(
91 &self,
92 identifier: &str,
93 ) -> Result<RepositoryData>;
91 94
92 /// Get all OIDs needed for purgatory events with this identifier. 95 /// Get all OIDs needed for purgatory events with this identifier.
93 /// 96 ///
@@ -283,7 +286,10 @@ impl SyncContext for RealSyncContext {
283 urls 286 urls
284 } 287 }
285 288
286 async fn fetch_repository_data(&self, identifier: &str) -> Result<RepositoryData> { 289 async fn fetch_repository_data_with_purgatory(
290 &self,
291 identifier: &str,
292 ) -> Result<RepositoryData> {
287 // Use the purgatory-aware variant so that clone URLs from announcements still 293 // Use the purgatory-aware variant so that clone URLs from announcements still
288 // in purgatory (not yet promoted) are available. Without this, the sync loop 294 // in purgatory (not yet promoted) are available. Without this, the sync loop
289 // would find no URLs to fetch from and the announcement could never be promoted 295 // would find no URLs to fetch from and the announcement could never be promoted
@@ -585,7 +591,7 @@ pub mod mock {
585 /// assert_eq!(mock.fetch_log(), vec!["https://github.com/foo/bar.git"]); 591 /// assert_eq!(mock.fetch_log(), vec!["https://github.com/foo/bar.git"]);
586 /// ``` 592 /// ```
587 pub struct MockSyncContext { 593 pub struct MockSyncContext {
588 /// Repository data to return from fetch_repository_data 594 /// Repository data to return from fetch_repository_data_with_purgatory
589 repo_data: RwLock<Option<RepositoryData>>, 595 repo_data: RwLock<Option<RepositoryData>>,
590 596
591 /// Clone URLs available for the repository (from announcements) 597 /// Clone URLs available for the repository (from announcements)
@@ -732,7 +738,10 @@ pub mod mock {
732 self.pr_clone_urls.clone() 738 self.pr_clone_urls.clone()
733 } 739 }
734 740
735 async fn fetch_repository_data(&self, _identifier: &str) -> Result<RepositoryData> { 741 async fn fetch_repository_data_with_purgatory(
742 &self,
743 _identifier: &str,
744 ) -> Result<RepositoryData> {
736 // Return stored repo_data or create a minimal one with clone URLs 745 // Return stored repo_data or create a minimal one with clone URLs
737 if let Some(data) = self.repo_data.read().unwrap().as_ref() { 746 if let Some(data) = self.repo_data.read().unwrap().as_ref() {
738 // Clone the data - this is a test mock so efficiency isn't critical 747 // Clone the data - this is a test mock so efficiency isn't critical
diff --git a/src/purgatory/sync/functions.rs b/src/purgatory/sync/functions.rs
index 9207d58..bd5c0c0 100644
--- a/src/purgatory/sync/functions.rs
+++ b/src/purgatory/sync/functions.rs
@@ -104,7 +104,7 @@ pub async fn sync_identifier_next_url<C: SyncContext + ?Sized>(
104 } 104 }
105 105
106 // 3. Get repository data 106 // 3. Get repository data
107 let repo_data = match ctx.fetch_repository_data(identifier).await { 107 let repo_data = match ctx.fetch_repository_data_with_purgatory(identifier).await {
108 Ok(data) => data, 108 Ok(data) => data,
109 Err(e) => { 109 Err(e) => {
110 debug!( 110 debug!(
@@ -228,7 +228,7 @@ pub async fn get_throttled_domains_with_untried_urls<C: SyncContext + ?Sized>(
228 throttle_manager: &ThrottleManager, 228 throttle_manager: &ThrottleManager,
229 git_naughty_list: &NaughtyListTracker, 229 git_naughty_list: &NaughtyListTracker,
230) -> Vec<ThrottledDomainInfo> { 230) -> Vec<ThrottledDomainInfo> {
231 let repo_data = match ctx.fetch_repository_data(identifier).await { 231 let repo_data = match ctx.fetch_repository_data_with_purgatory(identifier).await {
232 Ok(data) => data, 232 Ok(data) => data,
233 Err(_) => return vec![], 233 Err(_) => return vec![],
234 }; 234 };
@@ -333,7 +333,7 @@ pub async fn sync_identifier_from_url<C: SyncContext + ?Sized>(
333 }; 333 };
334 334
335 // Get repository data for target repo path 335 // Get repository data for target repo path
336 let repo_data = match ctx.fetch_repository_data(identifier).await { 336 let repo_data = match ctx.fetch_repository_data_with_purgatory(identifier).await {
337 Ok(data) => data, 337 Ok(data) => data,
338 Err(e) => { 338 Err(e) => {
339 debug!( 339 debug!(