upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 }