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/client.rs118
1 files changed, 87 insertions, 31 deletions
diff --git a/src/client.rs b/src/client.rs
index 5e9ec86..835d69e 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -38,7 +38,7 @@ use crate::{
38 repo_ref::{RepoRef, REPO_REF_KIND}, 38 repo_ref::{RepoRef, REPO_REF_KIND},
39 sub_commands::{ 39 sub_commands::{
40 list::status_kinds, 40 list::status_kinds,
41 send::{event_is_patch_set_root, PATCH_KIND}, 41 send::{event_is_patch_set_root, event_is_revision_root, PATCH_KIND},
42 }, 42 },
43}; 43};
44 44
@@ -419,7 +419,7 @@ impl Connect for Client {
419 fresh_coordinates.insert(c); 419 fresh_coordinates.insert(c);
420 } 420 }
421 let mut fresh_proposal_roots = request.proposals.clone(); 421 let mut fresh_proposal_roots = request.proposals.clone();
422 let mut fresh_authors = request.contributor_profiles.clone(); 422 let mut fresh_contributors = request.missing_contributor_profiles.clone();
423 423
424 let mut report = FetchReport::default(); 424 let mut report = FetchReport::default();
425 425
@@ -435,8 +435,11 @@ impl Connect for Client {
435 let dim = Style::new().color256(247); 435 let dim = Style::new().color256(247);
436 436
437 loop { 437 loop {
438 let filters = 438 let filters = get_fetch_filters(
439 get_fetch_filters(&fresh_coordinates, &fresh_proposal_roots, &fresh_authors); 439 &fresh_coordinates,
440 &fresh_proposal_roots,
441 &fresh_contributors,
442 );
440 443
441 if let Some(pb) = &pb { 444 if let Some(pb) = &pb {
442 pb.set_prefix( 445 pb.set_prefix(
@@ -455,7 +458,7 @@ impl Connect for Client {
455 458
456 fresh_coordinates = HashSet::new(); 459 fresh_coordinates = HashSet::new();
457 fresh_proposal_roots = HashSet::new(); 460 fresh_proposal_roots = HashSet::new();
458 fresh_authors = HashSet::new(); 461 fresh_contributors = HashSet::new();
459 462
460 let relay = self.client.relay(&relay_url).await?; 463 let relay = self.client.relay(&relay_url).await?;
461 let events: Vec<nostr::Event> = get_events_of(&relay, filters, &None).await?; 464 let events: Vec<nostr::Event> = get_events_of(&relay, filters, &None).await?;
@@ -467,6 +470,7 @@ impl Connect for Client {
467 git_repo_path, 470 git_repo_path,
468 &mut fresh_coordinates, 471 &mut fresh_coordinates,
469 &mut fresh_proposal_roots, 472 &mut fresh_proposal_roots,
473 &mut fresh_contributors,
470 &mut report, 474 &mut report,
471 ) 475 )
472 .await?; 476 .await?;
@@ -749,6 +753,7 @@ pub async fn get_repo_ref_from_cache(
749 }) 753 })
750} 754}
751 755
756#[allow(clippy::too_many_lines)]
752async fn create_relays_request( 757async fn create_relays_request(
753 git_repo_path: &Path, 758 git_repo_path: &Path,
754 repo_coordinates: &HashSet<Coordinate>, 759 repo_coordinates: &HashSet<Coordinate>,
@@ -793,29 +798,61 @@ async fn create_relays_request(
793 repo_coordinates.clone() 798 repo_coordinates.clone()
794 }; 799 };
795 800
796 let proposals: HashSet<EventId> = get_local_cache_database(git_repo_path) 801 let mut proposals: HashSet<EventId> = HashSet::new();
797 .await? 802 let mut missing_contributor_profiles: HashSet<PublicKey> = HashSet::new();
798 .negentropy_items( 803 let mut contributors: HashSet<PublicKey> = HashSet::new();
799 nostr::Filter::default() 804
800 .kinds(vec![Kind::Custom(PATCH_KIND)]) 805 {
801 .custom_tag( 806 if let Ok(repo_ref) = &repo_ref {
802 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 807 for m in &repo_ref.maintainers {
803 repo_coordinates 808 contributors.insert(m.to_owned());
804 .iter() 809 }
805 .map(std::string::ToString::to_string) 810 }
806 .collect::<Vec<String>>(), 811
807 ), 812 for event in &get_event_from_cache(
813 git_repo_path,
814 vec![
815 nostr::Filter::default()
816 .kinds(vec![Kind::Custom(PATCH_KIND)])
817 .custom_tag(
818 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
819 repo_coordinates
820 .iter()
821 .map(std::string::ToString::to_string)
822 .collect::<Vec<String>>(),
823 ),
824 ],
808 ) 825 )
809 .await? 826 .await?
810 .iter() 827 {
811 .map(|(id, _)| *id) 828 if event_is_patch_set_root(event) || event_is_revision_root(event) {
812 .collect(); 829 proposals.insert(event.id());
830 contributors.insert(event.author());
831 }
832 }
813 833
814 let contributor_profiles = HashSet::new(); 834 let profile_events = get_event_from_global_cache(
835 git_repo_path,
836 vec![get_filter_contributor_profiles(contributors.clone())],
837 )
838 .await?;
839 for c in &contributors {
840 if let Some(event) = profile_events
841 .iter()
842 .find(|e| e.kind() == Kind::Metadata && e.author().eq(c))
843 {
844 save_event_in_cache(git_repo_path, event).await?;
845 } else {
846 missing_contributor_profiles.insert(c.to_owned());
847 }
848 }
849 }
815 850
816 let existing_events: HashSet<EventId> = { 851 let existing_events: HashSet<EventId> = {
817 let mut existing_events: HashSet<EventId> = HashSet::new(); 852 let mut existing_events: HashSet<EventId> = HashSet::new();
818 for filter in get_fetch_filters(&repo_coordinates, &proposals, &contributor_profiles) { 853 for filter in
854 get_fetch_filters(&repo_coordinates, &proposals, &missing_contributor_profiles)
855 {
819 for (id, _) in get_local_cache_database(git_repo_path) 856 for (id, _) in get_local_cache_database(git_repo_path)
820 .await? 857 .await?
821 .negentropy_items(filter) 858 .negentropy_items(filter)
@@ -836,7 +873,8 @@ async fn create_relays_request(
836 repo_coordinates.iter().map(|c| (c.clone(), None)).collect() 873 repo_coordinates.iter().map(|c| (c.clone(), None)).collect()
837 }, 874 },
838 proposals, 875 proposals,
839 contributor_profiles, 876 contributors,
877 missing_contributor_profiles,
840 existing_events, 878 existing_events,
841 }) 879 })
842} 880}
@@ -847,6 +885,7 @@ async fn process_fetched_events(
847 git_repo_path: &Path, 885 git_repo_path: &Path,
848 fresh_coordinates: &mut HashSet<Coordinate>, 886 fresh_coordinates: &mut HashSet<Coordinate>,
849 fresh_proposal_roots: &mut HashSet<EventId>, 887 fresh_proposal_roots: &mut HashSet<EventId>,
888 fresh_contributors: &mut HashSet<PublicKey>,
850 report: &mut FetchReport, 889 report: &mut FetchReport,
851) -> Result<()> { 890) -> Result<()> {
852 for event in &events { 891 for event in &events {
@@ -896,14 +935,25 @@ async fn process_fetched_events(
896 identifier: repo_ref.identifier.clone(), 935 identifier: repo_ref.identifier.clone(),
897 relays: vec![], 936 relays: vec![],
898 }); 937 });
938 if !request.contributors.contains(m) && !fresh_contributors.contains(m)
939 {
940 fresh_contributors.insert(m.to_owned());
941 }
899 } 942 }
900 } 943 }
901 } 944 }
902 } else if event_is_patch_set_root(event) { 945 } else if event_is_patch_set_root(event) {
903 fresh_proposal_roots.insert(event.id); 946 fresh_proposal_roots.insert(event.id);
904 report.proposals.insert(event.id); 947 report.proposals.insert(event.id);
905 } else if event.kind().eq(&nostr_sdk::Kind::Metadata) { 948 if !request.contributors.contains(&event.author())
906 report.contributor_profiles.insert(event.author()); 949 && !fresh_contributors.contains(&event.author())
950 {
951 fresh_contributors.insert(event.author());
952 }
953 } else if [Kind::RelayList, Kind::Metadata].contains(&event.kind()) {
954 if Kind::Metadata.eq(&event.kind()) {
955 report.contributor_profiles.insert(event.author());
956 }
907 save_event_in_global_cache(git_repo_path, event).await?; 957 save_event_in_global_cache(git_repo_path, event).await?;
908 } 958 }
909 } 959 }
@@ -953,6 +1003,9 @@ fn consolidate_fetch_reports(reports: Vec<Result<FetchReport>>) -> FetchReport {
953 for c in relay_report.statuses { 1003 for c in relay_report.statuses {
954 report.statuses.insert(c); 1004 report.statuses.insert(c);
955 } 1005 }
1006 for c in relay_report.contributor_profiles {
1007 report.contributor_profiles.insert(c);
1008 }
956 } 1009 }
957 report 1010 report
958} 1011}
@@ -994,11 +1047,7 @@ pub fn get_fetch_filters(
994 if required_profiles.is_empty() { 1047 if required_profiles.is_empty() {
995 vec![] 1048 vec![]
996 } else { 1049 } else {
997 vec![ 1050 vec![get_filter_contributor_profiles(required_profiles.clone())]
998 nostr::Filter::default()
999 .kinds(vec![Kind::Metadata, Kind::RelayList])
1000 .authors(required_profiles.clone()),
1001 ]
1002 }, 1051 },
1003 ] 1052 ]
1004 .concat() 1053 .concat()
@@ -1021,6 +1070,12 @@ pub fn get_filter_repo_events(repo_coordinates: &HashSet<Coordinate>) -> nostr::
1021 ) 1070 )
1022} 1071}
1023 1072
1073pub fn get_filter_contributor_profiles(contributors: HashSet<PublicKey>) -> nostr::Filter {
1074 nostr::Filter::default()
1075 .kinds(vec![Kind::Metadata, Kind::RelayList])
1076 .authors(contributors)
1077}
1078
1024#[derive(Default)] 1079#[derive(Default)]
1025pub struct FetchReport { 1080pub struct FetchReport {
1026 repo_coordinates: Vec<Coordinate>, 1081 repo_coordinates: Vec<Coordinate>,
@@ -1101,6 +1156,7 @@ pub struct FetchRequest {
1101 relay_column_width: usize, 1156 relay_column_width: usize,
1102 repo_coordinates: Vec<(Coordinate, Option<Timestamp>)>, 1157 repo_coordinates: Vec<(Coordinate, Option<Timestamp>)>,
1103 proposals: HashSet<EventId>, 1158 proposals: HashSet<EventId>,
1104 contributor_profiles: HashSet<PublicKey>, 1159 contributors: HashSet<PublicKey>,
1160 missing_contributor_profiles: HashSet<PublicKey>,
1105 existing_events: HashSet<EventId>, 1161 existing_events: HashSet<EventId>,
1106} 1162}