diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/git_remote_nostr/push.rs | 94 |
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}; | |||
| 16 | use ngit::{ | 16 | use 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 | }; |
| 30 | use nostr::nips::nip10::Marker; | 32 | use nostr::nips::{ |
| 33 | nip10::Marker, | ||
| 34 | nip19::ToBech32, | ||
| 35 | nip22::{CommentTarget, extract_root}, | ||
| 36 | }; | ||
| 31 | use nostr_sdk::{ | 37 | use 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 = | |||
| 940 | async fn get_merged_proposals_info( | 948 | async 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 | ||
| 1253 | async fn get_proposal_and_revision_root_from_patch( | 1272 | async 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(), |