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>2024-02-14 16:44:56 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2024-02-14 16:44:56 +0000
commit115eca3d69310a58e8357fe091183d0a8e723967 (patch)
tree51860d62bdcde1d466d99134a41b767ac24eff52
parenta1d67c50c8ebc5395b069e30b60d66e0c7de5a5a (diff)
feat: find repo event by nevent or naddr
if repo event cannot be found using unique commit the user can find it via a nevent or naddr also handle no PRs found
-rw-r--r--src/repo_ref.rs65
-rw-r--r--src/sub_commands/list.rs5
-rw-r--r--tests/list.rs114
3 files changed, 169 insertions, 15 deletions
diff --git a/src/repo_ref.rs b/src/repo_ref.rs
index 87c5b75..38ea470 100644
--- a/src/repo_ref.rs
+++ b/src/repo_ref.rs
@@ -1,7 +1,7 @@
1use std::{fs::File, io::BufReader, str::FromStr}; 1use std::{fs::File, io::BufReader, str::FromStr};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use nostr::{secp256k1::XOnlyPublicKey, FromBech32, Tag, ToBech32}; 4use nostr::{nips::nip19::Nip19, secp256k1::XOnlyPublicKey, FromBech32, Tag, ToBech32};
5use serde::{Deserialize, Serialize}; 5use serde::{Deserialize, Serialize};
6 6
7#[cfg(not(test))] 7#[cfg(not(test))]
@@ -9,6 +9,7 @@ use crate::client::Client;
9#[cfg(test)] 9#[cfg(test)]
10use crate::client::MockConnect; 10use crate::client::MockConnect;
11use crate::{ 11use crate::{
12 cli_interactor::{Interactor, InteractorPrompt, PromptInputParms},
12 client::Connect, 13 client::Connect,
13 git::{Repo, RepoActions}, 14 git::{Repo, RepoActions},
14}; 15};
@@ -168,25 +169,59 @@ pub async fn fetch(
168 relays = repo_config.relays.clone(); 169 relays = repo_config.relays.clone();
169 } 170 }
170 171
171 let events: Vec<nostr::Event> = client.get_events(relays, vec![repo_event_filter]).await?; 172 let event = loop {
173 let events: Vec<nostr::Event> = client
174 .get_events(relays.clone(), vec![repo_event_filter.clone()])
175 .await?;
172 176
173 // TODO: fallback to ask user for nevent - to capture 177 // TODO: if maintainers.yaml isn't present, as the user to select from the
178 // pubkeys they want to use. could use WoT as an indicator as well as the repo
179 // and user name.
174 180
175 // TODO: if maintainers.yaml isn't present, as the user to select from the 181 // TODO: if maintainers.yaml isn't present, save the selected repo pubkey
176 // pubkeys they want to use. could use WoT as an indicator as well as the repo 182 // somewhere within .git folder for future use and seek to get that next time
177 // and user name. 183 if let Some(event) = events
178
179 // TODO: if maintainers.yaml isn't present, save the selected repo pubkey
180 // somewhere within .git folder for future use and seek to get that next time
181
182 RepoRef::try_from(
183 events
184 .iter() 184 .iter()
185 .filter(|e| e.kind.as_u64() == REPO_REF_KIND) 185 .filter(|e| e.kind.as_u64() == REPO_REF_KIND)
186 .max_by_key(|e| e.created_at) 186 .max_by_key(|e| e.created_at)
187 .context("cannot find repository reference event")? 187 {
188 .clone(), 188 break event.clone();
189 ) 189 }
190 println!("cannot find repo event");
191 loop {
192 let bech32 = Interactor::default()
193 .input(PromptInputParms::default().with_prompt("repository naddr or nevent"))?;
194 if let Ok(nip19) = Nip19::from_bech32(bech32) {
195 repo_event_filter =
196 nostr::Filter::default().kind(nostr::Kind::Custom(REPO_REF_KIND));
197 match nip19 {
198 Nip19::Coordinate(c) => {
199 repo_event_filter =
200 repo_event_filter.identifier(c.identifier).author(c.pubkey);
201 for r in c.relays {
202 relays.push(r);
203 }
204 }
205 Nip19::Event(n) => {
206 if let Some(author) = n.author {
207 repo_event_filter = repo_event_filter.id(n.event_id).author(author);
208 }
209 for r in n.relays {
210 relays.push(r);
211 }
212 }
213 Nip19::EventId(id) => repo_event_filter = repo_event_filter.id(id),
214 _ => (),
215 }
216 } else {
217 println!("not a valid nevent or naddr");
218 continue;
219 }
220 break;
221 }
222 };
223
224 RepoRef::try_from(event.clone()).context("cannot parse event as repo reference")
190} 225}
191 226
192#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)] 227#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
diff --git a/src/sub_commands/list.rs b/src/sub_commands/list.rs
index 49cbf6d..47a8fdc 100644
--- a/src/sub_commands/list.rs
+++ b/src/sub_commands/list.rs
@@ -51,6 +51,11 @@ pub async fn launch(_cli_args: &Cli, _args: &SubCommandArgs) -> Result<()> {
51 let pr_events: Vec<nostr::Event> = 51 let pr_events: Vec<nostr::Event> =
52 find_pr_events(&client, &repo_ref, &root_commit.to_string()).await?; 52 find_pr_events(&client, &repo_ref, &root_commit.to_string()).await?;
53 53
54 if pr_events.is_empty() {
55 println!("no PRs found... create one? try `ngit send`");
56 return Ok(());
57 }
58
54 let selected_index = Interactor::default().choice( 59 let selected_index = Interactor::default().choice(
55 PromptChoiceParms::default() 60 PromptChoiceParms::default()
56 .with_prompt("All PRs") 61 .with_prompt("All PRs")
diff --git a/tests/list.rs b/tests/list.rs
index 0d1d4e9..4337d73 100644
--- a/tests/list.rs
+++ b/tests/list.rs
@@ -103,6 +103,120 @@ fn cli_tester_create_pr(
103 Ok(()) 103 Ok(())
104} 104}
105 105
106mod cannot_find_repo_event {
107 use super::*;
108 mod cli_prompts {
109 use nostr::{
110 nips::{nip01::Coordinate, nip19::Nip19Event},
111 ToBech32,
112 };
113
114 use super::*;
115 async fn run_async_repo_event_ref_needed(
116 invalid_input: bool,
117 nevent: bool,
118 naddr: bool,
119 ) -> Result<()> {
120 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
121 Relay::new(8051, None, None),
122 Relay::new(8052, None, None),
123 Relay::new(8053, None, None),
124 Relay::new(8055, None, None),
125 Relay::new(8056, None, None),
126 );
127
128 r51.events.push(generate_test_key_1_relay_list_event());
129 r51.events.push(generate_test_key_1_metadata_event("fred"));
130
131 r55.events.push(generate_test_key_1_relay_list_event());
132 r55.events.push(generate_test_key_1_metadata_event("fred"));
133
134 let repo_event = generate_repo_ref_event();
135 r56.events.push(repo_event.clone());
136
137 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
138 let test_repo = GitTestRepo::default();
139 test_repo.populate()?;
140 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
141
142 p.expect("cannot find repo event\r\n")?;
143
144 if invalid_input {
145 let mut input = p.expect_input("repository naddr or nevent")?;
146 input.succeeds_with("dfgvfvfzadvd")?;
147 p.expect("not a valid nevent or naddr\r\n")?;
148 let _ = p.expect_input("repository naddr or nevent")?;
149 p.exit()?;
150 }
151 if nevent {
152 let mut input = p.expect_input("repository naddr or nevent")?;
153 input.succeeds_with(
154 &Nip19Event {
155 event_id: repo_event.id,
156 author: Some(TEST_KEY_1_KEYS.public_key()),
157 relays: vec!["ws://localhost:8056".to_string()],
158 }
159 .to_bech32()?,
160 )?;
161 p.expect("finding PRs...\r\n")?;
162 p.expect_end_with("no PRs found... create one? try `ngit send`\r\n")?;
163 }
164 if naddr {
165 let mut input = p.expect_input("repository naddr or nevent")?;
166 input.succeeds_with(
167 &Coordinate {
168 kind: nostr::Kind::Custom(REPOSITORY_KIND),
169 pubkey: TEST_KEY_1_KEYS.public_key(),
170 identifier: repo_event.identifier().unwrap().to_string(),
171 relays: vec!["ws://localhost:8056".to_string()],
172 }
173 .to_bech32()?,
174 )?;
175 p.expect("finding PRs...\r\n")?;
176 p.expect_end_with("no PRs found... create one? try `ngit send`\r\n")?;
177 p.expect_end_eventually()?;
178 }
179
180 for p in [51, 52, 53, 55, 56] {
181 relay::shutdown_relay(8000 + p)?;
182 }
183 Ok(())
184 });
185
186 // launch relay
187 let _ = join!(
188 r51.listen_until_close(),
189 r52.listen_until_close(),
190 r53.listen_until_close(),
191 r55.listen_until_close(),
192 r56.listen_until_close(),
193 );
194 cli_tester_handle.join().unwrap()?;
195 Ok(())
196 }
197
198 #[tokio::test]
199 #[serial]
200 async fn warns_not_valid_input_and_asks_again() -> Result<()> {
201 let _ = run_async_repo_event_ref_needed(true, false, false).await;
202 Ok(())
203 }
204
205 #[tokio::test]
206 #[serial]
207 async fn finds_based_on_nevent_on_embeded_relay() -> Result<()> {
208 let _ = run_async_repo_event_ref_needed(false, true, false).await;
209 Ok(())
210 }
211
212 #[tokio::test]
213 #[serial]
214 async fn finds_based_on_naddr_on_embeded_relay() -> Result<()> {
215 let _ = run_async_repo_event_ref_needed(false, false, true).await;
216 Ok(())
217 }
218 }
219}
106mod when_main_branch_is_uptodate { 220mod when_main_branch_is_uptodate {
107 use super::*; 221 use super::*;
108 222