upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-05-31 15:34:21 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2025-05-31 19:50:06 +0100
commit5f45edbebe310decb06f955d95665a6ad387c6cb (patch)
treed6da1d3148e55aa75fc28dca22ad70aa2a5fd224
parent6f74dd518fbb74dfd2abbe2e1c5bb5df7a7d0562 (diff)
feat(push): prevent push if no ann event
To ensure additional maintainers publish an annoucement event, require it for them to push
-rw-r--r--src/bin/git_remote_nostr/push.rs14
-rw-r--r--src/bin/ngit/sub_commands/init.rs1
-rw-r--r--src/lib/client.rs6
-rw-r--r--src/lib/repo_ref.rs9
-rw-r--r--tests/git_remote_nostr/push.rs8
5 files changed, 38 insertions, 0 deletions
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index c4953f8..56bf177 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -199,6 +199,20 @@ async fn create_and_publish_events(
199 if proposal_refspecs.is_empty() { 199 if proposal_refspecs.is_empty() {
200 return Ok((vec![], true)); 200 return Ok((vec![], true));
201 } 201 }
202 } else if repo_ref
203 .maintainers_without_annoucnement
204 .clone()
205 .is_some_and(|ms| ms.contains(&user_ref.public_key))
206 {
207 for refspec in git_server_refspecs {
208 let (_, to) = refspec_to_from_to(refspec).unwrap();
209 eprintln!(
210 "error {to} you must run `ngit init` before pushing updates. you've been offered maintainership but you must accept it before pushing",
211 );
212 }
213 if proposal_refspecs.is_empty() {
214 return Ok((vec![], true));
215 }
202 } 216 }
203 217
204 let mut events = vec![]; 218 let mut events = vec![];
diff --git a/src/bin/ngit/sub_commands/init.rs b/src/bin/ngit/sub_commands/init.rs
index 1d9fda0..aea4f8b 100644
--- a/src/bin/ngit/sub_commands/init.rs
+++ b/src/bin/ngit/sub_commands/init.rs
@@ -703,6 +703,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
703 relays: relays.clone(), 703 relays: relays.clone(),
704 blossoms, 704 blossoms,
705 trusted_maintainer: user_ref.public_key, 705 trusted_maintainer: user_ref.public_key,
706 maintainers_without_annoucnement: None,
706 maintainers: maintainers.clone(), 707 maintainers: maintainers.clone(),
707 events: HashMap::new(), 708 events: HashMap::new(),
708 nostr_git_url: None, 709 nostr_git_url: None,
diff --git a/src/lib/client.rs b/src/lib/client.rs
index bfa7b33..3b613b6 100644
--- a/src/lib/client.rs
+++ b/src/lib/client.rs
@@ -985,6 +985,9 @@ pub async fn get_repo_ref_from_cache(
985 .collect(); 985 .collect();
986 let mut seen_blossoms: HashSet<Url> = HashSet::from_iter(blossoms.iter().cloned()); 986 let mut seen_blossoms: HashSet<Url> = HashSet::from_iter(blossoms.iter().cloned());
987 987
988 // also set maintainers_without_annoucnement
989 let mut maintainers_without_annoucnement: Vec<PublicKey> = vec![];
990
988 for m in &maintainers { 991 for m in &maintainers {
989 if let Some(event) = repo_events.iter().find(|e| e.pubkey == *m) { 992 if let Some(event) = repo_events.iter().find(|e| e.pubkey == *m) {
990 if let Ok(m_repo_ref) = RepoRef::try_from((event.clone(), None)) { 993 if let Ok(m_repo_ref) = RepoRef::try_from((event.clone(), None)) {
@@ -1004,6 +1007,8 @@ pub async fn get_repo_ref_from_cache(
1004 } 1007 }
1005 } 1008 }
1006 } 1009 }
1010 } else {
1011 maintainers_without_annoucnement.push(*m);
1007 } 1012 }
1008 } 1013 }
1009 1014
@@ -1014,6 +1019,7 @@ pub async fn get_repo_ref_from_cache(
1014 relays, 1019 relays,
1015 git_server, 1020 git_server,
1016 events, 1021 events,
1022 maintainers_without_annoucnement: Some(maintainers_without_annoucnement),
1017 ..repo_ref 1023 ..repo_ref
1018 }) 1024 })
1019} 1025}
diff --git a/src/lib/repo_ref.rs b/src/lib/repo_ref.rs
index bf52cda..78968b4 100644
--- a/src/lib/repo_ref.rs
+++ b/src/lib/repo_ref.rs
@@ -42,6 +42,8 @@ pub struct RepoRef {
42 pub blossoms: Vec<Url>, 42 pub blossoms: Vec<Url>,
43 pub maintainers: Vec<PublicKey>, 43 pub maintainers: Vec<PublicKey>,
44 pub trusted_maintainer: PublicKey, 44 pub trusted_maintainer: PublicKey,
45 // set to None if not known
46 pub maintainers_without_annoucnement: Option<Vec<PublicKey>>,
45 pub events: HashMap<Nip19Coordinate, nostr::Event>, 47 pub events: HashMap<Nip19Coordinate, nostr::Event>,
46 pub nostr_git_url: Option<NostrUrlDecoded>, 48 pub nostr_git_url: Option<NostrUrlDecoded>,
47} 49}
@@ -49,6 +51,11 @@ pub struct RepoRef {
49impl TryFrom<(nostr::Event, Option<PublicKey>)> for RepoRef { 51impl TryFrom<(nostr::Event, Option<PublicKey>)> for RepoRef {
50 type Error = anyhow::Error; 52 type Error = anyhow::Error;
51 53
54 /*
55 * this could do with a refactor to intergrate enhancements made by
56 * `get_repo_ref_from_cache`. Other than tests, its only used there and the
57 * changes made by that function are important.
58 */
52 fn try_from((event, trusted_maintainer): (nostr::Event, Option<PublicKey>)) -> Result<Self> { 59 fn try_from((event, trusted_maintainer): (nostr::Event, Option<PublicKey>)) -> Result<Self> {
53 // TODO: turn trusted maintainer into NostrUrlDecoded 60 // TODO: turn trusted maintainer into NostrUrlDecoded
54 if !event.kind.eq(&Kind::GitRepoAnnouncement) { 61 if !event.kind.eq(&Kind::GitRepoAnnouncement) {
@@ -66,6 +73,7 @@ impl TryFrom<(nostr::Event, Option<PublicKey>)> for RepoRef {
66 blossoms: Vec::new(), 73 blossoms: Vec::new(),
67 maintainers: Vec::new(), 74 maintainers: Vec::new(),
68 trusted_maintainer: trusted_maintainer.unwrap_or(event.pubkey), 75 trusted_maintainer: trusted_maintainer.unwrap_or(event.pubkey),
76 maintainers_without_annoucnement: None,
69 events: HashMap::new(), 77 events: HashMap::new(),
70 nostr_git_url: None, 78 nostr_git_url: None,
71 }; 79 };
@@ -740,6 +748,7 @@ mod tests {
740 ], 748 ],
741 blossoms: vec![], 749 blossoms: vec![],
742 trusted_maintainer: TEST_KEY_1_KEYS.public_key(), 750 trusted_maintainer: TEST_KEY_1_KEYS.public_key(),
751 maintainers_without_annoucnement: None,
743 maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], 752 maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()],
744 events: HashMap::new(), 753 events: HashMap::new(),
745 nostr_git_url: None, 754 nostr_git_url: None,
diff --git a/tests/git_remote_nostr/push.rs b/tests/git_remote_nostr/push.rs
index d041a89..eab2422 100644
--- a/tests/git_remote_nostr/push.rs
+++ b/tests/git_remote_nostr/push.rs
@@ -1833,3 +1833,11 @@ async fn push_new_pr_branch_creates_proposal() -> Result<()> {
1833 1833
1834 Ok(()) 1834 Ok(())
1835} 1835}
1836
1837mod push_from_another_maintainer {
1838 // TODO that has issued announcement
1839 // - that is listed by trusted maintainer - succeeds
1840 // - that isn't listed by trusted maintainer - fails
1841 // TODO that hasn't yet issued announcement
1842 // - that is listed by trusted maintainer - fails
1843}