diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-06-11 16:21:44 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-06-13 09:09:00 +0100 |
| commit | f1b3fcc40ab666d8def97096d1942c274da9b279 (patch) | |
| tree | 05d6af0c5c1ad9baedb90ef652152fba6d46abf5 /src/sub_commands | |
| parent | 7c6a5ab4c5e7a81c7442061029b9230748a6639d (diff) | |
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
Diffstat (limited to 'src/sub_commands')
| -rw-r--r-- | src/sub_commands/list.rs | 2 | ||||
| -rw-r--r-- | src/sub_commands/send.rs | 338 |
2 files changed, 149 insertions, 191 deletions
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( | |||
| 801 | .context("cannot fetch patch events")? | 801 | .context("cannot fetch patch events")? |
| 802 | .iter() | 802 | .iter() |
| 803 | .filter(|e| { | 803 | .filter(|e| { |
| 804 | e.kind.as_u64() == PATCH_KIND | 804 | e.kind.as_u16() == PATCH_KIND |
| 805 | && e.tags.iter().any(|t| { | 805 | && e.tags.iter().any(|t| { |
| 806 | t.as_vec().len() > 2 | 806 | t.as_vec().len() > 2 |
| 807 | && proposal_root_events | 807 | && 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; | |||
| 5 | use futures::future::join_all; | 5 | use futures::future::join_all; |
| 6 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | 6 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
| 7 | use nostr::{ | 7 | use nostr::{ |
| 8 | nips::{nip01::Coordinate, nip19::Nip19}, | 8 | nips::{nip01::Coordinate, nip10::Marker, nip19::Nip19}, |
| 9 | EventBuilder, FromBech32, Marker, Tag, TagKind, ToBech32, UncheckedUrl, | 9 | EventBuilder, FromBech32, Tag, TagKind, ToBech32, UncheckedUrl, |
| 10 | }; | 10 | }; |
| 11 | use nostr_sdk::hashes::sha1::Hash as Sha1Hash; | 11 | use nostr_sdk::{hashes::sha1::Hash as Sha1Hash, TagStandard}; |
| 12 | 12 | ||
| 13 | use super::list::tag_value; | 13 | use super::list::tag_value; |
| 14 | #[cfg(not(test))] | 14 | #[cfg(not(test))] |
| @@ -265,6 +265,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | #[allow(clippy::module_name_repetitions)] | 267 | #[allow(clippy::module_name_repetitions)] |
| 268 | #[allow(clippy::too_many_lines)] | ||
| 268 | pub async fn send_events( | 269 | pub async fn send_events( |
| 269 | #[cfg(test)] client: &crate::client::MockConnect, | 270 | #[cfg(test)] client: &crate::client::MockConnect, |
| 270 | #[cfg(not(test))] client: &Client, | 271 | #[cfg(not(test))] client: &Client, |
| @@ -273,21 +274,41 @@ pub async fn send_events( | |||
| 273 | repo_read_relays: Vec<String>, | 274 | repo_read_relays: Vec<String>, |
| 274 | animate: bool, | 275 | animate: bool, |
| 275 | ) -> Result<()> { | 276 | ) -> Result<()> { |
| 276 | let (_, _, _, mut all) = unique_and_duplicate_all(&my_write_relays, &repo_read_relays); | 277 | let fallback = [ |
| 277 | 278 | client.get_fallback_relays().clone(), | |
| 278 | let mut fallback = client.get_fallback_relays().clone(); | 279 | if events.iter().any(|e| e.kind().as_u16().eq(&REPO_REF_KIND)) { |
| 279 | 280 | client.get_blaster_relays().clone() | |
| 280 | // blast repo events | 281 | } else { |
| 281 | if events.iter().any(|e| e.kind().as_u64().eq(&REPO_REF_KIND)) { | 282 | vec![] |
| 282 | for r in client.get_blaster_relays() { | 283 | }, |
| 283 | fallback.push(r.to_string()); | 284 | ] |
| 285 | .concat(); | ||
| 286 | let mut relays: Vec<&String> = vec![]; | ||
| 287 | |||
| 288 | let all = &[ | ||
| 289 | repo_read_relays.clone(), | ||
| 290 | my_write_relays.clone(), | ||
| 291 | fallback.clone(), | ||
| 292 | ] | ||
| 293 | .concat(); | ||
| 294 | // add duplicates first | ||
| 295 | for r in &repo_read_relays { | ||
| 296 | let r_clean = remove_trailing_slash(r); | ||
| 297 | if !my_write_relays | ||
| 298 | .iter() | ||
| 299 | .filter(|x| r_clean.eq(&remove_trailing_slash(x))) | ||
| 300 | .count() | ||
| 301 | > 1 | ||
| 302 | && !relays.iter().any(|x| r_clean.eq(&remove_trailing_slash(x))) | ||
| 303 | { | ||
| 304 | relays.push(r); | ||
| 284 | } | 305 | } |
| 285 | } | 306 | } |
| 286 | 307 | ||
| 287 | // then remaining fallback list | 308 | for r in all { |
| 288 | for r in &fallback { | 309 | let r_clean = remove_trailing_slash(r); |
| 289 | if !all.iter().any(|r2| r2.eq(&r)) { | 310 | if !relays.iter().any(|x| r_clean.eq(&remove_trailing_slash(x))) { |
| 290 | all.push(r); | 311 | relays.push(r); |
| 291 | } | 312 | } |
| 292 | } | 313 | } |
| 293 | 314 | ||
| @@ -319,25 +340,36 @@ pub async fn send_events( | |||
| 319 | "x".to_string() | 340 | "x".to_string() |
| 320 | })?; | 341 | })?; |
| 321 | 342 | ||
| 322 | join_all(all.iter().map(|&relay| async { | 343 | #[allow(clippy::borrow_deref_ref)] |
| 344 | join_all(relays.iter().map(|&relay| async { | ||
| 345 | let relay_clean = remove_trailing_slash(&*relay); | ||
| 323 | let details = format!( | 346 | let details = format!( |
| 324 | "{}{}{} {}", | 347 | "{}{}{} {}", |
| 325 | if my_write_relays.iter().any(|r| relay.eq(r)) { | 348 | if my_write_relays |
| 349 | .iter() | ||
| 350 | .any(|r| relay_clean.eq(&remove_trailing_slash(r))) | ||
| 351 | { | ||
| 326 | " [my-relay]" | 352 | " [my-relay]" |
| 327 | } else { | 353 | } else { |
| 328 | "" | 354 | "" |
| 329 | }, | 355 | }, |
| 330 | if repo_read_relays.iter().any(|r| relay.eq(r)) { | 356 | if repo_read_relays |
| 357 | .iter() | ||
| 358 | .any(|r| relay_clean.eq(&remove_trailing_slash(r))) | ||
| 359 | { | ||
| 331 | " [repo-relay]" | 360 | " [repo-relay]" |
| 332 | } else { | 361 | } else { |
| 333 | "" | 362 | "" |
| 334 | }, | 363 | }, |
| 335 | if fallback.iter().any(|r| relay.eq(r)) { | 364 | if fallback |
| 365 | .iter() | ||
| 366 | .any(|r| relay_clean.eq(&remove_trailing_slash(r))) | ||
| 367 | { | ||
| 336 | " [default]" | 368 | " [default]" |
| 337 | } else { | 369 | } else { |
| 338 | "" | 370 | "" |
| 339 | }, | 371 | }, |
| 340 | *relay, | 372 | relay_clean, |
| 341 | ); | 373 | ); |
| 342 | let pb = m.add( | 374 | let pb = m.add( |
| 343 | ProgressBar::new(events.len() as u64) | 375 | ProgressBar::new(events.len() as u64) |
| @@ -378,36 +410,12 @@ pub async fn send_events( | |||
| 378 | Ok(()) | 410 | Ok(()) |
| 379 | } | 411 | } |
| 380 | 412 | ||
| 381 | /// returns `(unique_vec1, unique_vec2, duplicates, all)` | 413 | fn remove_trailing_slash(s: &String) -> String { |
| 382 | fn unique_and_duplicate_all<'a, S>( | 414 | match s.as_str().strip_suffix('/') { |
| 383 | vec1: &'a Vec<S>, | 415 | Some(s) => s, |
| 384 | vec2: &'a Vec<S>, | 416 | None => s, |
| 385 | ) -> (Vec<&'a S>, Vec<&'a S>, Vec<&'a S>, Vec<&'a S>) | ||
| 386 | where | ||
| 387 | S: PartialEq, | ||
| 388 | { | ||
| 389 | let mut vec1_u = vec![]; | ||
| 390 | let mut vec2_u = vec![]; | ||
| 391 | let mut dup = vec![]; | ||
| 392 | let mut all = vec![]; | ||
| 393 | for s1 in vec1 { | ||
| 394 | if vec2.iter().any(|s2| s1.eq(s2)) { | ||
| 395 | dup.push(s1); | ||
| 396 | } else { | ||
| 397 | vec1_u.push(s1); | ||
| 398 | } | ||
| 399 | } | 417 | } |
| 400 | for s2 in vec2 { | 418 | .to_string() |
| 401 | if !vec1.iter().any(|s1| s2.eq(s1)) { | ||
| 402 | vec2_u.push(s2); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | for a in [&dup, &vec1_u, &vec2_u] { | ||
| 406 | for e in a { | ||
| 407 | all.push(&**e); | ||
| 408 | } | ||
| 409 | } | ||
| 410 | (vec1_u, vec2_u, dup, all) | ||
| 411 | } | 419 | } |
| 412 | 420 | ||
| 413 | fn choose_commits(git_repo: &Repo, proposed_commits: Vec<Sha1Hash>) -> Result<Vec<Sha1Hash>> { | 421 | fn choose_commits(git_repo: &Repo, proposed_commits: Vec<Sha1Hash>) -> Result<Vec<Sha1Hash>> { |
| @@ -501,53 +509,6 @@ fn summarise_commit_for_selection(git_repo: &Repo, commit: &Sha1Hash) -> Result< | |||
| 501 | )) | 509 | )) |
| 502 | } | 510 | } |
| 503 | 511 | ||
| 504 | mod tests_unique_and_duplicate { | ||
| 505 | |||
| 506 | #[test] | ||
| 507 | fn correct_number_of_unique_and_duplicate_items() { | ||
| 508 | let v1 = vec![ | ||
| 509 | "t1".to_string(), | ||
| 510 | "t2".to_string(), | ||
| 511 | "t3".to_string(), | ||
| 512 | "t4".to_string(), | ||
| 513 | "t5".to_string(), | ||
| 514 | ]; | ||
| 515 | let v2 = vec![ | ||
| 516 | "t3".to_string(), | ||
| 517 | "t4".to_string(), | ||
| 518 | "t5".to_string(), | ||
| 519 | "t6".to_string(), | ||
| 520 | ]; | ||
| 521 | |||
| 522 | let (v1_u, v2_u, d, a) = super::unique_and_duplicate_all(&v1, &v2); | ||
| 523 | |||
| 524 | assert_eq!(v1_u.len(), 2); | ||
| 525 | assert_eq!(v2_u.len(), 1); | ||
| 526 | assert_eq!(d.len(), 3); | ||
| 527 | assert_eq!(a.len(), 6); | ||
| 528 | } | ||
| 529 | #[test] | ||
| 530 | fn all_begins_with_duplicates() { | ||
| 531 | let v1 = vec![ | ||
| 532 | "t1".to_string(), | ||
| 533 | "t2".to_string(), | ||
| 534 | "t3".to_string(), | ||
| 535 | "t4".to_string(), | ||
| 536 | "t5".to_string(), | ||
| 537 | ]; | ||
| 538 | let v2 = vec![ | ||
| 539 | "t3".to_string(), | ||
| 540 | "t4".to_string(), | ||
| 541 | "t5".to_string(), | ||
| 542 | "t6".to_string(), | ||
| 543 | ]; | ||
| 544 | |||
| 545 | let (_, _, d, a) = super::unique_and_duplicate_all(&v1, &v2); | ||
| 546 | |||
| 547 | assert_eq!(a[0], d[0]); | ||
| 548 | } | ||
| 549 | } | ||
| 550 | |||
| 551 | async fn get_root_proposal_id_and_mentions_from_in_reply_to( | 512 | async fn get_root_proposal_id_and_mentions_from_in_reply_to( |
| 552 | #[cfg(test)] client: &crate::client::MockConnect, | 513 | #[cfg(test)] client: &crate::client::MockConnect, |
| 553 | #[cfg(not(test))] client: &Client, | 514 | #[cfg(not(test))] client: &Client, |
| @@ -555,20 +516,23 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to( | |||
| 555 | in_reply_to: &[String], | 516 | in_reply_to: &[String], |
| 556 | ) -> Result<(Option<String>, Vec<nostr::Tag>)> { | 517 | ) -> Result<(Option<String>, Vec<nostr::Tag>)> { |
| 557 | let root_proposal_id = if let Some(first) = in_reply_to.first() { | 518 | let root_proposal_id = if let Some(first) = in_reply_to.first() { |
| 558 | match event_tag_from_nip19_or_hex(first, "in-reply-to", nostr::Marker::Root, true, false)? { | 519 | match event_tag_from_nip19_or_hex(first, "in-reply-to", Marker::Root, true, false)? |
| 559 | Tag::Event { | 520 | .as_standardized() |
| 521 | { | ||
| 522 | Some(nostr_sdk::TagStandard::Event { | ||
| 560 | event_id, | 523 | event_id, |
| 561 | relay_url: _, | 524 | relay_url: _, |
| 562 | marker: _, | 525 | marker: _, |
| 563 | } => { | 526 | public_key: _, |
| 527 | }) => { | ||
| 564 | let events = client | 528 | let events = client |
| 565 | .get_events( | 529 | .get_events( |
| 566 | repo_relays.to_vec(), | 530 | repo_relays.to_vec(), |
| 567 | vec![nostr::Filter::new().id(event_id)], | 531 | vec![nostr::Filter::new().id(*event_id)], |
| 568 | ) | 532 | ) |
| 569 | .await | 533 | .await |
| 570 | .context("whilst getting events specified in --in-reply-to")?; | 534 | .context("whilst getting events specified in --in-reply-to")?; |
| 571 | if let Some(first) = events.iter().find(|e| e.id.eq(&event_id)) { | 535 | if let Some(first) = events.iter().find(|e| e.id.eq(event_id)) { |
| 572 | if event_is_patch_set_root(first) { | 536 | if event_is_patch_set_root(first) { |
| 573 | Some(event_id.to_string()) | 537 | Some(event_id.to_string()) |
| 574 | } else { | 538 | } else { |
| @@ -591,16 +555,10 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to( | |||
| 591 | for (i, reply_to) in in_reply_to.iter().enumerate() { | 555 | for (i, reply_to) in in_reply_to.iter().enumerate() { |
| 592 | if i.ne(&0) || root_proposal_id.is_none() { | 556 | if i.ne(&0) || root_proposal_id.is_none() { |
| 593 | mention_tags.push( | 557 | mention_tags.push( |
| 594 | event_tag_from_nip19_or_hex( | 558 | event_tag_from_nip19_or_hex(reply_to, "in-reply-to", Marker::Mention, true, false) |
| 595 | reply_to, | 559 | .context(format!( |
| 596 | "in-reply-to", | 560 | "{reply_to} in 'in-reply-to' not a valid nostr reference" |
| 597 | nostr::Marker::Mention, | 561 | ))?, |
| 598 | true, | ||
| 599 | false, | ||
| 600 | ) | ||
| 601 | .context(format!( | ||
| 602 | "{reply_to} in 'in-reply-to' not a valid nostr reference" | ||
| 603 | ))?, | ||
| 604 | ); | 562 | ); |
| 605 | } | 563 | } |
| 606 | } | 564 | } |
| @@ -608,7 +566,7 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to( | |||
| 608 | Ok((root_proposal_id, mention_tags)) | 566 | Ok((root_proposal_id, mention_tags)) |
| 609 | } | 567 | } |
| 610 | 568 | ||
| 611 | pub static PATCH_KIND: u64 = 1617; | 569 | pub static PATCH_KIND: u16 = 1617; |
| 612 | 570 | ||
| 613 | #[allow(clippy::too_many_lines)] | 571 | #[allow(clippy::too_many_lines)] |
| 614 | pub fn generate_cover_letter_and_patch_events( | 572 | pub fn generate_cover_letter_and_patch_events( |
| @@ -637,33 +595,30 @@ pub fn generate_cover_letter_and_patch_events( | |||
| 637 | [ | 595 | [ |
| 638 | vec![ | 596 | vec![ |
| 639 | // TODO: why not tag all maintainer identifiers? | 597 | // TODO: why not tag all maintainer identifiers? |
| 640 | Tag::A { | 598 | Tag::coordinate(Coordinate { |
| 641 | coordinate: Coordinate { | 599 | kind: nostr::Kind::Custom(REPO_REF_KIND), |
| 642 | kind: nostr::Kind::Custom(REPO_REF_KIND), | 600 | public_key: *repo_ref.maintainers.first() |
| 643 | public_key: *repo_ref.maintainers.first() | 601 | .context("repo reference should always have at least one maintainer")?, |
| 644 | .context("repo reference should always have at least one maintainer")?, | 602 | identifier: repo_ref.identifier.to_string(), |
| 645 | identifier: repo_ref.identifier.to_string(), | 603 | relays: repo_ref.relays.clone(), |
| 646 | relays: repo_ref.relays.clone(), | 604 | }), |
| 647 | }, | 605 | Tag::from_standardized(TagStandard::Reference(format!("{root_commit}"))), |
| 648 | relay_url: repo_ref.relays.first().map(nostr::UncheckedUrl::from).clone(), | 606 | Tag::hashtag("cover-letter"), |
| 649 | }, | 607 | Tag::custom( |
| 650 | Tag::Reference(format!("{root_commit}")), | 608 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("alt")), |
| 651 | Tag::Hashtag("cover-letter".to_string()), | ||
| 652 | Tag::Generic( | ||
| 653 | nostr::TagKind::Custom("alt".to_string()), | ||
| 654 | vec![format!("git patch cover letter: {}", title.clone())], | 609 | vec![format!("git patch cover letter: {}", title.clone())], |
| 655 | ), | 610 | ), |
| 656 | ], | 611 | ], |
| 657 | if let Some(event_ref) = root_proposal_id.clone() { | 612 | if let Some(event_ref) = root_proposal_id.clone() { |
| 658 | vec![ | 613 | vec![ |
| 659 | Tag::Hashtag("root".to_string()), | 614 | Tag::hashtag("root"), |
| 660 | Tag::Hashtag("revision-root".to_string()), | 615 | Tag::hashtag("revision-root"), |
| 661 | // TODO check if id is for a root proposal (perhaps its for an issue?) | 616 | // TODO check if id is for a root proposal (perhaps its for an issue?) |
| 662 | event_tag_from_nip19_or_hex(&event_ref,"proposal",nostr::Marker::Reply, false, false)?, | 617 | event_tag_from_nip19_or_hex(&event_ref,"proposal",Marker::Reply, false, false)?, |
| 663 | ] | 618 | ] |
| 664 | } else { | 619 | } else { |
| 665 | vec![ | 620 | vec![ |
| 666 | Tag::Hashtag("root".to_string()), | 621 | Tag::hashtag("root"), |
| 667 | ] | 622 | ] |
| 668 | }, | 623 | }, |
| 669 | mentions.to_vec(), | 624 | mentions.to_vec(), |
| @@ -677,10 +632,12 @@ pub fn generate_cover_letter_and_patch_events( | |||
| 677 | && !branch_name.eq("origin/main") | 632 | && !branch_name.eq("origin/main") |
| 678 | && !branch_name.eq("origin/master") | 633 | && !branch_name.eq("origin/master") |
| 679 | { | 634 | { |
| 680 | vec![Tag::Generic( | 635 | vec![ |
| 681 | TagKind::Custom("branch-name".to_string()), | 636 | Tag::custom( |
| 682 | vec![branch_name], | 637 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("branch-name")), |
| 683 | )] | 638 | vec![branch_name], |
| 639 | ), | ||
| 640 | ] | ||
| 684 | } | 641 | } |
| 685 | else { vec![] } | 642 | else { vec![] } |
| 686 | } else { | 643 | } else { |
| @@ -740,7 +697,7 @@ pub fn generate_cover_letter_and_patch_events( | |||
| 740 | fn event_tag_from_nip19_or_hex( | 697 | fn event_tag_from_nip19_or_hex( |
| 741 | reference: &str, | 698 | reference: &str, |
| 742 | reference_name: &str, | 699 | reference_name: &str, |
| 743 | marker: nostr::Marker, | 700 | marker: Marker, |
| 744 | allow_npub_reference: bool, | 701 | allow_npub_reference: bool, |
| 745 | prompt_for_correction: bool, | 702 | prompt_for_correction: bool, |
| 746 | ) -> Result<nostr::Tag> { | 703 | ) -> Result<nostr::Tag> { |
| @@ -754,44 +711,44 @@ fn event_tag_from_nip19_or_hex( | |||
| 754 | if let Ok(nip19) = Nip19::from_bech32(bech32.clone()) { | 711 | if let Ok(nip19) = Nip19::from_bech32(bech32.clone()) { |
| 755 | match nip19 { | 712 | match nip19 { |
| 756 | Nip19::Event(n) => { | 713 | Nip19::Event(n) => { |
| 757 | break Ok(nostr::Tag::Event { | 714 | break Ok(Tag::from_standardized(nostr_sdk::TagStandard::Event { |
| 758 | event_id: n.event_id, | 715 | event_id: n.event_id, |
| 759 | relay_url: n.relays.first().map(UncheckedUrl::new), | 716 | relay_url: n.relays.first().map(UncheckedUrl::new), |
| 760 | marker: Some(marker), | 717 | marker: Some(marker), |
| 761 | }); | 718 | public_key: None, |
| 719 | })); | ||
| 762 | } | 720 | } |
| 763 | Nip19::EventId(id) => { | 721 | Nip19::EventId(id) => { |
| 764 | break Ok(nostr::Tag::Event { | 722 | break Ok(Tag::from_standardized(nostr_sdk::TagStandard::Event { |
| 765 | event_id: id, | 723 | event_id: id, |
| 766 | relay_url: None, | 724 | relay_url: None, |
| 767 | marker: Some(marker), | 725 | marker: Some(marker), |
| 768 | }); | 726 | public_key: None, |
| 727 | })); | ||
| 769 | } | 728 | } |
| 770 | Nip19::Coordinate(coordinate) => { | 729 | Nip19::Coordinate(coordinate) => { |
| 771 | break Ok(nostr::Tag::A { | 730 | break Ok(Tag::coordinate(coordinate)); |
| 772 | coordinate, | ||
| 773 | relay_url: None, | ||
| 774 | }); | ||
| 775 | } | 731 | } |
| 776 | Nip19::Profile(profile) => { | 732 | Nip19::Profile(profile) => { |
| 777 | if allow_npub_reference { | 733 | if allow_npub_reference { |
| 778 | break Ok(nostr::Tag::public_key(profile.public_key)); | 734 | break Ok(Tag::public_key(profile.public_key)); |
| 779 | } | 735 | } |
| 780 | } | 736 | } |
| 781 | Nip19::Pubkey(public_key) => { | 737 | Nip19::Pubkey(public_key) => { |
| 782 | if allow_npub_reference { | 738 | if allow_npub_reference { |
| 783 | break Ok(nostr::Tag::public_key(public_key)); | 739 | break Ok(Tag::public_key(public_key)); |
| 784 | } | 740 | } |
| 785 | } | 741 | } |
| 786 | _ => {} | 742 | _ => {} |
| 787 | } | 743 | } |
| 788 | } | 744 | } |
| 789 | if let Ok(id) = nostr::EventId::from_str(&bech32) { | 745 | if let Ok(id) = nostr::EventId::from_str(&bech32) { |
| 790 | break Ok(nostr::Tag::Event { | 746 | break Ok(Tag::from_standardized(nostr_sdk::TagStandard::Event { |
| 791 | event_id: id, | 747 | event_id: id, |
| 792 | relay_url: None, | 748 | relay_url: None, |
| 793 | marker: Some(marker), | 749 | marker: Some(marker), |
| 794 | }); | 750 | public_key: None, |
| 751 | })); | ||
| 795 | } | 752 | } |
| 796 | if prompt_for_correction { | 753 | if prompt_for_correction { |
| 797 | println!("not a valid {reference_name} event reference"); | 754 | println!("not a valid {reference_name} event reference"); |
| @@ -813,7 +770,7 @@ pub fn event_is_cover_letter(event: &nostr::Event) -> bool { | |||
| 813 | // TODO: look for Subject:[ PATCH 0/n ] but watch out for: | 770 | // TODO: look for Subject:[ PATCH 0/n ] but watch out for: |
| 814 | // [PATCH v1 0/n ] or | 771 | // [PATCH v1 0/n ] or |
| 815 | // [PATCH subsystem v2 0/n ] | 772 | // [PATCH subsystem v2 0/n ] |
| 816 | event.kind.as_u64().eq(&PATCH_KIND) | 773 | event.kind.as_u16().eq(&PATCH_KIND) |
| 817 | && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) | 774 | && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) |
| 818 | && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) | 775 | && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) |
| 819 | } | 776 | } |
| @@ -883,16 +840,16 @@ pub fn event_to_cover_letter(event: &nostr::Event) -> Result<CoverLetter> { | |||
| 883 | } | 840 | } |
| 884 | 841 | ||
| 885 | pub fn event_is_patch_set_root(event: &nostr::Event) -> bool { | 842 | pub fn event_is_patch_set_root(event: &nostr::Event) -> bool { |
| 886 | event.kind.as_u64().eq(&PATCH_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) | 843 | event.kind.as_u16().eq(&PATCH_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) |
| 887 | } | 844 | } |
| 888 | 845 | ||
| 889 | pub fn event_is_revision_root(event: &nostr::Event) -> bool { | 846 | pub fn event_is_revision_root(event: &nostr::Event) -> bool { |
| 890 | event.kind.as_u64().eq(&PATCH_KIND) | 847 | event.kind.as_u16().eq(&PATCH_KIND) |
| 891 | && event.iter_tags().any(|t| t.as_vec()[1].eq("revision-root")) | 848 | && event.iter_tags().any(|t| t.as_vec()[1].eq("revision-root")) |
| 892 | } | 849 | } |
| 893 | 850 | ||
| 894 | pub fn patch_supports_commit_ids(event: &nostr::Event) -> bool { | 851 | pub fn patch_supports_commit_ids(event: &nostr::Event) -> bool { |
| 895 | event.kind.as_u64().eq(&PATCH_KIND) | 852 | event.kind.as_u16().eq(&PATCH_KIND) |
| 896 | && event | 853 | && event |
| 897 | .iter_tags() | 854 | .iter_tags() |
| 898 | .any(|t| t.as_vec()[0].eq("commit-pgp-sig")) | 855 | .any(|t| t.as_vec()[0].eq("commit-pgp-sig")) |
| @@ -925,55 +882,54 @@ pub fn generate_patch_event( | |||
| 925 | .context(format!("cannot make patch for commit {commit}"))?, | 882 | .context(format!("cannot make patch for commit {commit}"))?, |
| 926 | [ | 883 | [ |
| 927 | vec![ | 884 | vec![ |
| 928 | Tag::A { | 885 | Tag::coordinate(Coordinate { |
| 929 | coordinate: Coordinate { | 886 | kind: nostr::Kind::Custom(REPO_REF_KIND), |
| 930 | kind: nostr::Kind::Custom(REPO_REF_KIND), | 887 | public_key: *repo_ref.maintainers.first() |
| 931 | public_key: *repo_ref.maintainers.first() | 888 | .context("repo reference should always have at least one maintainer - the issuer of the repo event") |
| 932 | .context("repo reference should always have at least one maintainer - the issuer of the repo event") | 889 | ?, |
| 933 | ?, | 890 | identifier: repo_ref.identifier.to_string(), |
| 934 | identifier: repo_ref.identifier.to_string(), | 891 | relays: repo_ref.relays.clone(), |
| 935 | relays: repo_ref.relays.clone(), | 892 | }), |
| 936 | }, | 893 | Tag::from_standardized(TagStandard::Reference(root_commit.to_string())), |
| 937 | relay_url: relay_hint.clone(), | ||
| 938 | }, | ||
| 939 | Tag::Reference(format!("{root_commit}")), | ||
| 940 | // commit id reference is a trade-off. its now | 894 | // commit id reference is a trade-off. its now |
| 941 | // unclear which one is the root commit id but it | 895 | // unclear which one is the root commit id but it |
| 942 | // enables easier location of code comments againt | 896 | // enables easier location of code comments againt |
| 943 | // code that makes it into the main branch, assuming | 897 | // code that makes it into the main branch, assuming |
| 944 | // the commit id is correct | 898 | // the commit id is correct |
| 945 | Tag::Reference(commit.to_string()), | 899 | Tag::from_standardized(TagStandard::Reference(commit.to_string())), |
| 946 | Tag::Generic( | 900 | Tag::custom( |
| 947 | nostr::TagKind::Custom("alt".to_string()), | 901 | TagKind::Custom(std::borrow::Cow::Borrowed("alt")), |
| 948 | vec![format!("git patch: {}", git_repo.get_commit_message_summary(commit).unwrap_or_default())], | 902 | vec![format!("git patch: {}", git_repo.get_commit_message_summary(commit).unwrap_or_default())], |
| 949 | ), | 903 | ), |
| 950 | ], | 904 | ], |
| 951 | 905 | ||
| 952 | if let Some(thread_event_id) = thread_event_id { | 906 | if let Some(thread_event_id) = thread_event_id { |
| 953 | vec![Tag::Event { | 907 | vec![Tag::from_standardized(nostr_sdk::TagStandard::Event { |
| 954 | event_id: thread_event_id, | 908 | event_id: thread_event_id, |
| 955 | relay_url: relay_hint.clone(), | 909 | relay_url: relay_hint.clone(), |
| 956 | marker: Some(Marker::Root), | 910 | marker: Some(Marker::Root), |
| 957 | }] | 911 | public_key: None, |
| 912 | })] | ||
| 958 | } else if let Some(event_ref) = root_proposal_id.clone() { | 913 | } else if let Some(event_ref) = root_proposal_id.clone() { |
| 959 | vec![ | 914 | vec![ |
| 960 | Tag::Hashtag("root".to_string()), | 915 | Tag::hashtag("root"), |
| 961 | Tag::Hashtag("revision-root".to_string()), | 916 | Tag::hashtag("revision-root"), |
| 962 | // TODO check if id is for a root proposal (perhaps its for an issue?) | 917 | // TODO check if id is for a root proposal (perhaps its for an issue?) |
| 963 | event_tag_from_nip19_or_hex(&event_ref,"proposal",nostr::Marker::Reply, false, false)?, | 918 | event_tag_from_nip19_or_hex(&event_ref,"proposal", Marker::Reply, false, false)?, |
| 964 | ] | 919 | ] |
| 965 | } else { | 920 | } else { |
| 966 | vec![ | 921 | vec![ |
| 967 | Tag::Hashtag("root".to_string()), | 922 | Tag::hashtag("root"), |
| 968 | ] | 923 | ] |
| 969 | }, | 924 | }, |
| 970 | mentions.to_vec(), | 925 | mentions.to_vec(), |
| 971 | if let Some(id) = parent_patch_event_id { | 926 | if let Some(id) = parent_patch_event_id { |
| 972 | vec![Tag::Event { | 927 | vec![Tag::from_standardized(nostr_sdk::TagStandard::Event { |
| 973 | event_id: id, | 928 | event_id: id, |
| 974 | relay_url: relay_hint.clone(), | 929 | relay_url: relay_hint.clone(), |
| 975 | marker: Some(Marker::Reply), | 930 | marker: Some(Marker::Reply), |
| 976 | }] | 931 | public_key: None, |
| 932 | })] | ||
| 977 | } else { | 933 | } else { |
| 978 | vec![] | 934 | vec![] |
| 979 | }, | 935 | }, |
| @@ -981,8 +937,8 @@ pub fn generate_patch_event( | |||
| 981 | if let Some(branch_name) = branch_name { | 937 | if let Some(branch_name) = branch_name { |
| 982 | if thread_event_id.is_none() { | 938 | if thread_event_id.is_none() { |
| 983 | vec![ | 939 | vec![ |
| 984 | Tag::Generic( | 940 | Tag::custom( |
| 985 | TagKind::Custom("branch-name".to_string()), | 941 | TagKind::Custom(std::borrow::Cow::Borrowed("branch-name")), |
| 986 | vec![branch_name.to_string()], | 942 | vec![branch_name.to_string()], |
| 987 | ) | 943 | ) |
| 988 | ] | 944 | ] |
| @@ -1002,33 +958,35 @@ pub fn generate_patch_event( | |||
| 1002 | .collect(), | 958 | .collect(), |
| 1003 | vec![ | 959 | vec![ |
| 1004 | // a fallback is now in place to extract this from the patch | 960 | // a fallback is now in place to extract this from the patch |
| 1005 | Tag::Generic( | 961 | Tag::custom( |
| 1006 | TagKind::Custom("commit".to_string()), | 962 | TagKind::Custom(std::borrow::Cow::Borrowed("commit")), |
| 1007 | vec![commit.to_string()], | 963 | vec![commit.to_string()], |
| 1008 | ), | 964 | ), |
| 1009 | // this is required as patches cannot be relied upon to include the 'base commit' | 965 | // this is required as patches cannot be relied upon to include the 'base commit' |
| 1010 | Tag::Generic( | 966 | Tag::custom( |
| 1011 | TagKind::Custom("parent-commit".to_string()), | 967 | TagKind::Custom(std::borrow::Cow::Borrowed("parent-commit")), |
| 1012 | vec![commit_parent.to_string()], | 968 | vec![commit_parent.to_string()], |
| 1013 | ), | 969 | ), |
| 1014 | // this is required to ensure the commit id matches | 970 | // this is required to ensure the commit id matches |
| 1015 | Tag::Generic( | 971 | Tag::custom( |
| 1016 | TagKind::Custom("commit-pgp-sig".to_string()), | 972 | TagKind::Custom(std::borrow::Cow::Borrowed("commit-pgp-sig")), |
| 1017 | vec![ | 973 | vec![ |
| 1018 | git_repo | 974 | git_repo |
| 1019 | .extract_commit_pgp_signature(commit) | 975 | .extract_commit_pgp_signature(commit) |
| 1020 | .unwrap_or_default(), | 976 | .unwrap_or_default(), |
| 1021 | ], | 977 | ], |
| 1022 | ), | 978 | ), |
| 1023 | // removing description tag will not cause anything to break | 979 | // removing description tag will not cause anything to break |
| 1024 | Tag::Description(git_repo.get_commit_message(commit)?.to_string()), | 980 | Tag::from_standardized(nostr_sdk::TagStandard::Description( |
| 1025 | Tag::Generic( | 981 | git_repo.get_commit_message(commit)?.to_string() |
| 1026 | TagKind::Custom("author".to_string()), | 982 | )), |
| 983 | Tag::custom( | ||
| 984 | TagKind::Custom(std::borrow::Cow::Borrowed("author")), | ||
| 1027 | git_repo.get_commit_author(commit)?, | 985 | git_repo.get_commit_author(commit)?, |
| 1028 | ), | 986 | ), |
| 1029 | // this is required to ensure the commit id matches | 987 | // this is required to ensure the commit id matches |
| 1030 | Tag::Generic( | 988 | Tag::custom( |
| 1031 | TagKind::Custom("committer".to_string()), | 989 | TagKind::Custom(std::borrow::Cow::Borrowed("committer")), |
| 1032 | git_repo.get_commit_comitter(commit)?, | 990 | git_repo.get_commit_comitter(commit)?, |
| 1033 | ), | 991 | ), |
| 1034 | ], | 992 | ], |
| @@ -1246,8 +1204,8 @@ mod tests { | |||
| 1246 | nostr::event::Kind::Custom(PATCH_KIND), | 1204 | nostr::event::Kind::Custom(PATCH_KIND), |
| 1247 | format!("From ea897e987ea9a7a98e7a987e97987ea98e7a3334 Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/2] {title}\n\n{description}"), | 1205 | format!("From ea897e987ea9a7a98e7a987e97987ea98e7a3334 Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/2] {title}\n\n{description}"), |
| 1248 | [ | 1206 | [ |
| 1249 | Tag::Hashtag("cover-letter".to_string()), | 1207 | Tag::hashtag("cover-letter"), |
| 1250 | Tag::Hashtag("root".to_string()), | 1208 | Tag::hashtag("root"), |
| 1251 | ], | 1209 | ], |
| 1252 | ) | 1210 | ) |
| 1253 | .to_event(&nostr::Keys::generate())?) | 1211 | .to_event(&nostr::Keys::generate())?) |