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-12-03 15:29:06 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2024-12-03 15:29:06 +0000
commitd2478dbca6c5d3f61331ceabe20c6d9315cd6840 (patch)
tree9cd79f52ac96378ef68b4798db48ee65839d9f74
parent79f55ad6488ddb628438580acf54a1d23a990cb3 (diff)
refactor: limit fetch to 1 trusted coordinate
previously fetch supported fetching multiple trusted coordinates at once. The additional complexity trade off isn't worth it. It will still fetch events related to the coordinates of maintainers that the trusted maintainer lists. A scenario where there might be multiple trusted coordinates is where a large repo is split into multiple nostr repos to manage pull requests and issues in seperate sub-units. I might therefore have different remotes that target different identifiers. There also might be different set of maintainers groups that are have different views on the latest state of the same codebase and they haven't split off into using different identifiers. Its simplier ngit to fetch these different nostr repos independantly when requested. git-remote-nostr will do this automatically as it works through remotes but for ngit cmds a further change is required so `get_repo_coordinates` and `try_and_get_repo_coordinates` prompts to select the desired one.
-rw-r--r--src/bin/git_remote_nostr/main.rs12
-rw-r--r--src/bin/ngit/sub_commands/init.rs66
-rw-r--r--src/lib/client.rs86
-rw-r--r--src/lib/git/nostr_url.rs72
-rw-r--r--src/lib/login/user.rs6
-rw-r--r--src/lib/repo_ref.rs23
6 files changed, 134 insertions, 131 deletions
diff --git a/src/bin/git_remote_nostr/main.rs b/src/bin/git_remote_nostr/main.rs
index 54fb7cf..8e12d68 100644
--- a/src/bin/git_remote_nostr/main.rs
+++ b/src/bin/git_remote_nostr/main.rs
@@ -43,10 +43,10 @@ async fn main() -> Result<()> {
43 client.set_signer(signer).await; 43 client.set_signer(signer).await;
44 } 44 }
45 45
46 fetching_with_report_for_helper(git_repo_path, &client, &decoded_nostr_url.coordinates).await?; 46 fetching_with_report_for_helper(git_repo_path, &client, &decoded_nostr_url.coordinate).await?;
47 47
48 let repo_ref = 48 let repo_ref =
49 get_repo_ref_from_cache(Some(git_repo_path), &decoded_nostr_url.coordinates).await?; 49 get_repo_ref_from_cache(Some(git_repo_path), &decoded_nostr_url.coordinate).await?;
50 50
51 let stdin = io::stdin(); 51 let stdin = io::stdin();
52 let mut line = String::new(); 52 let mut line = String::new();
@@ -148,12 +148,16 @@ fn process_args() -> Result<Option<(NostrUrlDecoded, Repo)>> {
148async fn fetching_with_report_for_helper( 148async fn fetching_with_report_for_helper(
149 git_repo_path: &Path, 149 git_repo_path: &Path,
150 client: &Client, 150 client: &Client,
151 repo_coordinates: &HashSet<Coordinate>, 151 trusted_maintainer_coordinate: &Coordinate,
152) -> Result<()> { 152) -> Result<()> {
153 let term = console::Term::stderr(); 153 let term = console::Term::stderr();
154 term.write_line("nostr: fetching...")?; 154 term.write_line("nostr: fetching...")?;
155 let (relay_reports, progress_reporter) = client 155 let (relay_reports, progress_reporter) = client
156 .fetch_all(Some(git_repo_path), repo_coordinates, &HashSet::new()) 156 .fetch_all(
157 Some(git_repo_path),
158 Some(trusted_maintainer_coordinate),
159 &HashSet::new(),
160 )
157 .await?; 161 .await?;
158 if !relay_reports.iter().any(std::result::Result::is_err) { 162 if !relay_reports.iter().any(std::result::Result::is_err) {
159 let _ = progress_reporter.clear(); 163 let _ = progress_reporter.clear();
diff --git a/src/bin/ngit/sub_commands/init.rs b/src/bin/ngit/sub_commands/init.rs
index bf57769..9d87ba2 100644
--- a/src/bin/ngit/sub_commands/init.rs
+++ b/src/bin/ngit/sub_commands/init.rs
@@ -60,18 +60,17 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
60 60
61 let mut client = Client::default(); 61 let mut client = Client::default();
62 62
63 let repo_coordinates = if let Ok(repo_coordinates) = 63 let repo_coordinate = if let Ok(repo_coordinate) =
64 try_and_get_repo_coordinates(&git_repo, &client, false).await 64 try_and_get_repo_coordinates(&git_repo, &client, false).await
65 { 65 {
66 Some(repo_coordinates) 66 Some(repo_coordinate)
67 } else { 67 } else {
68 None 68 None
69 }; 69 };
70 70
71 let repo_ref = if let Some(repo_coordinates) = repo_coordinates.clone() { 71 let repo_ref = if let Some(repo_coordinate) = &repo_coordinate {
72 fetching_with_report(git_repo_path, &client, &repo_coordinates).await?; 72 fetching_with_report(git_repo_path, &client, repo_coordinate).await?;
73 if let Ok(repo_ref) = get_repo_ref_from_cache(Some(git_repo_path), &repo_coordinates).await 73 if let Ok(repo_ref) = get_repo_ref_from_cache(Some(git_repo_path), repo_coordinate).await {
74 {
75 Some(repo_ref) 74 Some(repo_ref)
76 } else { 75 } else {
77 None 76 None
@@ -98,12 +97,8 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
98 .with_prompt("repo name") 97 .with_prompt("repo name")
99 .with_default(if let Some(repo_ref) = &repo_ref { 98 .with_default(if let Some(repo_ref) = &repo_ref {
100 repo_ref.name.clone() 99 repo_ref.name.clone()
101 } else if let Some(repo_coordinates) = repo_coordinates.clone() { 100 } else if let Some(coordinate) = &repo_coordinate {
102 if let Some(coordinate) = repo_coordinates.iter().next() { 101 coordinate.identifier.clone()
103 coordinate.identifier.clone()
104 } else {
105 String::new()
106 }
107 } else { 102 } else {
108 String::new() 103 String::new()
109 }), 104 }),
@@ -119,12 +114,8 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
119 ) 114 )
120 .with_default(if let Some(repo_ref) = &repo_ref { 115 .with_default(if let Some(repo_ref) = &repo_ref {
121 repo_ref.identifier.clone() 116 repo_ref.identifier.clone()
122 } else if let Some(repo_coordinates) = repo_coordinates.clone() { 117 } else if let Some(repo_coordinate) = &repo_coordinate {
123 if let Some(coordinate) = repo_coordinates.iter().next() { 118 repo_coordinate.identifier.clone()
124 coordinate.identifier.clone()
125 } else {
126 String::new()
127 }
128 } else { 119 } else {
129 let fallback = name 120 let fallback = name
130 .clone() 121 .clone()
@@ -503,32 +494,21 @@ fn prompt_to_set_nostr_url_as_origin(repo_ref: &RepoRef, git_repo: &Repo) -> Res
503 if let Ok(origin_remote) = git_repo.git_repo.find_remote("origin") { 494 if let Ok(origin_remote) = git_repo.git_repo.find_remote("origin") {
504 if let Some(origin_url) = origin_remote.url() { 495 if let Some(origin_url) = origin_remote.url() {
505 if let Ok(nostr_url) = NostrUrlDecoded::from_str(origin_url) { 496 if let Ok(nostr_url) = NostrUrlDecoded::from_str(origin_url) {
506 if let Some(c) = &nostr_url.coordinates.iter().next() { 497 if nostr_url.coordinate.identifier == repo_ref.identifier {
507 if c.identifier == repo_ref.identifier { 498 if nostr_url.coordinate.public_key == repo_ref.trusted_maintainer {
508 if nostr_url 499 return Ok(());
509 .coordinates
510 .iter()
511 .next()
512 .context(
513 "a decoded nostr url will always have at least one coordinate",
514 )?
515 .public_key
516 == repo_ref.trusted_maintainer
517 {
518 return Ok(());
519 }
520 // origin is set to a different trusted maintainer
521 println!(
522 "warning: currently git remote 'origin' is set to a different trusted maintainer with the same identifier"
523 );
524 ask_to_set_origin_remote(repo_ref, git_repo)?;
525 } else {
526 // origin is linked to a different identifier
527 println!(
528 "warning: currently git remote 'origin' is set to a different repository identifier"
529 );
530 ask_to_set_origin_remote(repo_ref, git_repo)?;
531 } 500 }
501 // origin is set to a different trusted maintainer
502 println!(
503 "warning: currently git remote 'origin' is set to a different trusted maintainer with the same identifier"
504 );
505 ask_to_set_origin_remote(repo_ref, git_repo)?;
506 } else {
507 // origin is linked to a different identifier
508 println!(
509 "warning: currently git remote 'origin' is set to a different repository identifier"
510 );
511 ask_to_set_origin_remote(repo_ref, git_repo)?;
532 } 512 }
533 } else { 513 } else {
534 // remote is non-nostr url 514 // remote is non-nostr url
diff --git a/src/lib/client.rs b/src/lib/client.rs
index 4b87cd8..32f5bd7 100644
--- a/src/lib/client.rs
+++ b/src/lib/client.rs
@@ -89,7 +89,7 @@ pub trait Connect {
89 async fn fetch_all<'a>( 89 async fn fetch_all<'a>(
90 &self, 90 &self,
91 git_repo_path: Option<&'a Path>, 91 git_repo_path: Option<&'a Path>,
92 repo_coordinates: &HashSet<Coordinate>, 92 repo_coordinates: Option<&'a Coordinate>,
93 user_profiles: &HashSet<PublicKey>, 93 user_profiles: &HashSet<PublicKey>,
94 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)>; 94 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)>;
95 async fn fetch_all_from_relay<'a>( 95 async fn fetch_all_from_relay<'a>(
@@ -329,7 +329,7 @@ impl Connect for Client {
329 async fn fetch_all<'a>( 329 async fn fetch_all<'a>(
330 &self, 330 &self,
331 git_repo_path: Option<&'a Path>, 331 git_repo_path: Option<&'a Path>,
332 repo_coordinates: &HashSet<Coordinate>, 332 trusted_maintainer_coordinate: Option<&'a Coordinate>,
333 user_profiles: &HashSet<PublicKey>, 333 user_profiles: &HashSet<PublicKey>,
334 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)> { 334 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)> {
335 let fallback_relays = &self 335 let fallback_relays = &self
@@ -340,7 +340,7 @@ impl Connect for Client {
340 340
341 let mut request = create_relays_request( 341 let mut request = create_relays_request(
342 git_repo_path, 342 git_repo_path,
343 repo_coordinates, 343 trusted_maintainer_coordinate,
344 user_profiles, 344 user_profiles,
345 fallback_relays.clone(), 345 fallback_relays.clone(),
346 ) 346 )
@@ -468,8 +468,12 @@ impl Connect for Client {
468 } 468 }
469 processed_relays.extend(relays.clone()); 469 processed_relays.extend(relays.clone());
470 470
471 if let Ok(repo_ref) = get_repo_ref_from_cache(git_repo_path, repo_coordinates).await { 471 if let Some(trusted_maintainer_coordinate) = trusted_maintainer_coordinate {
472 request.repo_relays = repo_ref.relays.iter().cloned().collect(); 472 if let Ok(repo_ref) =
473 get_repo_ref_from_cache(git_repo_path, trusted_maintainer_coordinate).await
474 {
475 request.repo_relays = repo_ref.relays.iter().cloned().collect();
476 }
473 } 477 }
474 478
475 request.user_relays_for_profiles = { 479 request.user_relays_for_profiles = {
@@ -809,18 +813,24 @@ pub async fn save_event_in_global_cache(
809 813
810pub async fn get_repo_ref_from_cache( 814pub async fn get_repo_ref_from_cache(
811 git_repo_path: Option<&Path>, 815 git_repo_path: Option<&Path>,
812 repo_coordinates: &HashSet<Coordinate>, 816 repo_coordinate: &Coordinate,
813) -> Result<RepoRef> { 817) -> Result<RepoRef> {
814 let mut maintainers = HashSet::new(); 818 let mut maintainers = HashSet::new();
815 let mut new_coordinate: bool; 819 let mut new_coordinate: bool;
816 820
817 for c in repo_coordinates { 821 maintainers.insert(repo_coordinate.public_key);
818 maintainers.insert(c.public_key);
819 }
820 let mut repo_events = vec![]; 822 let mut repo_events = vec![];
821 loop { 823 loop {
822 new_coordinate = false; 824 new_coordinate = false;
823 let repo_events_filter = get_filter_repo_events(repo_coordinates); 825 let repo_events_filter =
826 get_filter_repo_events(&HashSet::from_iter(maintainers.iter().map(|m| {
827 Coordinate {
828 kind: Kind::GitRepoAnnouncement,
829 public_key: *m,
830 identifier: repo_coordinate.identifier.to_string(),
831 relays: vec![],
832 }
833 })));
824 834
825 let events = [ 835 let events = [
826 get_event_from_global_cache(git_repo_path, vec![repo_events_filter.clone()]).await?, 836 get_event_from_global_cache(git_repo_path, vec![repo_events_filter.clone()]).await?,
@@ -832,13 +842,7 @@ pub async fn get_repo_ref_from_cache(
832 ] 842 ]
833 .concat(); 843 .concat();
834 for e in events { 844 for e in events {
835 if let Ok(repo_ref) = RepoRef::try_from(( 845 if let Ok(repo_ref) = RepoRef::try_from((e.clone(), None)) {
836 e.clone(),
837 repo_coordinates
838 .iter()
839 .next()
840 .map(|coordinate| coordinate.public_key),
841 )) {
842 for m in repo_ref.maintainers { 846 for m in repo_ref.maintainers {
843 if maintainers.insert(m) { 847 if maintainers.insert(m) {
844 new_coordinate = true; 848 new_coordinate = true;
@@ -857,10 +861,7 @@ pub async fn get_repo_ref_from_cache(
857 .first() 861 .first()
858 .context("no repo announcement event found at specified coordinates. if you are the repository maintainer consider running `ngit init` to create one")? 862 .context("no repo announcement event found at specified coordinates. if you are the repository maintainer consider running `ngit init` to create one")?
859 .clone(), 863 .clone(),
860 repo_coordinates 864 Some(repo_coordinate.public_key),
861 .iter()
862 .next()
863 .map(|coordinate| coordinate.public_key),
864 ))?; 865 ))?;
865 866
866 let mut events: HashMap<Coordinate, nostr::Event> = HashMap::new(); 867 let mut events: HashMap<Coordinate, nostr::Event> = HashMap::new();
@@ -913,27 +914,40 @@ pub async fn get_state_from_cache(
913#[allow(clippy::too_many_lines)] 914#[allow(clippy::too_many_lines)]
914async fn create_relays_request( 915async fn create_relays_request(
915 git_repo_path: Option<&Path>, 916 git_repo_path: Option<&Path>,
916 repo_coordinates: &HashSet<Coordinate>, 917 trusted_maintainer_coordinate: Option<&Coordinate>,
917 user_profiles: &HashSet<PublicKey>, 918 user_profiles: &HashSet<PublicKey>,
918 fallback_relays: HashSet<RelayUrl>, 919 fallback_relays: HashSet<RelayUrl>,
919) -> Result<FetchRequest> { 920) -> Result<FetchRequest> {
920 let repo_ref = get_repo_ref_from_cache(git_repo_path, repo_coordinates).await; 921 let repo_ref = if let Some(trusted_maintainer_coordinate) = trusted_maintainer_coordinate {
922 if let Ok(repo_ref) =
923 get_repo_ref_from_cache(git_repo_path, trusted_maintainer_coordinate).await
924 {
925 Some(repo_ref)
926 } else {
927 None
928 }
929 } else {
930 None
931 };
921 932
922 let repo_coordinates = { 933 let repo_coordinates = {
923 // add coordinates of users listed in maintainers to explicitly specified 934 // add coordinates of users listed in maintainers to explicitly specified
924 // coodinates 935 // coodinates
925 let mut repo_coordinates = repo_coordinates.clone(); 936 let mut set: HashSet<Coordinate> = HashSet::new();
926 if let Ok(repo_ref) = &repo_ref { 937 if let Some(trusted_maintainer_coordinate) = trusted_maintainer_coordinate {
938 set.insert(trusted_maintainer_coordinate.clone());
939 }
940 if let Some(repo_ref) = &repo_ref {
927 for c in repo_ref.coordinates() { 941 for c in repo_ref.coordinates() {
928 if !repo_coordinates 942 if !set
929 .iter() 943 .iter()
930 .any(|e| e.identifier.eq(&c.identifier) && e.public_key.eq(&c.public_key)) 944 .any(|e| e.identifier.eq(&c.identifier) && e.public_key.eq(&c.public_key))
931 { 945 {
932 repo_coordinates.insert(c); 946 set.insert(c);
933 } 947 }
934 } 948 }
935 } 949 }
936 repo_coordinates 950 set
937 }; 951 };
938 952
939 let repo_coordinates_without_relays = { 953 let repo_coordinates_without_relays = {
@@ -954,7 +968,7 @@ async fn create_relays_request(
954 let mut contributors: HashSet<PublicKey> = HashSet::new(); 968 let mut contributors: HashSet<PublicKey> = HashSet::new();
955 969
956 if !repo_coordinates_without_relays.is_empty() { 970 if !repo_coordinates_without_relays.is_empty() {
957 if let Ok(repo_ref) = &repo_ref { 971 if let Some(repo_ref) = &repo_ref {
958 for m in &repo_ref.maintainers { 972 for m in &repo_ref.maintainers {
959 contributors.insert(m.to_owned()); 973 contributors.insert(m.to_owned());
960 } 974 }
@@ -1077,7 +1091,7 @@ async fn create_relays_request(
1077 1091
1078 let relays = { 1092 let relays = {
1079 let mut relays = fallback_relays; 1093 let mut relays = fallback_relays;
1080 if let Ok(repo_ref) = &repo_ref { 1094 if let Some(repo_ref) = &repo_ref {
1081 for r in repo_ref.relays.clone() { 1095 for r in repo_ref.relays.clone() {
1082 relays.insert(r); 1096 relays.insert(r);
1083 } 1097 }
@@ -1113,7 +1127,7 @@ async fn create_relays_request(
1113 selected_relay: None, 1127 selected_relay: None,
1114 repo_relays: relays, 1128 repo_relays: relays,
1115 relay_column_width, 1129 relay_column_width,
1116 repo_coordinates_without_relays: if let Ok(repo_ref) = &repo_ref { 1130 repo_coordinates_without_relays: if let Some(repo_ref) = &repo_ref {
1117 repo_ref.coordinates_with_timestamps() 1131 repo_ref.coordinates_with_timestamps()
1118 } else { 1132 } else {
1119 repo_coordinates_without_relays 1133 repo_coordinates_without_relays
@@ -1121,7 +1135,7 @@ async fn create_relays_request(
1121 .map(|c| (c.clone(), None)) 1135 .map(|c| (c.clone(), None))
1122 .collect() 1136 .collect()
1123 }, 1137 },
1124 state: if let Ok(repo_ref) = &repo_ref { 1138 state: if let Some(repo_ref) = &repo_ref {
1125 if let Ok(existing_state) = get_state_from_cache(git_repo_path, repo_ref).await { 1139 if let Ok(existing_state) = get_state_from_cache(git_repo_path, repo_ref).await {
1126 Some((existing_state.event.created_at, existing_state.event.id)) 1140 Some((existing_state.event.created_at, existing_state.event.id))
1127 } else { 1141 } else {
@@ -1523,12 +1537,16 @@ pub async fn fetching_with_report(
1523 git_repo_path: &Path, 1537 git_repo_path: &Path,
1524 #[cfg(test)] client: &crate::client::MockConnect, 1538 #[cfg(test)] client: &crate::client::MockConnect,
1525 #[cfg(not(test))] client: &Client, 1539 #[cfg(not(test))] client: &Client,
1526 repo_coordinates: &HashSet<Coordinate>, 1540 trusted_maintainer_coordinate: &Coordinate,
1527) -> Result<FetchReport> { 1541) -> Result<FetchReport> {
1528 let term = console::Term::stderr(); 1542 let term = console::Term::stderr();
1529 term.write_line("fetching updates...")?; 1543 term.write_line("fetching updates...")?;
1530 let (relay_reports, progress_reporter) = client 1544 let (relay_reports, progress_reporter) = client
1531 .fetch_all(Some(git_repo_path), repo_coordinates, &HashSet::new()) 1545 .fetch_all(
1546 Some(git_repo_path),
1547 Some(trusted_maintainer_coordinate),
1548 &HashSet::new(),
1549 )
1532 .await?; 1550 .await?;
1533 if !relay_reports.iter().any(std::result::Result::is_err) { 1551 if !relay_reports.iter().any(std::result::Result::is_err) {
1534 let _ = progress_reporter.clear(); 1552 let _ = progress_reporter.clear();
diff --git a/src/lib/git/nostr_url.rs b/src/lib/git/nostr_url.rs
index a501765..c26bb2e 100644
--- a/src/lib/git/nostr_url.rs
+++ b/src/lib/git/nostr_url.rs
@@ -1,5 +1,5 @@
1use core::fmt; 1use core::fmt;
2use std::{collections::HashSet, str::FromStr}; 2use std::str::FromStr;
3 3
4use anyhow::{anyhow, bail, Context, Error, Result}; 4use anyhow::{anyhow, bail, Context, Error, Result};
5use nostr::nips::nip01::Coordinate; 5use nostr::nips::nip01::Coordinate;
@@ -56,7 +56,7 @@ impl FromStr for ServerProtocol {
56#[derive(Debug, PartialEq)] 56#[derive(Debug, PartialEq)]
57pub struct NostrUrlDecoded { 57pub struct NostrUrlDecoded {
58 pub original_string: String, 58 pub original_string: String,
59 pub coordinates: HashSet<Coordinate>, 59 pub coordinate: Coordinate,
60 pub protocol: Option<ServerProtocol>, 60 pub protocol: Option<ServerProtocol>,
61 pub user: Option<String>, 61 pub user: Option<String>,
62} 62}
@@ -70,9 +70,8 @@ impl fmt::Display for NostrUrlDecoded {
70 if let Some(protocol) = &self.protocol { 70 if let Some(protocol) = &self.protocol {
71 write!(f, "{}/", protocol)?; 71 write!(f, "{}/", protocol)?;
72 } 72 }
73 let c = self.coordinates.iter().next().unwrap(); 73 write!(f, "{}/", self.coordinate.public_key.to_bech32().unwrap())?;
74 write!(f, "{}/", c.public_key.to_bech32().unwrap())?; 74 if let Some(relay) = self.coordinate.relays.first() {
75 if let Some(relay) = c.relays.first() {
76 write!( 75 write!(
77 f, 76 f,
78 "{}/", 77 "{}/",
@@ -84,7 +83,7 @@ impl fmt::Display for NostrUrlDecoded {
84 ) 83 )
85 )?; 84 )?;
86 } 85 }
87 write!(f, "{}", c.identifier) 86 write!(f, "{}", self.coordinate.identifier)
88 } 87 }
89} 88}
90 89
@@ -94,7 +93,6 @@ impl std::str::FromStr for NostrUrlDecoded {
94 type Err = anyhow::Error; 93 type Err = anyhow::Error;
95 94
96 fn from_str(url: &str) -> Result<Self> { 95 fn from_str(url: &str) -> Result<Self> {
97 let mut coordinates = HashSet::new();
98 let mut protocol = None; 96 let mut protocol = None;
99 let mut user = None; 97 let mut user = None;
100 let mut relays = vec![]; 98 let mut relays = vec![];
@@ -157,9 +155,9 @@ impl std::str::FromStr for NostrUrlDecoded {
157 // extract naddr npub/<optional-relays>/identifer 155 // extract naddr npub/<optional-relays>/identifer
158 let part = parts.first().context(INCORRECT_NOSTR_URL_FORMAT_ERROR)?; 156 let part = parts.first().context(INCORRECT_NOSTR_URL_FORMAT_ERROR)?;
159 // naddr used 157 // naddr used
160 if let Ok(coordinate) = Coordinate::parse(part) { 158 let coordinate = if let Ok(coordinate) = Coordinate::parse(part) {
161 if coordinate.kind.eq(&nostr_sdk::Kind::GitRepoAnnouncement) { 159 if coordinate.kind.eq(&nostr_sdk::Kind::GitRepoAnnouncement) {
162 coordinates.insert(coordinate); 160 coordinate
163 } else { 161 } else {
164 bail!("naddr doesnt point to a git repository announcement"); 162 bail!("naddr doesnt point to a git repository announcement");
165 } 163 }
@@ -181,19 +179,19 @@ impl std::str::FromStr for NostrUrlDecoded {
181 RelayUrl::parse(&decoded).context("could not parse relays in nostr git url")?; 179 RelayUrl::parse(&decoded).context("could not parse relays in nostr git url")?;
182 relays.push(url); 180 relays.push(url);
183 } 181 }
184 coordinates.insert(Coordinate { 182 Coordinate {
185 identifier, 183 identifier,
186 public_key, 184 public_key,
187 kind: nostr_sdk::Kind::GitRepoAnnouncement, 185 kind: nostr_sdk::Kind::GitRepoAnnouncement,
188 relays, 186 relays,
189 }); 187 }
190 } else { 188 } else {
191 bail!(INCORRECT_NOSTR_URL_FORMAT_ERROR); 189 bail!(INCORRECT_NOSTR_URL_FORMAT_ERROR);
192 } 190 };
193 191
194 Ok(Self { 192 Ok(Self {
195 original_string: url.to_string(), 193 original_string: url.to_string(),
196 coordinates, 194 coordinate,
197 protocol, 195 protocol,
198 user, 196 user,
199 }) 197 })
@@ -865,8 +863,6 @@ mod tests {
865 } 863 }
866 } 864 }
867 mod nostr_git_url_format { 865 mod nostr_git_url_format {
868 use std::collections::HashSet;
869
870 use nostr::nips::nip01::Coordinate; 866 use nostr::nips::nip01::Coordinate;
871 use nostr_sdk::PublicKey; 867 use nostr_sdk::PublicKey;
872 868
@@ -880,7 +876,7 @@ mod tests {
880 "{}", 876 "{}",
881 NostrUrlDecoded { 877 NostrUrlDecoded {
882 original_string: String::new(), 878 original_string: String::new(),
883 coordinates: HashSet::from_iter(vec![Coordinate { 879 coordinate: Coordinate {
884 identifier: "ngit".to_string(), 880 identifier: "ngit".to_string(),
885 public_key: PublicKey::parse( 881 public_key: PublicKey::parse(
886 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 882 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
@@ -888,7 +884,7 @@ mod tests {
888 .unwrap(), 884 .unwrap(),
889 kind: nostr_sdk::Kind::GitRepoAnnouncement, 885 kind: nostr_sdk::Kind::GitRepoAnnouncement,
890 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], 886 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()],
891 }]), 887 },
892 protocol: None, 888 protocol: None,
893 user: None, 889 user: None,
894 } 890 }
@@ -905,7 +901,7 @@ mod tests {
905 "{}", 901 "{}",
906 NostrUrlDecoded { 902 NostrUrlDecoded {
907 original_string: String::new(), 903 original_string: String::new(),
908 coordinates: HashSet::from_iter(vec![Coordinate { 904 coordinate: Coordinate {
909 identifier: "ngit".to_string(), 905 identifier: "ngit".to_string(),
910 public_key: PublicKey::parse( 906 public_key: PublicKey::parse(
911 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 907 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
@@ -913,7 +909,7 @@ mod tests {
913 .unwrap(), 909 .unwrap(),
914 kind: nostr_sdk::Kind::GitRepoAnnouncement, 910 kind: nostr_sdk::Kind::GitRepoAnnouncement,
915 relays: vec![], 911 relays: vec![],
916 }]), 912 },
917 protocol: None, 913 protocol: None,
918 user: None, 914 user: None,
919 } 915 }
@@ -930,7 +926,7 @@ mod tests {
930 "{}", 926 "{}",
931 NostrUrlDecoded { 927 NostrUrlDecoded {
932 original_string: String::new(), 928 original_string: String::new(),
933 coordinates: HashSet::from_iter(vec![Coordinate { 929 coordinate: Coordinate {
934 identifier: "ngit".to_string(), 930 identifier: "ngit".to_string(),
935 public_key: PublicKey::parse( 931 public_key: PublicKey::parse(
936 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 932 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
@@ -938,7 +934,7 @@ mod tests {
938 .unwrap(), 934 .unwrap(),
939 kind: nostr_sdk::Kind::GitRepoAnnouncement, 935 kind: nostr_sdk::Kind::GitRepoAnnouncement,
940 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], 936 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()],
941 }]), 937 },
942 protocol: Some(ServerProtocol::Ssh), 938 protocol: Some(ServerProtocol::Ssh),
943 user: None, 939 user: None,
944 } 940 }
@@ -955,7 +951,7 @@ mod tests {
955 "{}", 951 "{}",
956 NostrUrlDecoded { 952 NostrUrlDecoded {
957 original_string: String::new(), 953 original_string: String::new(),
958 coordinates: HashSet::from_iter(vec![Coordinate { 954 coordinate: Coordinate {
959 identifier: "ngit".to_string(), 955 identifier: "ngit".to_string(),
960 public_key: PublicKey::parse( 956 public_key: PublicKey::parse(
961 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 957 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
@@ -963,7 +959,7 @@ mod tests {
963 .unwrap(), 959 .unwrap(),
964 kind: nostr_sdk::Kind::GitRepoAnnouncement, 960 kind: nostr_sdk::Kind::GitRepoAnnouncement,
965 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], 961 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()],
966 }]), 962 },
967 protocol: Some(ServerProtocol::Ssh), 963 protocol: Some(ServerProtocol::Ssh),
968 user: Some("bla".to_string()), 964 user: Some("bla".to_string()),
969 } 965 }
@@ -1002,7 +998,7 @@ mod tests {
1002 NostrUrlDecoded::from_str(&url)?, 998 NostrUrlDecoded::from_str(&url)?,
1003 NostrUrlDecoded { 999 NostrUrlDecoded {
1004 original_string: url.clone(), 1000 original_string: url.clone(),
1005 coordinates: HashSet::from([Coordinate { 1001 coordinate: Coordinate {
1006 identifier: "ngit".to_string(), 1002 identifier: "ngit".to_string(),
1007 public_key: PublicKey::parse( 1003 public_key: PublicKey::parse(
1008 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 1004 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
@@ -1011,7 +1007,7 @@ mod tests {
1011 kind: nostr_sdk::Kind::GitRepoAnnouncement, 1007 kind: nostr_sdk::Kind::GitRepoAnnouncement,
1012 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], /* wont add the 1008 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], /* wont add the
1013 * slash */ 1009 * slash */
1014 }]), 1010 },
1015 protocol: None, 1011 protocol: None,
1016 user: None, 1012 user: None,
1017 }, 1013 },
@@ -1031,7 +1027,7 @@ mod tests {
1031 NostrUrlDecoded::from_str(&url)?, 1027 NostrUrlDecoded::from_str(&url)?,
1032 NostrUrlDecoded { 1028 NostrUrlDecoded {
1033 original_string: url.clone(), 1029 original_string: url.clone(),
1034 coordinates: HashSet::from([get_model_coordinate(false)]), 1030 coordinate: get_model_coordinate(false),
1035 protocol: None, 1031 protocol: None,
1036 user: None, 1032 user: None,
1037 }, 1033 },
@@ -1049,7 +1045,7 @@ mod tests {
1049 NostrUrlDecoded::from_str(&url)?, 1045 NostrUrlDecoded::from_str(&url)?,
1050 NostrUrlDecoded { 1046 NostrUrlDecoded {
1051 original_string: url.clone(), 1047 original_string: url.clone(),
1052 coordinates: HashSet::from([get_model_coordinate(true)]), 1048 coordinate: get_model_coordinate(true),
1053 protocol: None, 1049 protocol: None,
1054 user: None, 1050 user: None,
1055 }, 1051 },
@@ -1067,7 +1063,7 @@ mod tests {
1067 NostrUrlDecoded::from_str(&url)?, 1063 NostrUrlDecoded::from_str(&url)?,
1068 NostrUrlDecoded { 1064 NostrUrlDecoded {
1069 original_string: url.clone(), 1065 original_string: url.clone(),
1070 coordinates: HashSet::from([get_model_coordinate(true)]), 1066 coordinate: get_model_coordinate(true),
1071 protocol: None, 1067 protocol: None,
1072 user: None, 1068 user: None,
1073 }, 1069 },
@@ -1086,7 +1082,7 @@ mod tests {
1086 NostrUrlDecoded::from_str(&url)?, 1082 NostrUrlDecoded::from_str(&url)?,
1087 NostrUrlDecoded { 1083 NostrUrlDecoded {
1088 original_string: url.clone(), 1084 original_string: url.clone(),
1089 coordinates: HashSet::from([Coordinate { 1085 coordinate: Coordinate {
1090 identifier: "ngit".to_string(), 1086 identifier: "ngit".to_string(),
1091 public_key: PublicKey::parse( 1087 public_key: PublicKey::parse(
1092 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 1088 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
@@ -1097,7 +1093,7 @@ mod tests {
1097 RelayUrl::parse("wss://nos.lol/").unwrap(), 1093 RelayUrl::parse("wss://nos.lol/").unwrap(),
1098 RelayUrl::parse("wss://relay.damus.io/").unwrap(), 1094 RelayUrl::parse("wss://relay.damus.io/").unwrap(),
1099 ], 1095 ],
1100 }]), 1096 },
1101 protocol: None, 1097 protocol: None,
1102 user: None, 1098 user: None,
1103 }, 1099 },
@@ -1112,7 +1108,7 @@ mod tests {
1112 NostrUrlDecoded::from_str(&url)?, 1108 NostrUrlDecoded::from_str(&url)?,
1113 NostrUrlDecoded { 1109 NostrUrlDecoded {
1114 original_string: url.clone(), 1110 original_string: url.clone(),
1115 coordinates: HashSet::from([get_model_coordinate(false)]), 1111 coordinate: get_model_coordinate(false),
1116 protocol: Some(ServerProtocol::Ssh), 1112 protocol: Some(ServerProtocol::Ssh),
1117 user: None, 1113 user: None,
1118 }, 1114 },
@@ -1127,7 +1123,7 @@ mod tests {
1127 NostrUrlDecoded::from_str(&url)?, 1123 NostrUrlDecoded::from_str(&url)?,
1128 NostrUrlDecoded { 1124 NostrUrlDecoded {
1129 original_string: url.clone(), 1125 original_string: url.clone(),
1130 coordinates: HashSet::from([get_model_coordinate(false)]), 1126 coordinate: get_model_coordinate(false),
1131 protocol: Some(ServerProtocol::Ssh), 1127 protocol: Some(ServerProtocol::Ssh),
1132 user: Some("fred".to_string()), 1128 user: Some("fred".to_string()),
1133 }, 1129 },
@@ -1146,7 +1142,7 @@ mod tests {
1146 NostrUrlDecoded::from_str(&url)?, 1142 NostrUrlDecoded::from_str(&url)?,
1147 NostrUrlDecoded { 1143 NostrUrlDecoded {
1148 original_string: url.clone(), 1144 original_string: url.clone(),
1149 coordinates: HashSet::from([get_model_coordinate(true)]), 1145 coordinate: get_model_coordinate(true),
1150 protocol: None, 1146 protocol: None,
1151 user: None, 1147 user: None,
1152 }, 1148 },
@@ -1164,7 +1160,7 @@ mod tests {
1164 NostrUrlDecoded::from_str(&url)?, 1160 NostrUrlDecoded::from_str(&url)?,
1165 NostrUrlDecoded { 1161 NostrUrlDecoded {
1166 original_string: url.clone(), 1162 original_string: url.clone(),
1167 coordinates: HashSet::from([get_model_coordinate(true)]), 1163 coordinate: get_model_coordinate(true),
1168 protocol: None, 1164 protocol: None,
1169 user: None, 1165 user: None,
1170 }, 1166 },
@@ -1183,7 +1179,7 @@ mod tests {
1183 NostrUrlDecoded::from_str(&url)?, 1179 NostrUrlDecoded::from_str(&url)?,
1184 NostrUrlDecoded { 1180 NostrUrlDecoded {
1185 original_string: url.clone(), 1181 original_string: url.clone(),
1186 coordinates: HashSet::from([Coordinate { 1182 coordinate: Coordinate {
1187 identifier: "ngit".to_string(), 1183 identifier: "ngit".to_string(),
1188 public_key: PublicKey::parse( 1184 public_key: PublicKey::parse(
1189 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 1185 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
@@ -1194,7 +1190,7 @@ mod tests {
1194 RelayUrl::parse("wss://nos.lol/").unwrap(), 1190 RelayUrl::parse("wss://nos.lol/").unwrap(),
1195 RelayUrl::parse("wss://relay.damus.io/").unwrap(), 1191 RelayUrl::parse("wss://relay.damus.io/").unwrap(),
1196 ], 1192 ],
1197 }]), 1193 },
1198 protocol: None, 1194 protocol: None,
1199 user: None, 1195 user: None,
1200 }, 1196 },
@@ -1209,7 +1205,7 @@ mod tests {
1209 NostrUrlDecoded::from_str(&url)?, 1205 NostrUrlDecoded::from_str(&url)?,
1210 NostrUrlDecoded { 1206 NostrUrlDecoded {
1211 original_string: url.clone(), 1207 original_string: url.clone(),
1212 coordinates: HashSet::from([get_model_coordinate(false)]), 1208 coordinate: get_model_coordinate(false),
1213 protocol: Some(ServerProtocol::Ssh), 1209 protocol: Some(ServerProtocol::Ssh),
1214 user: None, 1210 user: None,
1215 }, 1211 },
@@ -1224,7 +1220,7 @@ mod tests {
1224 NostrUrlDecoded::from_str(&url)?, 1220 NostrUrlDecoded::from_str(&url)?,
1225 NostrUrlDecoded { 1221 NostrUrlDecoded {
1226 original_string: url.clone(), 1222 original_string: url.clone(),
1227 coordinates: HashSet::from([get_model_coordinate(false)]), 1223 coordinate: get_model_coordinate(false),
1228 protocol: Some(ServerProtocol::Ssh), 1224 protocol: Some(ServerProtocol::Ssh),
1229 user: Some("fred".to_string()), 1225 user: Some("fred".to_string()),
1230 }, 1226 },
diff --git a/src/lib/login/user.rs b/src/lib/login/user.rs
index 9534bbe..1898a1f 100644
--- a/src/lib/login/user.rs
+++ b/src/lib/login/user.rs
@@ -75,11 +75,7 @@ pub async fn get_user_details(
75 let term = console::Term::stderr(); 75 let term = console::Term::stderr();
76 term.write_line("searching for profile...")?; 76 term.write_line("searching for profile...")?;
77 let (_, progress_reporter) = client 77 let (_, progress_reporter) = client
78 .fetch_all( 78 .fetch_all(git_repo_path, None, &HashSet::from_iter(vec![*public_key]))
79 git_repo_path,
80 &HashSet::new(),
81 &HashSet::from_iter(vec![*public_key]),
82 )
83 .await?; 79 .await?;
84 if let Ok(user_ref) = get_user_ref_from_cache(git_repo_path, public_key).await { 80 if let Ok(user_ref) = get_user_ref_from_cache(git_repo_path, public_key).await {
85 progress_reporter.clear()?; 81 progress_reporter.clear()?;
diff --git a/src/lib/repo_ref.rs b/src/lib/repo_ref.rs
index 69fbe64..988c87d 100644
--- a/src/lib/repo_ref.rs
+++ b/src/lib/repo_ref.rs
@@ -188,6 +188,13 @@ impl RepoRef {
188 /// coordinates without relay hints 188 /// coordinates without relay hints
189 pub fn coordinates(&self) -> HashSet<Coordinate> { 189 pub fn coordinates(&self) -> HashSet<Coordinate> {
190 let mut res = HashSet::new(); 190 let mut res = HashSet::new();
191 res.insert(Coordinate {
192 kind: Kind::GitRepoAnnouncement,
193 public_key: self.trusted_maintainer,
194 identifier: self.identifier.clone(),
195 relays: vec![],
196 });
197
191 for m in &self.maintainers { 198 for m in &self.maintainers {
192 res.insert(Coordinate { 199 res.insert(Coordinate {
193 kind: Kind::GitRepoAnnouncement, 200 kind: Kind::GitRepoAnnouncement,
@@ -226,7 +233,7 @@ impl RepoRef {
226 "{}", 233 "{}",
227 NostrUrlDecoded { 234 NostrUrlDecoded {
228 original_string: String::new(), 235 original_string: String::new(),
229 coordinates: HashSet::from_iter(vec![self.coordinate_with_hint()]), 236 coordinate: self.coordinate_with_hint(),
230 protocol: None, 237 protocol: None,
231 user: None, 238 user: None,
232 } 239 }
@@ -238,7 +245,7 @@ pub async fn get_repo_coordinates(
238 git_repo: &Repo, 245 git_repo: &Repo,
239 #[cfg(test)] client: &crate::client::MockConnect, 246 #[cfg(test)] client: &crate::client::MockConnect,
240 #[cfg(not(test))] client: &Client, 247 #[cfg(not(test))] client: &Client,
241) -> Result<HashSet<Coordinate>> { 248) -> Result<Coordinate> {
242 try_and_get_repo_coordinates(git_repo, client, true).await 249 try_and_get_repo_coordinates(git_repo, client, true).await
243} 250}
244 251
@@ -247,7 +254,7 @@ pub async fn try_and_get_repo_coordinates(
247 #[cfg(test)] client: &crate::client::MockConnect, 254 #[cfg(test)] client: &crate::client::MockConnect,
248 #[cfg(not(test))] client: &Client, 255 #[cfg(not(test))] client: &Client,
249 prompt_user: bool, 256 prompt_user: bool,
250) -> Result<HashSet<Coordinate>> { 257) -> Result<Coordinate> {
251 let mut repo_coordinates = get_repo_coordinates_from_git_config(git_repo)?; 258 let mut repo_coordinates = get_repo_coordinates_from_git_config(git_repo)?;
252 259
253 if repo_coordinates.is_empty() { 260 if repo_coordinates.is_empty() {
@@ -265,7 +272,11 @@ pub async fn try_and_get_repo_coordinates(
265 bail!("couldn't find repo coordinates in git config nostr.repo or in maintainers.yaml"); 272 bail!("couldn't find repo coordinates in git config nostr.repo or in maintainers.yaml");
266 } 273 }
267 } 274 }
268 Ok(repo_coordinates) 275 Ok(repo_coordinates
276 .iter()
277 .next()
278 .context("would have bailed if no coordinates found")?
279 .clone())
269} 280}
270 281
271fn get_repo_coordinates_from_git_config(git_repo: &Repo) -> Result<HashSet<Coordinate>> { 282fn get_repo_coordinates_from_git_config(git_repo: &Repo) -> Result<HashSet<Coordinate>> {
@@ -285,9 +296,7 @@ fn get_repo_coordinates_from_nostr_remotes(git_repo: &Repo) -> Result<HashSet<Co
285 for remote_name in git_repo.git_repo.remotes()?.iter().flatten() { 296 for remote_name in git_repo.git_repo.remotes()?.iter().flatten() {
286 if let Some(remote_url) = git_repo.git_repo.find_remote(remote_name)?.url() { 297 if let Some(remote_url) = git_repo.git_repo.find_remote(remote_name)?.url() {
287 if let Ok(nostr_url_decoded) = NostrUrlDecoded::from_str(remote_url) { 298 if let Ok(nostr_url_decoded) = NostrUrlDecoded::from_str(remote_url) {
288 for c in nostr_url_decoded.coordinates { 299 repo_coordinates.insert(nostr_url_decoded.coordinate);
289 repo_coordinates.insert(c);
290 }
291 } 300 }
292 } 301 }
293 } 302 }