upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/bin/git_remote_nostr/push.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/git_remote_nostr/push.rs')
-rw-r--r--src/bin/git_remote_nostr/push.rs94
1 files changed, 73 insertions, 21 deletions
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index 8a750ce..fc82796 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -16,7 +16,9 @@ use git2::{Oid, Repository};
16use ngit::{ 16use ngit::{
17 client::{self, get_event_from_cache_by_id}, 17 client::{self, get_event_from_cache_by_id},
18 git::{self, nostr_url::NostrUrlDecoded}, 18 git::{self, nostr_url::NostrUrlDecoded},
19 git_events::{self, KIND_PULL_REQUEST, event_to_cover_letter, get_event_root}, 19 git_events::{
20 self, KIND_PULL_REQUEST, KIND_PULL_REQUEST_UPDATE, event_to_cover_letter, get_event_root,
21 },
20 list::list_from_remotes, 22 list::list_from_remotes,
21 login::{self, user::UserRef}, 23 login::{self, user::UserRef},
22 push::{push_to_remote, select_servers_push_refs_and_generate_pr_or_pr_update_event}, 24 push::{push_to_remote, select_servers_push_refs_and_generate_pr_or_pr_update_event},
@@ -27,7 +29,11 @@ use ngit::{
27 get_short_git_server_name, read_line, 29 get_short_git_server_name, read_line,
28 }, 30 },
29}; 31};
30use nostr::nips::nip10::Marker; 32use nostr::nips::{
33 nip10::Marker,
34 nip19::ToBech32,
35 nip22::{CommentTarget, extract_root},
36};
31use nostr_sdk::{ 37use nostr_sdk::{
32 Event, EventBuilder, EventId, Kind, NostrSigner, PublicKey, RelayUrl, Tag, TagStandard, 38 Event, EventBuilder, EventId, Kind, NostrSigner, PublicKey, RelayUrl, Tag, TagStandard,
33 hashes::sha1::Hash as Sha1Hash, 39 hashes::sha1::Hash as Sha1Hash,
@@ -914,6 +920,8 @@ async fn get_merged_status_events(
914 git_repo.get_path()?, 920 git_repo.get_path()?,
915 vec![ 921 vec![
916 nostr::Filter::default().kind(nostr::Kind::GitPatch), 922 nostr::Filter::default().kind(nostr::Kind::GitPatch),
923 nostr::Filter::default().kind(KIND_PULL_REQUEST),
924 nostr::Filter::default().kind(KIND_PULL_REQUEST_UPDATE),
917 // TODO: limit by repo_ref 925 // TODO: limit by repo_ref
918 ], 926 ],
919 ) 927 )
@@ -940,7 +948,7 @@ type MergedProposalsInfo =
940async fn get_merged_proposals_info( 948async fn get_merged_proposals_info(
941 git_repo: &Repo, 949 git_repo: &Repo,
942 ahead: &Vec<Sha1Hash>, 950 ahead: &Vec<Sha1Hash>,
943 available_patches_pr_pr_update: &[Event], 951 available_patches_prs_pr_updates: &[Event],
944) -> Result<MergedProposalsInfo> { 952) -> Result<MergedProposalsInfo> {
945 let mut proposals: MergedProposalsInfo = HashMap::new(); 953 let mut proposals: MergedProposalsInfo = HashMap::new();
946 954
@@ -950,7 +958,7 @@ async fn get_merged_proposals_info(
950 // are in ahead 958 // are in ahead
951 if commit.parent_count() > 1 { 959 if commit.parent_count() > 1 {
952 for parent in commit.parents() { 960 for parent in commit.parents() {
953 for event in available_patches_pr_pr_update 961 for event in available_patches_prs_pr_updates
954 .iter() 962 .iter()
955 .filter(|e| { 963 .filter(|e| {
956 e.tags.iter().any(|t| { 964 e.tags.iter().any(|t| {
@@ -962,7 +970,10 @@ async fn get_merged_proposals_info(
962 .collect::<Vec<&Event>>() 970 .collect::<Vec<&Event>>()
963 { 971 {
964 if let Ok((proposal_id, revision_id)) = 972 if let Ok((proposal_id, revision_id)) =
965 get_proposal_and_revision_root_from_patch(git_repo, event).await 973 get_proposal_and_revision_root_from_patch_or_pr_or_pr_update(
974 git_repo, event,
975 )
976 .await
966 { 977 {
967 let (entry_revision_id, merged_patches) = 978 let (entry_revision_id, merged_patches) =
968 proposals.entry(proposal_id).or_default(); 979 proposals.entry(proposal_id).or_default();
@@ -975,7 +986,7 @@ async fn get_merged_proposals_info(
975 } else { 986 } else {
976 // three way merge or fast forward merge commits 987 // three way merge or fast forward merge commits
977 // note: ahead included commits of three-way merged branches 988 // note: ahead included commits of three-way merged branches
978 let mut matching_patches = available_patches_pr_pr_update 989 let mut matching_patches_prs_pr_updates = available_patches_prs_pr_updates
979 .iter() 990 .iter()
980 .filter(|e| { 991 .filter(|e| {
981 e.tags.iter().any(|t| { 992 e.tags.iter().any(|t| {
@@ -985,15 +996,19 @@ async fn get_merged_proposals_info(
985 }) 996 })
986 }) 997 })
987 .collect::<Vec<&Event>>(); 998 .collect::<Vec<&Event>>();
988 for patch_event in &matching_patches { 999 for patch_event in &matching_patches_prs_pr_updates {
989 if let Ok((proposal_id, revision_id)) = 1000 if let Ok((proposal_id, revision_id)) =
990 get_proposal_and_revision_root_from_patch(git_repo, patch_event).await 1001 get_proposal_and_revision_root_from_patch_or_pr_or_pr_update(
1002 git_repo,
1003 patch_event,
1004 )
1005 .await
991 { 1006 {
992 let (entry_revision_id, merged_patches) = 1007 let (entry_revision_id, merged_patches_pr_pr_updates) =
993 proposals.entry(proposal_id).or_default(); 1008 proposals.entry(proposal_id).or_default();
994 // ignore revisions without all the merged commits 1009 // ignore revisions without all the merged commits
995 if entry_revision_id == &revision_id { 1010 if entry_revision_id == &revision_id {
996 merged_patches.insert( 1011 merged_patches_pr_pr_updates.insert(
997 *commit_hash, 1012 *commit_hash,
998 MergedPRCommitType::PatchCommit { 1013 MergedPRCommitType::PatchCommit {
999 event_id: patch_event.id, 1014 event_id: patch_event.id,
@@ -1003,9 +1018,9 @@ async fn get_merged_proposals_info(
1003 } 1018 }
1004 } 1019 }
1005 // applied commits - this is done after so that merged revisions take priority 1020 // applied commits - this is done after so that merged revisions take priority
1006 if matching_patches.is_empty() { 1021 if matching_patches_prs_pr_updates.is_empty() {
1007 let author = git_repo.get_commit_author(commit_hash)?; 1022 let author = git_repo.get_commit_author(commit_hash)?;
1008 matching_patches = available_patches_pr_pr_update 1023 matching_patches_prs_pr_updates = available_patches_prs_pr_updates
1009 .iter() 1024 .iter()
1010 .filter(|e| { 1025 .filter(|e| {
1011 if let Ok(patch_author) = get_patch_author(e) { 1026 if let Ok(patch_author) = get_patch_author(e) {
@@ -1015,9 +1030,13 @@ async fn get_merged_proposals_info(
1015 } 1030 }
1016 }) 1031 })
1017 .collect::<Vec<&Event>>(); 1032 .collect::<Vec<&Event>>();
1018 for patch_event in matching_patches { 1033 for patch_event in matching_patches_prs_pr_updates {
1019 if let Ok((proposal_id, revision_id)) = 1034 if let Ok((proposal_id, revision_id)) =
1020 get_proposal_and_revision_root_from_patch(git_repo, patch_event).await 1035 get_proposal_and_revision_root_from_patch_or_pr_or_pr_update(
1036 git_repo,
1037 patch_event,
1038 )
1039 .await
1021 { 1040 {
1022 let (entry_revision_id, merged_patches) = 1041 let (entry_revision_id, merged_patches) =
1023 proposals.entry(proposal_id).or_default(); 1042 proposals.entry(proposal_id).or_default();
@@ -1250,24 +1269,57 @@ async fn create_merge_status(
1250 .await 1269 .await
1251} 1270}
1252 1271
1253async fn get_proposal_and_revision_root_from_patch( 1272async fn get_proposal_and_revision_root_from_patch_or_pr_or_pr_update(
1254 git_repo: &Repo, 1273 git_repo: &Repo,
1255 patch: &Event, 1274 event: &Event,
1256) -> Result<(EventId, Option<EventId>)> { 1275) -> Result<(EventId, Option<EventId>)> {
1257 let proposal_or_revision = if patch 1276 if event.kind.eq(&KIND_PULL_REQUEST) {
1277 return Ok((event.id, None));
1278 } else if event.kind.eq(&KIND_PULL_REQUEST_UPDATE) {
1279 if let Some(root) = extract_root(event) {
1280 if let CommentTarget::Event {
1281 id,
1282 relay_hint: _,
1283 pubkey_hint: _,
1284 kind,
1285 } = root
1286 {
1287 if let Some(kind) = kind {
1288 if !kind.eq(&KIND_PULL_REQUEST) {
1289 bail!(
1290 "pull request update {} root event is {} and not a pull request kind",
1291 { event.id.to_bech32()? },
1292 kind
1293 );
1294 }
1295 }
1296 return Ok((*id, None));
1297 }
1298 bail!(
1299 "pull request update {} root event is not a pull request event",
1300 event.id.to_bech32()?
1301 );
1302 }
1303 bail!(
1304 "pull request update {} root event is not a pull request event",
1305 { event.id.to_bech32()? }
1306 );
1307 }
1308
1309 let proposal_or_revision = if event
1258 .tags 1310 .tags
1259 .iter() 1311 .iter()
1260 .any(|t| t.as_slice().len() > 1 && t.as_slice()[1].eq("root")) 1312 .any(|t| t.as_slice().len() > 1 && t.as_slice()[1].eq("root"))
1261 { 1313 {
1262 patch.clone() 1314 event.clone()
1263 } else { 1315 } else {
1264 let proposal_or_revision_id = EventId::parse( 1316 let proposal_or_revision_id = EventId::parse(
1265 &if let Some(t) = patch.tags.iter().find(|t| t.is_root()) { 1317 &if let Some(t) = event.tags.iter().find(|t| t.is_root()) {
1266 t.clone() 1318 t.clone()
1267 } else if let Some(t) = patch.tags.iter().find(|t| t.is_reply()) { 1319 } else if let Some(t) = event.tags.iter().find(|t| t.is_reply()) {
1268 t.clone() 1320 t.clone()
1269 } else { 1321 } else {
1270 Tag::event(patch.id) 1322 Tag::event(event.id)
1271 } 1323 }
1272 .as_slice()[1] 1324 .as_slice()[1]
1273 .clone(), 1325 .clone(),