From f4e1df4c718a3755ffe50e99946996729f3504e9 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 22 Jul 2025 17:14:21 +0100 Subject: feat(pr): generate pr event > oversized patch but only for new proposals --- src/lib/git_events.rs | 130 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 19 deletions(-) (limited to 'src/lib/git_events.rs') diff --git a/src/lib/git_events.rs b/src/lib/git_events.rs index 09ec040..86b9641 100644 --- a/src/lib/git_events.rs +++ b/src/lib/git_events.rs @@ -1,7 +1,10 @@ use std::{str::FromStr, sync::Arc}; use anyhow::{Context, Result, bail}; -use nostr::nips::{nip01::Coordinate, nip10::Marker, nip19::Nip19}; +use nostr::{ + event::UnsignedEvent, + nips::{nip01::Coordinate, nip10::Marker, nip19::Nip19}, +}; use nostr_sdk::{ Event, EventBuilder, EventId, FromBech32, Kind, NostrSigner, PublicKey, Tag, TagKind, TagStandard, hashes::sha1::Hash as Sha1Hash, @@ -347,6 +350,111 @@ pub fn event_tag_from_nip19_or_hex( } } +pub fn generate_unsigned_pr_event( + git_repo: &Repo, + repo_ref: &RepoRef, + signing_public_key: &PublicKey, + commit: &Sha1Hash, + clone_url_hint: &[&str], + mentions: &[nostr::Tag], +) -> Result { + let title = git_repo.get_commit_message_summary(commit)?; + + let description = { + let mut description = git_repo.get_commit_message(commit)?.trim().to_string(); + if let Some(remaining_description) = description.strip_prefix(&title) { + description = remaining_description.trim().to_string(); + } + description + }; + + let root_commit = git_repo + .get_root_commit() + .context("failed to get root commit of the repository")?; + + Ok(EventBuilder::new(KIND_PULL_REQUEST, description) + .tags( + [ + repo_ref + .maintainers + .iter() + .map(|m| { + Tag::from_standardized(TagStandard::Coordinate { + coordinate: Coordinate { + kind: nostr::Kind::GitRepoAnnouncement, + public_key: *m, + identifier: repo_ref.identifier.to_string(), + }, + relay_url: repo_ref.relays.first().cloned(), + uppercase: false, + }) + }) + .collect::>(), + mentions.to_vec(), + vec![ + Tag::from_standardized(TagStandard::Subject(title.clone())), + Tag::from_standardized(TagStandard::Reference(format!("{root_commit}"))), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("c")), + vec![format!("{commit}")], + ), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("clone")), + clone_url_hint + .iter() + .map(|s| s.to_string()) + .collect::>(), + ), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("alt")), + vec![format!("git Pull Request: {}", title.clone())], + ), + ], + if let Some(branch_name_tag) = make_branch_name_tag_from_check_out_branch(git_repo) + { + vec![branch_name_tag] + } else { + vec![] + }, + repo_ref + .maintainers + .iter() + .map(|pk| Tag::public_key(*pk)) + .collect(), + ] + .concat(), + ) + .build(*signing_public_key)) +} + +fn make_branch_name_tag_from_check_out_branch(git_repo: &Repo) -> Option { + if let Ok(branch_name) = git_repo.get_checked_out_branch_name() { + if !branch_name.eq("main") + && !branch_name.eq("master") + && !branch_name.eq("origin/main") + && !branch_name.eq("origin/master") + { + Some(Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("branch-name")), + vec![ + if let Some(branch_name) = branch_name.strip_prefix("pr/") { + branch_name.to_string() + } else { + branch_name + } + .chars() + .take(60) + .collect::(), + ], + )) + } else { + None + } + } else { + None + } +} + #[allow(clippy::too_many_lines)] pub async fn generate_cover_letter_and_patch_events( cover_letter_title_description: Option<(String, String)>, @@ -409,24 +517,8 @@ pub async fn generate_cover_letter_and_patch_events( // eventually a prefix will be needed of the event id to stop 2 proposals with the same name colliding // a change like this, or the removal of this tag will require the actual branch name to be tracked // so pulling and pushing still work - if let Ok(branch_name) = git_repo.get_checked_out_branch_name() { - if !branch_name.eq("main") - && !branch_name.eq("master") - && !branch_name.eq("origin/main") - && !branch_name.eq("origin/master") - { - vec![ - Tag::custom( - nostr::TagKind::Custom(std::borrow::Cow::Borrowed("branch-name")), - vec![if let Some(branch_name) = branch_name.strip_prefix("pr/") { - branch_name.to_string() - } else { - branch_name - }.chars().take(60).collect::()], - ), - ] - } - else { vec![] } + if let Some(branch_name_tag) = make_branch_name_tag_from_check_out_branch(git_repo) { + vec![branch_name_tag] } else { vec![] }, -- cgit v1.2.3