From f1b3fcc40ab666d8def97096d1942c274da9b279 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 11 Jun 2024 16:21:44 +0100 Subject: chore: bump rust-nostr to v0.32.0 both nostr and nostr-sdk packages and also in test_utils fix the many breaking changes fix: ignore trailing slash when depuplicate relays for send events. this was picked up as TagStandard::RelayMetadata has started adding a traling slash. refactor cli output test function `expect_send_with_progress` so that relays can succeed / fail in a random order --- src/git.rs | 4 +- src/key_handling/users.rs | 48 ++++--- src/repo_ref.rs | 47 ++++--- src/sub_commands/list.rs | 2 +- src/sub_commands/send.rs | 338 ++++++++++++++++++++-------------------------- 5 files changed, 203 insertions(+), 236 deletions(-) (limited to 'src') diff --git a/src/git.rs b/src/git.rs index e797cb8..fb3b353 100644 --- a/src/git.rs +++ b/src/git.rs @@ -948,8 +948,8 @@ mod tests { fn test(time: git2::Time) -> Result<()> { assert_eq!( extract_sig_from_patch_tags( - &[nostr::Tag::Generic( - nostr::TagKind::Custom("author".to_string()), + &[nostr::Tag::custom( + nostr::TagKind::Custom("author".to_string().into()), prep(&time)?, )], "author", diff --git a/src/key_handling/users.rs b/src/key_handling/users.rs index 1dd75a8..a79a977 100644 --- a/src/key_handling/users.rs +++ b/src/key_handling/users.rs @@ -567,15 +567,18 @@ mod tests { nostr::Kind::RelayList, "", [ - nostr::Tag::RelayMetadata( - "wss://fredswrite1.relay".into(), - Some(nostr::RelayMetadata::Write), - ), - nostr::Tag::RelayMetadata( - "wss://fredsread1.relay".into(), - Some(nostr::RelayMetadata::Read), - ), - nostr::Tag::RelayMetadata("wss://fredsreadwrite.relay".into(), None), + nostr::Tag::from_standardized(nostr::TagStandard::RelayMetadata { + relay_url: nostr::Url::from_str("wss://fredswrite1.relay/").unwrap(), + metadata: Some(RelayMetadata::Write), + }), + nostr::Tag::from_standardized(nostr::TagStandard::RelayMetadata { + relay_url: nostr::Url::from_str("wss://fredsread1.relay/").unwrap(), + metadata: Some(RelayMetadata::Read), + }), + nostr::Tag::from_standardized(nostr::TagStandard::RelayMetadata { + relay_url: nostr::Url::from_str("wss://fredsreadwrite.relay/").unwrap(), + metadata: None, + }), ], ) .to_event(&TEST_KEY_1_KEYS) @@ -587,15 +590,18 @@ mod tests { nostr::Kind::RelayList, "", [ - nostr::Tag::RelayMetadata( - "wss://carolswrite1.relay".into(), - Some(nostr::RelayMetadata::Write), - ), - nostr::Tag::RelayMetadata( - "wss://carolsread1.relay".into(), - Some(nostr::RelayMetadata::Read), - ), - nostr::Tag::RelayMetadata("wss://carolsreadwrite.relay".into(), None), + nostr::Tag::from_standardized(nostr::TagStandard::RelayMetadata { + relay_url: nostr::Url::from_str("wss://carolswrite1.relay/").unwrap(), + metadata: Some(RelayMetadata::Write), + }), + nostr::Tag::from_standardized(nostr::TagStandard::RelayMetadata { + relay_url: nostr::Url::from_str("wss://carolsread1.relay/").unwrap(), + metadata: Some(RelayMetadata::Read), + }), + nostr::Tag::from_standardized(nostr::TagStandard::RelayMetadata { + relay_url: nostr::Url::from_str("wss://carolsreadwrite.relay/").unwrap(), + metadata: None, + }), ], ) .to_event(&TEST_KEY_2_KEYS) @@ -652,7 +658,7 @@ mod tests { fn expected_userrelayrefs_write1() -> UserRelayRef { UserRelayRef { - url: "wss://fredswrite1.relay".into(), + url: "wss://fredswrite1.relay/".into(), read: false, write: true, } @@ -661,7 +667,7 @@ mod tests { fn expected_userrelayrefs_read_write1() -> UserRelayRef { UserRelayRef { - url: "wss://fredsreadwrite.relay".into(), + url: "wss://fredsreadwrite.relay/".into(), read: true, write: true, } @@ -672,7 +678,7 @@ mod tests { vec![ expected_userrelayrefs_write1(), UserRelayRef { - url: "wss://fredsread1.relay".into(), + url: "wss://fredsread1.relay/".into(), read: true, write: false, }, diff --git a/src/repo_ref.rs b/src/repo_ref.rs index d314e6d..9fb1f0c 100644 --- a/src/repo_ref.rs +++ b/src/repo_ref.rs @@ -1,7 +1,7 @@ use std::{fs::File, io::BufReader, str::FromStr}; use anyhow::{bail, Context, Result}; -use nostr::{nips::nip19::Nip19, FromBech32, PublicKey, Tag, ToBech32}; +use nostr::{nips::nip19::Nip19, FromBech32, PublicKey, Tag, TagStandard, ToBech32}; use serde::{Deserialize, Serialize}; #[cfg(not(test))] @@ -31,7 +31,7 @@ impl TryFrom for RepoRef { type Error = anyhow::Error; fn try_from(event: nostr::Event) -> Result { - if !event.kind.as_u64().eq(&REPO_REF_KIND) { + if !event.kind.as_u16().eq(&REPO_REF_KIND) { bail!("incorrect kind"); } let mut r = Self::default(); @@ -49,12 +49,12 @@ impl TryFrom for RepoRef { } if let Some(t) = event.tags.iter().find(|t| t.as_vec()[0].eq("clone")) { - r.git_server = t.as_vec().clone(); + r.git_server = t.clone().to_vec(); r.git_server.remove(0); } if let Some(t) = event.tags.iter().find(|t| t.as_vec()[0].eq("web")) { - r.web = t.as_vec().clone(); + r.web = t.clone().to_vec(); r.web.remove(0); } @@ -67,12 +67,12 @@ impl TryFrom for RepoRef { } if let Some(t) = event.tags.iter().find(|t| t.as_vec()[0].eq("relays")) { - r.relays = t.as_vec().clone(); + r.relays = t.clone().to_vec(); r.relays.remove(0); } if let Some(t) = event.tags.iter().find(|t| t.as_vec()[0].eq("maintainers")) { - let mut maintainers = t.as_vec().clone(); + let mut maintainers = t.clone().to_vec(); maintainers.remove(0); if !maintainers.contains(&event.pubkey.to_string()) { r.maintainers.push(event.pubkey); @@ -90,7 +90,7 @@ impl TryFrom for RepoRef { } } -pub static REPO_REF_KIND: u64 = 30_617; +pub static REPO_REF_KIND: u16 = 30_617; impl RepoRef { pub fn to_event(&self, keys: &nostr::Keys) -> Result { @@ -99,7 +99,7 @@ impl RepoRef { "", [ vec![ - Tag::Identifier(if self.identifier.to_string().is_empty() { + Tag::identifier(if self.identifier.to_string().is_empty() { // fiatjaf thought a random string. its not in the draft nip. // thread_rng() // .sample_iter(&Alphanumeric) @@ -117,27 +117,30 @@ impl RepoRef { } else { self.identifier.to_string() }), - Tag::Reference(self.root_commit.to_string()), - Tag::Name(self.name.clone()), - Tag::Description(self.description.clone()), - Tag::Generic( - nostr::TagKind::Custom("clone".to_string()), + Tag::from_standardized(TagStandard::Reference(self.root_commit.to_string())), + Tag::from_standardized(TagStandard::Name(self.name.clone())), + Tag::from_standardized(TagStandard::Description(self.description.clone())), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("clone")), self.git_server.clone(), ), - Tag::Generic(nostr::TagKind::Custom("web".to_string()), self.web.clone()), - Tag::Generic( - nostr::TagKind::Custom("relays".to_string()), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("web")), + self.web.clone(), + ), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("relays")), self.relays.clone(), ), - Tag::Generic( - nostr::TagKind::Custom("maintainers".to_string()), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("maintainers")), self.maintainers .iter() .map(std::string::ToString::to_string) - .collect(), + .collect::>(), ), - Tag::Generic( - nostr::TagKind::Custom("alt".to_string()), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("alt")), vec![format!("git repository: {}", self.name.clone())], ), ], @@ -188,7 +191,7 @@ pub async fn fetch( // somewhere within .git folder for future use and seek to get that next time if let Some(event) = events .iter() - .filter(|e| e.kind.as_u64() == REPO_REF_KIND) + .filter(|e| e.kind.as_u16() == REPO_REF_KIND) .max_by_key(|e| e.created_at) { break event.clone(); diff --git a/src/sub_commands/list.rs b/src/sub_commands/list.rs index 1a30b9b..24979fe 100644 --- a/src/sub_commands/list.rs +++ b/src/sub_commands/list.rs @@ -801,7 +801,7 @@ pub async fn find_commits_for_proposal_root_events( .context("cannot fetch patch events")? .iter() .filter(|e| { - e.kind.as_u64() == PATCH_KIND + e.kind.as_u16() == PATCH_KIND && e.tags.iter().any(|t| { t.as_vec().len() > 2 && proposal_root_events diff --git a/src/sub_commands/send.rs b/src/sub_commands/send.rs index 189dc53..c8d900c 100644 --- a/src/sub_commands/send.rs +++ b/src/sub_commands/send.rs @@ -5,10 +5,10 @@ use console::Style; use futures::future::join_all; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use nostr::{ - nips::{nip01::Coordinate, nip19::Nip19}, - EventBuilder, FromBech32, Marker, Tag, TagKind, ToBech32, UncheckedUrl, + nips::{nip01::Coordinate, nip10::Marker, nip19::Nip19}, + EventBuilder, FromBech32, Tag, TagKind, ToBech32, UncheckedUrl, }; -use nostr_sdk::hashes::sha1::Hash as Sha1Hash; +use nostr_sdk::{hashes::sha1::Hash as Sha1Hash, TagStandard}; use super::list::tag_value; #[cfg(not(test))] @@ -265,6 +265,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { } #[allow(clippy::module_name_repetitions)] +#[allow(clippy::too_many_lines)] pub async fn send_events( #[cfg(test)] client: &crate::client::MockConnect, #[cfg(not(test))] client: &Client, @@ -273,21 +274,41 @@ pub async fn send_events( repo_read_relays: Vec, animate: bool, ) -> Result<()> { - let (_, _, _, mut all) = unique_and_duplicate_all(&my_write_relays, &repo_read_relays); - - let mut fallback = client.get_fallback_relays().clone(); - - // blast repo events - if events.iter().any(|e| e.kind().as_u64().eq(&REPO_REF_KIND)) { - for r in client.get_blaster_relays() { - fallback.push(r.to_string()); + let fallback = [ + client.get_fallback_relays().clone(), + if events.iter().any(|e| e.kind().as_u16().eq(&REPO_REF_KIND)) { + client.get_blaster_relays().clone() + } else { + vec![] + }, + ] + .concat(); + let mut relays: Vec<&String> = vec![]; + + let all = &[ + repo_read_relays.clone(), + my_write_relays.clone(), + fallback.clone(), + ] + .concat(); + // add duplicates first + for r in &repo_read_relays { + let r_clean = remove_trailing_slash(r); + if !my_write_relays + .iter() + .filter(|x| r_clean.eq(&remove_trailing_slash(x))) + .count() + > 1 + && !relays.iter().any(|x| r_clean.eq(&remove_trailing_slash(x))) + { + relays.push(r); } } - // then remaining fallback list - for r in &fallback { - if !all.iter().any(|r2| r2.eq(&r)) { - all.push(r); + for r in all { + let r_clean = remove_trailing_slash(r); + if !relays.iter().any(|x| r_clean.eq(&remove_trailing_slash(x))) { + relays.push(r); } } @@ -319,25 +340,36 @@ pub async fn send_events( "x".to_string() })?; - join_all(all.iter().map(|&relay| async { + #[allow(clippy::borrow_deref_ref)] + join_all(relays.iter().map(|&relay| async { + let relay_clean = remove_trailing_slash(&*relay); let details = format!( "{}{}{} {}", - if my_write_relays.iter().any(|r| relay.eq(r)) { + if my_write_relays + .iter() + .any(|r| relay_clean.eq(&remove_trailing_slash(r))) + { " [my-relay]" } else { "" }, - if repo_read_relays.iter().any(|r| relay.eq(r)) { + if repo_read_relays + .iter() + .any(|r| relay_clean.eq(&remove_trailing_slash(r))) + { " [repo-relay]" } else { "" }, - if fallback.iter().any(|r| relay.eq(r)) { + if fallback + .iter() + .any(|r| relay_clean.eq(&remove_trailing_slash(r))) + { " [default]" } else { "" }, - *relay, + relay_clean, ); let pb = m.add( ProgressBar::new(events.len() as u64) @@ -378,36 +410,12 @@ pub async fn send_events( Ok(()) } -/// returns `(unique_vec1, unique_vec2, duplicates, all)` -fn unique_and_duplicate_all<'a, S>( - vec1: &'a Vec, - vec2: &'a Vec, -) -> (Vec<&'a S>, Vec<&'a S>, Vec<&'a S>, Vec<&'a S>) -where - S: PartialEq, -{ - let mut vec1_u = vec![]; - let mut vec2_u = vec![]; - let mut dup = vec![]; - let mut all = vec![]; - for s1 in vec1 { - if vec2.iter().any(|s2| s1.eq(s2)) { - dup.push(s1); - } else { - vec1_u.push(s1); - } +fn remove_trailing_slash(s: &String) -> String { + match s.as_str().strip_suffix('/') { + Some(s) => s, + None => s, } - for s2 in vec2 { - if !vec1.iter().any(|s1| s2.eq(s1)) { - vec2_u.push(s2); - } - } - for a in [&dup, &vec1_u, &vec2_u] { - for e in a { - all.push(&**e); - } - } - (vec1_u, vec2_u, dup, all) + .to_string() } fn choose_commits(git_repo: &Repo, proposed_commits: Vec) -> Result> { @@ -501,53 +509,6 @@ fn summarise_commit_for_selection(git_repo: &Repo, commit: &Sha1Hash) -> Result< )) } -mod tests_unique_and_duplicate { - - #[test] - fn correct_number_of_unique_and_duplicate_items() { - let v1 = vec![ - "t1".to_string(), - "t2".to_string(), - "t3".to_string(), - "t4".to_string(), - "t5".to_string(), - ]; - let v2 = vec![ - "t3".to_string(), - "t4".to_string(), - "t5".to_string(), - "t6".to_string(), - ]; - - let (v1_u, v2_u, d, a) = super::unique_and_duplicate_all(&v1, &v2); - - assert_eq!(v1_u.len(), 2); - assert_eq!(v2_u.len(), 1); - assert_eq!(d.len(), 3); - assert_eq!(a.len(), 6); - } - #[test] - fn all_begins_with_duplicates() { - let v1 = vec![ - "t1".to_string(), - "t2".to_string(), - "t3".to_string(), - "t4".to_string(), - "t5".to_string(), - ]; - let v2 = vec![ - "t3".to_string(), - "t4".to_string(), - "t5".to_string(), - "t6".to_string(), - ]; - - let (_, _, d, a) = super::unique_and_duplicate_all(&v1, &v2); - - assert_eq!(a[0], d[0]); - } -} - async fn get_root_proposal_id_and_mentions_from_in_reply_to( #[cfg(test)] client: &crate::client::MockConnect, #[cfg(not(test))] client: &Client, @@ -555,20 +516,23 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to( in_reply_to: &[String], ) -> Result<(Option, Vec)> { let root_proposal_id = if let Some(first) = in_reply_to.first() { - match event_tag_from_nip19_or_hex(first, "in-reply-to", nostr::Marker::Root, true, false)? { - Tag::Event { + match event_tag_from_nip19_or_hex(first, "in-reply-to", Marker::Root, true, false)? + .as_standardized() + { + Some(nostr_sdk::TagStandard::Event { event_id, relay_url: _, marker: _, - } => { + public_key: _, + }) => { let events = client .get_events( repo_relays.to_vec(), - vec![nostr::Filter::new().id(event_id)], + vec![nostr::Filter::new().id(*event_id)], ) .await .context("whilst getting events specified in --in-reply-to")?; - if let Some(first) = events.iter().find(|e| e.id.eq(&event_id)) { + if let Some(first) = events.iter().find(|e| e.id.eq(event_id)) { if event_is_patch_set_root(first) { Some(event_id.to_string()) } else { @@ -591,16 +555,10 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to( for (i, reply_to) in in_reply_to.iter().enumerate() { if i.ne(&0) || root_proposal_id.is_none() { mention_tags.push( - event_tag_from_nip19_or_hex( - reply_to, - "in-reply-to", - nostr::Marker::Mention, - true, - false, - ) - .context(format!( - "{reply_to} in 'in-reply-to' not a valid nostr reference" - ))?, + event_tag_from_nip19_or_hex(reply_to, "in-reply-to", Marker::Mention, true, false) + .context(format!( + "{reply_to} in 'in-reply-to' not a valid nostr reference" + ))?, ); } } @@ -608,7 +566,7 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to( Ok((root_proposal_id, mention_tags)) } -pub static PATCH_KIND: u64 = 1617; +pub static PATCH_KIND: u16 = 1617; #[allow(clippy::too_many_lines)] pub fn generate_cover_letter_and_patch_events( @@ -637,33 +595,30 @@ pub fn generate_cover_letter_and_patch_events( [ vec![ // TODO: why not tag all maintainer identifiers? - Tag::A { - coordinate: Coordinate { - kind: nostr::Kind::Custom(REPO_REF_KIND), - public_key: *repo_ref.maintainers.first() - .context("repo reference should always have at least one maintainer")?, - identifier: repo_ref.identifier.to_string(), - relays: repo_ref.relays.clone(), - }, - relay_url: repo_ref.relays.first().map(nostr::UncheckedUrl::from).clone(), - }, - Tag::Reference(format!("{root_commit}")), - Tag::Hashtag("cover-letter".to_string()), - Tag::Generic( - nostr::TagKind::Custom("alt".to_string()), + Tag::coordinate(Coordinate { + kind: nostr::Kind::Custom(REPO_REF_KIND), + public_key: *repo_ref.maintainers.first() + .context("repo reference should always have at least one maintainer")?, + identifier: repo_ref.identifier.to_string(), + relays: repo_ref.relays.clone(), + }), + Tag::from_standardized(TagStandard::Reference(format!("{root_commit}"))), + Tag::hashtag("cover-letter"), + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("alt")), vec![format!("git patch cover letter: {}", title.clone())], ), ], if let Some(event_ref) = root_proposal_id.clone() { vec![ - Tag::Hashtag("root".to_string()), - Tag::Hashtag("revision-root".to_string()), + Tag::hashtag("root"), + Tag::hashtag("revision-root"), // TODO check if id is for a root proposal (perhaps its for an issue?) - event_tag_from_nip19_or_hex(&event_ref,"proposal",nostr::Marker::Reply, false, false)?, + event_tag_from_nip19_or_hex(&event_ref,"proposal",Marker::Reply, false, false)?, ] } else { vec![ - Tag::Hashtag("root".to_string()), + Tag::hashtag("root"), ] }, mentions.to_vec(), @@ -677,10 +632,12 @@ pub fn generate_cover_letter_and_patch_events( && !branch_name.eq("origin/main") && !branch_name.eq("origin/master") { - vec![Tag::Generic( - TagKind::Custom("branch-name".to_string()), - vec![branch_name], - )] + vec![ + Tag::custom( + nostr::TagKind::Custom(std::borrow::Cow::Borrowed("branch-name")), + vec![branch_name], + ), + ] } else { vec![] } } else { @@ -740,7 +697,7 @@ pub fn generate_cover_letter_and_patch_events( fn event_tag_from_nip19_or_hex( reference: &str, reference_name: &str, - marker: nostr::Marker, + marker: Marker, allow_npub_reference: bool, prompt_for_correction: bool, ) -> Result { @@ -754,44 +711,44 @@ fn event_tag_from_nip19_or_hex( if let Ok(nip19) = Nip19::from_bech32(bech32.clone()) { match nip19 { Nip19::Event(n) => { - break Ok(nostr::Tag::Event { + break Ok(Tag::from_standardized(nostr_sdk::TagStandard::Event { event_id: n.event_id, relay_url: n.relays.first().map(UncheckedUrl::new), marker: Some(marker), - }); + public_key: None, + })); } Nip19::EventId(id) => { - break Ok(nostr::Tag::Event { + break Ok(Tag::from_standardized(nostr_sdk::TagStandard::Event { event_id: id, relay_url: None, marker: Some(marker), - }); + public_key: None, + })); } Nip19::Coordinate(coordinate) => { - break Ok(nostr::Tag::A { - coordinate, - relay_url: None, - }); + break Ok(Tag::coordinate(coordinate)); } Nip19::Profile(profile) => { if allow_npub_reference { - break Ok(nostr::Tag::public_key(profile.public_key)); + break Ok(Tag::public_key(profile.public_key)); } } Nip19::Pubkey(public_key) => { if allow_npub_reference { - break Ok(nostr::Tag::public_key(public_key)); + break Ok(Tag::public_key(public_key)); } } _ => {} } } if let Ok(id) = nostr::EventId::from_str(&bech32) { - break Ok(nostr::Tag::Event { + break Ok(Tag::from_standardized(nostr_sdk::TagStandard::Event { event_id: id, relay_url: None, marker: Some(marker), - }); + public_key: None, + })); } if prompt_for_correction { println!("not a valid {reference_name} event reference"); @@ -813,7 +770,7 @@ pub fn event_is_cover_letter(event: &nostr::Event) -> bool { // TODO: look for Subject:[ PATCH 0/n ] but watch out for: // [PATCH v1 0/n ] or // [PATCH subsystem v2 0/n ] - event.kind.as_u64().eq(&PATCH_KIND) + event.kind.as_u16().eq(&PATCH_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) } @@ -883,16 +840,16 @@ pub fn event_to_cover_letter(event: &nostr::Event) -> Result { } pub fn event_is_patch_set_root(event: &nostr::Event) -> bool { - event.kind.as_u64().eq(&PATCH_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) + event.kind.as_u16().eq(&PATCH_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) } pub fn event_is_revision_root(event: &nostr::Event) -> bool { - event.kind.as_u64().eq(&PATCH_KIND) + event.kind.as_u16().eq(&PATCH_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("revision-root")) } pub fn patch_supports_commit_ids(event: &nostr::Event) -> bool { - event.kind.as_u64().eq(&PATCH_KIND) + event.kind.as_u16().eq(&PATCH_KIND) && event .iter_tags() .any(|t| t.as_vec()[0].eq("commit-pgp-sig")) @@ -925,55 +882,54 @@ pub fn generate_patch_event( .context(format!("cannot make patch for commit {commit}"))?, [ vec![ - Tag::A { - coordinate: Coordinate { - kind: nostr::Kind::Custom(REPO_REF_KIND), - public_key: *repo_ref.maintainers.first() - .context("repo reference should always have at least one maintainer - the issuer of the repo event") - ?, - identifier: repo_ref.identifier.to_string(), - relays: repo_ref.relays.clone(), - }, - relay_url: relay_hint.clone(), - }, - Tag::Reference(format!("{root_commit}")), + Tag::coordinate(Coordinate { + kind: nostr::Kind::Custom(REPO_REF_KIND), + public_key: *repo_ref.maintainers.first() + .context("repo reference should always have at least one maintainer - the issuer of the repo event") + ?, + identifier: repo_ref.identifier.to_string(), + relays: repo_ref.relays.clone(), + }), + Tag::from_standardized(TagStandard::Reference(root_commit.to_string())), // commit id reference is a trade-off. its now // unclear which one is the root commit id but it // enables easier location of code comments againt // code that makes it into the main branch, assuming // the commit id is correct - Tag::Reference(commit.to_string()), - Tag::Generic( - nostr::TagKind::Custom("alt".to_string()), + Tag::from_standardized(TagStandard::Reference(commit.to_string())), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("alt")), vec![format!("git patch: {}", git_repo.get_commit_message_summary(commit).unwrap_or_default())], ), ], if let Some(thread_event_id) = thread_event_id { - vec![Tag::Event { + vec![Tag::from_standardized(nostr_sdk::TagStandard::Event { event_id: thread_event_id, relay_url: relay_hint.clone(), marker: Some(Marker::Root), - }] + public_key: None, + })] } else if let Some(event_ref) = root_proposal_id.clone() { vec![ - Tag::Hashtag("root".to_string()), - Tag::Hashtag("revision-root".to_string()), + Tag::hashtag("root"), + Tag::hashtag("revision-root"), // TODO check if id is for a root proposal (perhaps its for an issue?) - event_tag_from_nip19_or_hex(&event_ref,"proposal",nostr::Marker::Reply, false, false)?, + event_tag_from_nip19_or_hex(&event_ref,"proposal", Marker::Reply, false, false)?, ] } else { vec![ - Tag::Hashtag("root".to_string()), + Tag::hashtag("root"), ] }, mentions.to_vec(), if let Some(id) = parent_patch_event_id { - vec![Tag::Event { + vec![Tag::from_standardized(nostr_sdk::TagStandard::Event { event_id: id, relay_url: relay_hint.clone(), marker: Some(Marker::Reply), - }] + public_key: None, + })] } else { vec![] }, @@ -981,8 +937,8 @@ pub fn generate_patch_event( if let Some(branch_name) = branch_name { if thread_event_id.is_none() { vec![ - Tag::Generic( - TagKind::Custom("branch-name".to_string()), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("branch-name")), vec![branch_name.to_string()], ) ] @@ -1002,33 +958,35 @@ pub fn generate_patch_event( .collect(), vec![ // a fallback is now in place to extract this from the patch - Tag::Generic( - TagKind::Custom("commit".to_string()), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("commit")), vec![commit.to_string()], ), // this is required as patches cannot be relied upon to include the 'base commit' - Tag::Generic( - TagKind::Custom("parent-commit".to_string()), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("parent-commit")), vec![commit_parent.to_string()], ), // this is required to ensure the commit id matches - Tag::Generic( - TagKind::Custom("commit-pgp-sig".to_string()), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("commit-pgp-sig")), vec![ git_repo .extract_commit_pgp_signature(commit) .unwrap_or_default(), - ], + ], ), // removing description tag will not cause anything to break - Tag::Description(git_repo.get_commit_message(commit)?.to_string()), - Tag::Generic( - TagKind::Custom("author".to_string()), + Tag::from_standardized(nostr_sdk::TagStandard::Description( + git_repo.get_commit_message(commit)?.to_string() + )), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("author")), git_repo.get_commit_author(commit)?, ), // this is required to ensure the commit id matches - Tag::Generic( - TagKind::Custom("committer".to_string()), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("committer")), git_repo.get_commit_comitter(commit)?, ), ], @@ -1246,8 +1204,8 @@ mod tests { nostr::event::Kind::Custom(PATCH_KIND), format!("From ea897e987ea9a7a98e7a987e97987ea98e7a3334 Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/2] {title}\n\n{description}"), [ - Tag::Hashtag("cover-letter".to_string()), - Tag::Hashtag("root".to_string()), + Tag::hashtag("cover-letter"), + Tag::hashtag("root"), ], ) .to_event(&nostr::Keys::generate())?) -- cgit v1.2.3