diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-07-16 17:09:43 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-07-16 17:09:43 +0100 |
| commit | 65d5daf6e42683ef116369b4f6a0f99d6971667b (patch) | |
| tree | 4455b2e67a964ed07cc36e667098239a40f6fe5a /src/client.rs | |
| parent | 3d939fc3c661995ed7500b09584ab98e28134341 (diff) | |
feat(fetch): get contributor profiles
just from repository / fallback relays and only if we don't already
have a version in cache
this is because we are only using it for the user's name
Diffstat (limited to 'src/client.rs')
| -rw-r--r-- | src/client.rs | 118 |
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)] | ||
| 752 | async fn create_relays_request( | 757 | async 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 | ||
| 1073 | pub 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)] |
| 1025 | pub struct FetchReport { | 1080 | pub 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 | } |