diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-02-13 06:27:34 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-02-13 06:27:34 +0000 |
| commit | 3112576195aef212622d27ad9164336796c1953e (patch) | |
| tree | 0e897bcb8309c2d4c8f33d7c1590c2dcc0577508 | |
| parent | 9cd3e43b899b23b7f6e75276fa3d19bf9550f8fd (diff) | |
feat(prs-create)!: pr to nip34-like cover letter
up the pr event type to a nip34-like cover letter format
this sets the building blocks in place to enable simplier clients to
use the 'cover letter' feature in `git format-patch` to create the
experience as a pr event
| -rw-r--r-- | src/git.rs | 3 | ||||
| -rw-r--r-- | src/sub_commands/prs/create.rs | 240 | ||||
| -rw-r--r-- | src/sub_commands/prs/list.rs | 28 | ||||
| -rw-r--r-- | src/sub_commands/pull.rs | 10 | ||||
| -rw-r--r-- | src/sub_commands/push.rs | 13 | ||||
| -rw-r--r-- | test_utils/src/lib.rs | 2 | ||||
| -rw-r--r-- | tests/prs_create.rs | 219 |
7 files changed, 375 insertions, 140 deletions
| @@ -1260,7 +1260,7 @@ mod tests { | |||
| 1260 | &git_repo, | 1260 | &git_repo, |
| 1261 | &git_repo.get_root_commit()?, | 1261 | &git_repo.get_root_commit()?, |
| 1262 | &oid_to_sha1(&original_oid), | 1262 | &oid_to_sha1(&original_oid), |
| 1263 | nostr::EventId::all_zeros(), | 1263 | Some(nostr::EventId::all_zeros()), |
| 1264 | &TEST_KEY_1_KEYS, | 1264 | &TEST_KEY_1_KEYS, |
| 1265 | &RepoRef::try_from(generate_repo_ref_event()).unwrap(), | 1265 | &RepoRef::try_from(generate_repo_ref_event()).unwrap(), |
| 1266 | None, | 1266 | None, |
| @@ -1418,6 +1418,7 @@ mod tests { | |||
| 1418 | let git_repo = Repo::from_path(&original_repo.dir)?; | 1418 | let git_repo = Repo::from_path(&original_repo.dir)?; |
| 1419 | 1419 | ||
| 1420 | let mut events = generate_pr_and_patch_events( | 1420 | let mut events = generate_pr_and_patch_events( |
| 1421 | // Some(("test".to_string(), "test".to_string())), | ||
| 1421 | "title", | 1422 | "title", |
| 1422 | "description", | 1423 | "description", |
| 1423 | &git_repo, | 1424 | &git_repo, |
diff --git a/src/sub_commands/prs/create.rs b/src/sub_commands/prs/create.rs index 8506303..83a3942 100644 --- a/src/sub_commands/prs/create.rs +++ b/src/sub_commands/prs/create.rs | |||
| @@ -21,10 +21,10 @@ use crate::{ | |||
| 21 | #[derive(Debug, clap::Args)] | 21 | #[derive(Debug, clap::Args)] |
| 22 | pub struct SubCommandArgs { | 22 | pub struct SubCommandArgs { |
| 23 | #[clap(short, long)] | 23 | #[clap(short, long)] |
| 24 | /// title of pull request (defaults to first line of first commit) | 24 | /// optional cover letter title |
| 25 | title: Option<String>, | 25 | title: Option<String>, |
| 26 | #[clap(short, long)] | 26 | #[clap(short, long)] |
| 27 | /// optional description | 27 | /// optional cover letter description |
| 28 | description: Option<String>, | 28 | description: Option<String>, |
| 29 | #[clap(long)] | 29 | #[clap(long)] |
| 30 | /// branch to get changes from (defaults to head) | 30 | /// branch to get changes from (defaults to head) |
| @@ -34,6 +34,7 @@ pub struct SubCommandArgs { | |||
| 34 | to_branch: Option<String>, | 34 | to_branch: Option<String>, |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | #[allow(clippy::too_many_lines)] | ||
| 37 | pub async fn launch( | 38 | pub async fn launch( |
| 38 | cli_args: &Cli, | 39 | cli_args: &Cli, |
| 39 | _pr_args: &super::SubCommandArgs, | 40 | _pr_args: &super::SubCommandArgs, |
| @@ -91,6 +92,21 @@ pub async fn launch( | |||
| 91 | .input(PromptInputParms::default().with_prompt("description (Optional)"))?, | 92 | .input(PromptInputParms::default().with_prompt("description (Optional)"))?, |
| 92 | }; | 93 | }; |
| 93 | 94 | ||
| 95 | // let cover_letter_title_description = if let Some(title) = title { | ||
| 96 | // Some(( | ||
| 97 | // title, | ||
| 98 | // if let Some(t) = &args.description { | ||
| 99 | // t.clone() | ||
| 100 | // } else { | ||
| 101 | // Interactor::default() | ||
| 102 | // .input(PromptInputParms::default().with_prompt("cover letter | ||
| 103 | // description"))? .clone() | ||
| 104 | // }, | ||
| 105 | // )) | ||
| 106 | // } else { | ||
| 107 | // None | ||
| 108 | // }; | ||
| 109 | |||
| 94 | #[cfg(not(test))] | 110 | #[cfg(not(test))] |
| 95 | let mut client = Client::default(); | 111 | let mut client = Client::default(); |
| 96 | #[cfg(test)] | 112 | #[cfg(test)] |
| @@ -111,8 +127,15 @@ pub async fn launch( | |||
| 111 | ) | 127 | ) |
| 112 | .await?; | 128 | .await?; |
| 113 | 129 | ||
| 114 | let events = | 130 | let events = generate_pr_and_patch_events( |
| 115 | generate_pr_and_patch_events(&title, &description, &git_repo, &ahead, &keys, &repo_ref)?; | 131 | // cover_letter_title_description, |
| 132 | &title, | ||
| 133 | &description, | ||
| 134 | &git_repo, | ||
| 135 | &ahead, | ||
| 136 | &keys, | ||
| 137 | &repo_ref, | ||
| 138 | )?; | ||
| 116 | 139 | ||
| 117 | println!( | 140 | println!( |
| 118 | "posting 1 pull request with {} commits...", | 141 | "posting 1 pull request with {} commits...", |
| @@ -308,6 +331,7 @@ pub static PATCH_KIND: u64 = 1617; | |||
| 308 | pub fn generate_pr_and_patch_events( | 331 | pub fn generate_pr_and_patch_events( |
| 309 | title: &str, | 332 | title: &str, |
| 310 | description: &str, | 333 | description: &str, |
| 334 | // cover_letter_title_description: Option<(String, String)>, | ||
| 311 | git_repo: &Repo, | 335 | git_repo: &Repo, |
| 312 | commits: &Vec<Sha1Hash>, | 336 | commits: &Vec<Sha1Hash>, |
| 313 | keys: &nostr::Keys, | 337 | keys: &nostr::Keys, |
| @@ -317,40 +341,57 @@ pub fn generate_pr_and_patch_events( | |||
| 317 | .get_root_commit() | 341 | .get_root_commit() |
| 318 | .context("failed to get root commit of the repository")?; | 342 | .context("failed to get root commit of the repository")?; |
| 319 | 343 | ||
| 320 | let mut pr_tags = vec![ | 344 | let mut events = vec![]; |
| 321 | Tag::Reference(format!("r-{root_commit}")), | ||
| 322 | Tag::Name(title.to_string()), | ||
| 323 | Tag::Description(description.to_string()), | ||
| 324 | ]; | ||
| 325 | |||
| 326 | if let Ok(branch_name) = git_repo.get_checked_out_branch_name() { | ||
| 327 | pr_tags.push(Tag::Generic( | ||
| 328 | TagKind::Custom("branch-name".to_string()), | ||
| 329 | vec![branch_name], | ||
| 330 | )); | ||
| 331 | } | ||
| 332 | 345 | ||
| 333 | let pr_event = EventBuilder::new( | 346 | // if let Some((title, description)) = cover_letter_title_description { |
| 347 | if !title.is_empty() { | ||
| 348 | events.push(EventBuilder::new( | ||
| 334 | nostr::event::Kind::Custom(PR_KIND), | 349 | nostr::event::Kind::Custom(PR_KIND), |
| 335 | format!("{title}\r\n\r\n{description}"), | 350 | format!( |
| 336 | pr_tags, | 351 | "From {} Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/{}] {title}\n\n{description}", |
| 337 | // TODO: add Repo event as root | 352 | commits.last().unwrap(), |
| 338 | // TODO: people tag maintainers | 353 | commits.len() |
| 339 | // TODO: add relay tags | 354 | ), |
| 355 | [ | ||
| 356 | vec![ | ||
| 357 | // TODO: why not tag all maintainer identifiers? | ||
| 358 | Tag::A { | ||
| 359 | kind: nostr::Kind::Custom(REPO_REF_KIND), | ||
| 360 | public_key: *repo_ref.maintainers.first() | ||
| 361 | .context("repo reference should always have at least one maintainer - the issuer of the repo event") | ||
| 362 | ?, | ||
| 363 | identifier: repo_ref.identifier.to_string(), | ||
| 364 | relay_url: repo_ref.relays.first().map(nostr::UncheckedUrl::from).clone(), | ||
| 365 | }, | ||
| 366 | Tag::Reference(format!("{root_commit}")), | ||
| 367 | Tag::Hashtag("cover-letter".to_string()), | ||
| 368 | Tag::Hashtag("root".to_string()), | ||
| 369 | ], | ||
| 370 | if let Ok(branch_name) = git_repo.get_checked_out_branch_name() { | ||
| 371 | vec![Tag::Generic( | ||
| 372 | TagKind::Custom("branch-name".to_string()), | ||
| 373 | vec![branch_name], | ||
| 374 | )] | ||
| 375 | } else { | ||
| 376 | vec![] | ||
| 377 | }, | ||
| 378 | repo_ref.maintainers | ||
| 379 | .iter() | ||
| 380 | .map(|pk| Tag::public_key(*pk)) | ||
| 381 | .collect(), | ||
| 382 | ].concat(), | ||
| 340 | ) | 383 | ) |
| 341 | .to_event(keys) | 384 | .to_event(keys) |
| 342 | .context("failed to create pr event")?; | 385 | .context("failed to create cover-letter event")?); |
| 343 | 386 | } | |
| 344 | let pr_event_id = pr_event.id; | ||
| 345 | 387 | ||
| 346 | let mut events = vec![pr_event]; | ||
| 347 | for (i, commit) in commits.iter().enumerate() { | 388 | for (i, commit) in commits.iter().enumerate() { |
| 348 | events.push( | 389 | events.push( |
| 349 | generate_patch_event( | 390 | generate_patch_event( |
| 350 | git_repo, | 391 | git_repo, |
| 351 | &root_commit, | 392 | &root_commit, |
| 352 | commit, | 393 | commit, |
| 353 | pr_event_id, | 394 | events.first().map(|event| event.id), |
| 354 | keys, | 395 | keys, |
| 355 | repo_ref, | 396 | repo_ref, |
| 356 | events.last().map(nostr::Event::id), | 397 | events.last().map(nostr::Event::id), |
| @@ -366,12 +407,45 @@ pub fn generate_pr_and_patch_events( | |||
| 366 | Ok(events) | 407 | Ok(events) |
| 367 | } | 408 | } |
| 368 | 409 | ||
| 410 | pub struct CoverLetter { | ||
| 411 | pub title: String, | ||
| 412 | pub description: String, | ||
| 413 | pub branch_name: Option<String>, | ||
| 414 | } | ||
| 415 | |||
| 416 | fn event_is_cover_letter(event: &nostr::Event) -> bool { | ||
| 417 | event.kind.as_u64().eq(&PR_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) | ||
| 418 | } | ||
| 419 | pub fn event_to_cover_letter(event: &nostr::Event) -> Result<CoverLetter> { | ||
| 420 | if !event_is_cover_letter(event) { | ||
| 421 | bail!("event is not a cover letter") | ||
| 422 | } | ||
| 423 | let title_index = event | ||
| 424 | .content | ||
| 425 | .find("] ") | ||
| 426 | .context("event is not formatted as a cover letter patch")? | ||
| 427 | + 2; | ||
| 428 | let description_index = event.content[title_index..] | ||
| 429 | .find('\n') | ||
| 430 | .unwrap_or(event.content.len() - 1 - title_index) | ||
| 431 | + title_index; | ||
| 432 | |||
| 433 | Ok(CoverLetter { | ||
| 434 | title: event.content[title_index..description_index].to_string(), | ||
| 435 | description: event.content[description_index..].trim().to_string(), | ||
| 436 | branch_name: event | ||
| 437 | .iter_tags() | ||
| 438 | .find(|t| t.as_vec()[0].eq("branch-name")) | ||
| 439 | .map(|tag| tag.as_vec()[1].clone()), | ||
| 440 | }) | ||
| 441 | } | ||
| 442 | |||
| 369 | #[allow(clippy::too_many_arguments)] | 443 | #[allow(clippy::too_many_arguments)] |
| 370 | pub fn generate_patch_event( | 444 | pub fn generate_patch_event( |
| 371 | git_repo: &Repo, | 445 | git_repo: &Repo, |
| 372 | root_commit: &Sha1Hash, | 446 | root_commit: &Sha1Hash, |
| 373 | commit: &Sha1Hash, | 447 | commit: &Sha1Hash, |
| 374 | thread_event_id: nostr::EventId, | 448 | thread_event_id: Option<nostr::EventId>, |
| 375 | keys: &nostr::Keys, | 449 | keys: &nostr::Keys, |
| 376 | repo_ref: &RepoRef, | 450 | repo_ref: &RepoRef, |
| 377 | parent_patch_event_id: Option<nostr::EventId>, | 451 | parent_patch_event_id: Option<nostr::EventId>, |
| @@ -404,10 +478,13 @@ pub fn generate_patch_event( | |||
| 404 | // the commit id is correct | 478 | // the commit id is correct |
| 405 | Tag::Reference(commit.to_string()), | 479 | Tag::Reference(commit.to_string()), |
| 406 | 480 | ||
| 407 | Tag::Event { | 481 | if let Some(thread_event_id) = thread_event_id { Tag::Event { |
| 408 | event_id: thread_event_id, | 482 | event_id: thread_event_id, |
| 409 | relay_url: relay_hint.clone(), | 483 | relay_url: relay_hint.clone(), |
| 410 | marker: Some(Marker::Root), | 484 | marker: Some(Marker::Root), |
| 485 | } } | ||
| 486 | else { | ||
| 487 | Tag::Hashtag("root".to_string()) | ||
| 411 | }, | 488 | }, |
| 412 | ], | 489 | ], |
| 413 | if let Some(id) = parent_patch_event_id { | 490 | if let Some(id) = parent_patch_event_id { |
| @@ -686,4 +763,109 @@ mod tests { | |||
| 686 | Ok(()) | 763 | Ok(()) |
| 687 | } | 764 | } |
| 688 | } | 765 | } |
| 766 | |||
| 767 | mod event_to_cover_letter { | ||
| 768 | use super::*; | ||
| 769 | |||
| 770 | fn generate_cover_letter(title: &str, description: &str) -> Result<nostr::Event> { | ||
| 771 | Ok(nostr::event::EventBuilder::new( | ||
| 772 | nostr::event::Kind::Custom(PR_KIND), | ||
| 773 | format!("From ea897e987ea9a7a98e7a987e97987ea98e7a3334 Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/2] {title}\n\n{description}"), | ||
| 774 | [ | ||
| 775 | Tag::Hashtag("cover-letter".to_string()), | ||
| 776 | Tag::Hashtag("root".to_string()), | ||
| 777 | ], | ||
| 778 | ) | ||
| 779 | .to_event(&nostr::Keys::generate())?) | ||
| 780 | } | ||
| 781 | |||
| 782 | #[test] | ||
| 783 | fn basic_title() -> Result<()> { | ||
| 784 | assert_eq!( | ||
| 785 | event_to_cover_letter(&generate_cover_letter("the title", "description here")?)? | ||
| 786 | .title, | ||
| 787 | "the title", | ||
| 788 | ); | ||
| 789 | Ok(()) | ||
| 790 | } | ||
| 791 | |||
| 792 | #[test] | ||
| 793 | fn basic_description() -> Result<()> { | ||
| 794 | assert_eq!( | ||
| 795 | event_to_cover_letter(&generate_cover_letter("the title", "description here")?)? | ||
| 796 | .description, | ||
| 797 | "description here", | ||
| 798 | ); | ||
| 799 | Ok(()) | ||
| 800 | } | ||
| 801 | |||
| 802 | #[test] | ||
| 803 | fn description_trimmed() -> Result<()> { | ||
| 804 | assert_eq!( | ||
| 805 | event_to_cover_letter(&generate_cover_letter( | ||
| 806 | "the title", | ||
| 807 | " \n \ndescription here\n\n " | ||
| 808 | )?)? | ||
| 809 | .description, | ||
| 810 | "description here", | ||
| 811 | ); | ||
| 812 | Ok(()) | ||
| 813 | } | ||
| 814 | |||
| 815 | #[test] | ||
| 816 | fn multi_line_description() -> Result<()> { | ||
| 817 | assert_eq!( | ||
| 818 | event_to_cover_letter(&generate_cover_letter( | ||
| 819 | "the title", | ||
| 820 | "description here\n\nmore here\nmore" | ||
| 821 | )?)? | ||
| 822 | .description, | ||
| 823 | "description here\n\nmore here\nmore", | ||
| 824 | ); | ||
| 825 | Ok(()) | ||
| 826 | } | ||
| 827 | |||
| 828 | #[test] | ||
| 829 | fn new_lines_in_title_forms_part_of_description() -> Result<()> { | ||
| 830 | assert_eq!( | ||
| 831 | event_to_cover_letter(&generate_cover_letter( | ||
| 832 | "the title\nwith new line", | ||
| 833 | "description here\n\nmore here\nmore" | ||
| 834 | )?)? | ||
| 835 | .title, | ||
| 836 | "the title", | ||
| 837 | ); | ||
| 838 | assert_eq!( | ||
| 839 | event_to_cover_letter(&generate_cover_letter( | ||
| 840 | "the title\nwith new line", | ||
| 841 | "description here\n\nmore here\nmore" | ||
| 842 | )?)? | ||
| 843 | .description, | ||
| 844 | "with new line\n\ndescription here\n\nmore here\nmore", | ||
| 845 | ); | ||
| 846 | Ok(()) | ||
| 847 | } | ||
| 848 | |||
| 849 | mod blank_description { | ||
| 850 | use super::*; | ||
| 851 | |||
| 852 | #[test] | ||
| 853 | fn title_correct() -> Result<()> { | ||
| 854 | assert_eq!( | ||
| 855 | event_to_cover_letter(&generate_cover_letter("the title", "")?)?.title, | ||
| 856 | "the title", | ||
| 857 | ); | ||
| 858 | Ok(()) | ||
| 859 | } | ||
| 860 | |||
| 861 | #[test] | ||
| 862 | fn description_is_empty_string() -> Result<()> { | ||
| 863 | assert_eq!( | ||
| 864 | event_to_cover_letter(&generate_cover_letter("the title", "")?)?.description, | ||
| 865 | "", | ||
| 866 | ); | ||
| 867 | Ok(()) | ||
| 868 | } | ||
| 869 | } | ||
| 870 | } | ||
| 689 | } | 871 | } |
diff --git a/src/sub_commands/prs/list.rs b/src/sub_commands/prs/list.rs index 88b325b..bc85eed 100644 --- a/src/sub_commands/prs/list.rs +++ b/src/sub_commands/prs/list.rs | |||
| @@ -8,8 +8,8 @@ use crate::{ | |||
| 8 | cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms}, | 8 | cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms}, |
| 9 | client::Connect, | 9 | client::Connect, |
| 10 | git::{Repo, RepoActions}, | 10 | git::{Repo, RepoActions}, |
| 11 | repo_ref, | 11 | repo_ref::{self}, |
| 12 | sub_commands::prs::create::{PATCH_KIND, PR_KIND}, | 12 | sub_commands::prs::create::{event_to_cover_letter, PATCH_KIND, PR_KIND}, |
| 13 | Cli, | 13 | Cli, |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| @@ -20,6 +20,7 @@ pub struct SubCommandArgs { | |||
| 20 | open_only: bool, | 20 | open_only: bool, |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | #[allow(clippy::too_many_lines)] | ||
| 23 | pub async fn launch( | 24 | pub async fn launch( |
| 24 | _cli_args: &Cli, | 25 | _cli_args: &Cli, |
| 25 | _pr_args: &super::SubCommandArgs, | 26 | _pr_args: &super::SubCommandArgs, |
| @@ -56,7 +57,7 @@ pub async fn launch( | |||
| 56 | vec![ | 57 | vec![ |
| 57 | nostr::Filter::default() | 58 | nostr::Filter::default() |
| 58 | .kind(nostr::Kind::Custom(PR_KIND)) | 59 | .kind(nostr::Kind::Custom(PR_KIND)) |
| 59 | .reference(format!("r-{root_commit}")), | 60 | .reference(format!("{root_commit}")), |
| 60 | ], | 61 | ], |
| 61 | ) | 62 | ) |
| 62 | .await? | 63 | .await? |
| @@ -65,7 +66,7 @@ pub async fn launch( | |||
| 65 | e.kind.as_u64() == PR_KIND | 66 | e.kind.as_u64() == PR_KIND |
| 66 | && e.tags | 67 | && e.tags |
| 67 | .iter() | 68 | .iter() |
| 68 | .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("r-{root_commit}"))) | 69 | .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("{root_commit}"))) |
| 69 | }) | 70 | }) |
| 70 | .map(std::borrow::ToOwned::to_owned) | 71 | .map(std::borrow::ToOwned::to_owned) |
| 71 | .collect(); | 72 | .collect(); |
| @@ -92,8 +93,8 @@ pub async fn launch( | |||
| 92 | pr_events | 93 | pr_events |
| 93 | .iter() | 94 | .iter() |
| 94 | .map(|e| { | 95 | .map(|e| { |
| 95 | if let Ok(name) = tag_value(e, "name") { | 96 | if let Ok(cl) = event_to_cover_letter(e) { |
| 96 | name | 97 | cl.title |
| 97 | } else { | 98 | } else { |
| 98 | e.id.to_string() | 99 | e.id.to_string() |
| 99 | } | 100 | } |
| @@ -131,7 +132,19 @@ pub async fn launch( | |||
| 131 | let most_recent_pr_patch_chain = get_most_recent_patch_with_ancestors(commits_events) | 132 | let most_recent_pr_patch_chain = get_most_recent_patch_with_ancestors(commits_events) |
| 132 | .context("cannot get most recent patch for PR")?; | 133 | .context("cannot get most recent patch for PR")?; |
| 133 | 134 | ||
| 134 | let branch_name = tag_value(&pr_events[selected_index], "branch-name")?; | 135 | let branch_name: String = if let Ok(cl) = event_to_cover_letter(&pr_events[selected_index]) { |
| 136 | if let Some(name) = cl.branch_name { | ||
| 137 | name | ||
| 138 | } else { | ||
| 139 | cl.title | ||
| 140 | .replace(' ', "-") | ||
| 141 | .chars() | ||
| 142 | .filter(|c| c.is_ascii_alphanumeric() || c.eq(&'/')) | ||
| 143 | .collect() | ||
| 144 | } | ||
| 145 | } else { | ||
| 146 | bail!("Placeholder not a cover letter") | ||
| 147 | }; | ||
| 135 | 148 | ||
| 136 | let applied = git_repo | 149 | let applied = git_repo |
| 137 | .apply_patch_chain(&branch_name, most_recent_pr_patch_chain) | 150 | .apply_patch_chain(&branch_name, most_recent_pr_patch_chain) |
| @@ -145,7 +158,6 @@ pub async fn launch( | |||
| 145 | applied.len(), | 158 | applied.len(), |
| 146 | ); | 159 | ); |
| 147 | } | 160 | } |
| 148 | |||
| 149 | Ok(()) | 161 | Ok(()) |
| 150 | } | 162 | } |
| 151 | 163 | ||
diff --git a/src/sub_commands/pull.rs b/src/sub_commands/pull.rs index c426510..f3ae81f 100644 --- a/src/sub_commands/pull.rs +++ b/src/sub_commands/pull.rs | |||
| @@ -8,6 +8,7 @@ use crate::{ | |||
| 8 | client::Connect, | 8 | client::Connect, |
| 9 | git::{Repo, RepoActions}, | 9 | git::{Repo, RepoActions}, |
| 10 | repo_ref, | 10 | repo_ref, |
| 11 | repo_ref::REPO_REF_KIND, | ||
| 11 | sub_commands::prs::{ | 12 | sub_commands::prs::{ |
| 12 | create::{PATCH_KIND, PR_KIND}, | 13 | create::{PATCH_KIND, PR_KIND}, |
| 13 | list::{get_most_recent_patch_with_ancestors, tag_value}, | 14 | list::{get_most_recent_patch_with_ancestors, tag_value}, |
| @@ -53,7 +54,12 @@ pub async fn launch() -> Result<()> { | |||
| 53 | vec![ | 54 | vec![ |
| 54 | nostr::Filter::default() | 55 | nostr::Filter::default() |
| 55 | .kind(nostr::Kind::Custom(PR_KIND)) | 56 | .kind(nostr::Kind::Custom(PR_KIND)) |
| 56 | .reference(format!("r-{root_commit}")), | 57 | .identifiers( |
| 58 | repo_ref | ||
| 59 | .maintainers | ||
| 60 | .iter() | ||
| 61 | .map(|m| format!("{REPO_REF_KIND}:{m}:{}", repo_ref.identifier)), | ||
| 62 | ), | ||
| 57 | ], | 63 | ], |
| 58 | ) | 64 | ) |
| 59 | .await? | 65 | .await? |
| @@ -62,7 +68,7 @@ pub async fn launch() -> Result<()> { | |||
| 62 | e.kind.as_u64() == PR_KIND | 68 | e.kind.as_u64() == PR_KIND |
| 63 | && e.tags | 69 | && e.tags |
| 64 | .iter() | 70 | .iter() |
| 65 | .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("r-{root_commit}"))) | 71 | .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("{root_commit}"))) |
| 66 | && tag_value(e, "branch-name") | 72 | && tag_value(e, "branch-name") |
| 67 | .unwrap_or_default() | 73 | .unwrap_or_default() |
| 68 | .eq(&branch_name) | 74 | .eq(&branch_name) |
diff --git a/src/sub_commands/push.rs b/src/sub_commands/push.rs index 037d512..61d5d46 100644 --- a/src/sub_commands/push.rs +++ b/src/sub_commands/push.rs | |||
| @@ -9,7 +9,7 @@ use crate::{ | |||
| 9 | client::Connect, | 9 | client::Connect, |
| 10 | git::{str_to_sha1, Repo, RepoActions}, | 10 | git::{str_to_sha1, Repo, RepoActions}, |
| 11 | login, | 11 | login, |
| 12 | repo_ref::{self, RepoRef}, | 12 | repo_ref::{self, RepoRef, REPO_REF_KIND}, |
| 13 | sub_commands::prs::{ | 13 | sub_commands::prs::{ |
| 14 | create::{generate_patch_event, send_events, PATCH_KIND, PR_KIND}, | 14 | create::{generate_patch_event, send_events, PATCH_KIND, PR_KIND}, |
| 15 | list::{get_most_recent_patch_with_ancestors, tag_value}, | 15 | list::{get_most_recent_patch_with_ancestors, tag_value}, |
| @@ -106,7 +106,7 @@ pub async fn launch(cli_args: &Cli) -> Result<()> { | |||
| 106 | &git_repo, | 106 | &git_repo, |
| 107 | &root_commit, | 107 | &root_commit, |
| 108 | commit, | 108 | commit, |
| 109 | pr_event.id, | 109 | Some(pr_event.id), |
| 110 | &keys, | 110 | &keys, |
| 111 | &repo_ref, | 111 | &repo_ref, |
| 112 | patch_events.last().map(nostr::Event::id), | 112 | patch_events.last().map(nostr::Event::id), |
| @@ -146,7 +146,12 @@ async fn fetch_pr_and_most_recent_patch_chain( | |||
| 146 | vec![ | 146 | vec![ |
| 147 | nostr::Filter::default() | 147 | nostr::Filter::default() |
| 148 | .kind(nostr::Kind::Custom(PR_KIND)) | 148 | .kind(nostr::Kind::Custom(PR_KIND)) |
| 149 | .reference(format!("r-{root_commit}")), | 149 | .identifiers( |
| 150 | repo_ref | ||
| 151 | .maintainers | ||
| 152 | .iter() | ||
| 153 | .map(|m| format!("{REPO_REF_KIND}:{m}:{}", repo_ref.identifier)), | ||
| 154 | ), | ||
| 150 | ], | 155 | ], |
| 151 | ) | 156 | ) |
| 152 | .await? | 157 | .await? |
| @@ -155,7 +160,7 @@ async fn fetch_pr_and_most_recent_patch_chain( | |||
| 155 | e.kind.as_u64() == PR_KIND | 160 | e.kind.as_u64() == PR_KIND |
| 156 | && e.tags | 161 | && e.tags |
| 157 | .iter() | 162 | .iter() |
| 158 | .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("r-{root_commit}"))) | 163 | .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("{root_commit}"))) |
| 159 | && tag_value(e, "branch-name") | 164 | && tag_value(e, "branch-name") |
| 160 | .unwrap_or_default() | 165 | .unwrap_or_default() |
| 161 | .eq(branch_name) | 166 | .eq(branch_name) |
diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index 94ada76..8128e98 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs | |||
| @@ -21,6 +21,8 @@ pub static TEST_KEY_1_SK_HEX: &str = | |||
| 21 | "08608a436aee4c07ea5c36f85cb17c58f52b3ad7094f9318cc777771f0bf218b"; | 21 | "08608a436aee4c07ea5c36f85cb17c58f52b3ad7094f9318cc777771f0bf218b"; |
| 22 | pub static TEST_KEY_1_NPUB: &str = | 22 | pub static TEST_KEY_1_NPUB: &str = |
| 23 | "npub175lyhnt6nn00qjw0v3navw9pxgv43txnku0tpxprl4h6mvpr6a5qlphudg"; | 23 | "npub175lyhnt6nn00qjw0v3navw9pxgv43txnku0tpxprl4h6mvpr6a5qlphudg"; |
| 24 | pub static TEST_KEY_1_PUBKEY_HEX: &str = | ||
| 25 | "f53e4bcd7a9cdef049cf6467d638a1321958acd3b71eb09823fd6fadb023d768"; | ||
| 24 | pub static TEST_KEY_1_DISPLAY_NAME: &str = "bob"; | 26 | pub static TEST_KEY_1_DISPLAY_NAME: &str = "bob"; |
| 25 | pub static TEST_KEY_1_ENCRYPTED: &str = "ncryptsec1qyq607h3cykxc3f2a44u89cdk336fptccn3fm5pf3nmf93d3c86qpunc7r6klwcn6lyszjy72wxwqq9aljg4pm6atvjrds9e248yhv76xfnt464265kgnjsvg8rlg06wg4sp9uljzfpu8zuaztcvfn2j8ggdrg8mldh850cy75efsyqqansert9wqmn4e6khpgvfz7h5le9"; | 27 | pub static TEST_KEY_1_ENCRYPTED: &str = "ncryptsec1qyq607h3cykxc3f2a44u89cdk336fptccn3fm5pf3nmf93d3c86qpunc7r6klwcn6lyszjy72wxwqq9aljg4pm6atvjrds9e248yhv76xfnt464265kgnjsvg8rlg06wg4sp9uljzfpu8zuaztcvfn2j8ggdrg8mldh850cy75efsyqqansert9wqmn4e6khpgvfz7h5le9"; |
| 26 | pub static TEST_KEY_1_ENCRYPTED_WEAK: &str = "ncryptsec1qy8ke0tjqnn8wt3w6lnc86c27ry3qrptxctjfcgruryxy0at238kwyjwsswd7z88thysruzw3awlrsxjvw5uptcd7vt70ft9rtkx00m8cgy3khm4hxa5d2gfnc6athnfruy2eyl6pkas8k34jg85z7xjqqadzfzh9rp0fzxqtw0tvxksac3n8yc98uksvuf93e0lcvqy8j6"; | 28 | pub static TEST_KEY_1_ENCRYPTED_WEAK: &str = "ncryptsec1qy8ke0tjqnn8wt3w6lnc86c27ry3qrptxctjfcgruryxy0at238kwyjwsswd7z88thysruzw3awlrsxjvw5uptcd7vt70ft9rtkx00m8cgy3khm4hxa5d2gfnc6athnfruy2eyl6pkas8k34jg85z7xjqqadzfzh9rp0fzxqtw0tvxksac3n8yc98uksvuf93e0lcvqy8j6"; |
diff --git a/tests/prs_create.rs b/tests/prs_create.rs index 8db45d7..6272ccd 100644 --- a/tests/prs_create.rs +++ b/tests/prs_create.rs | |||
| @@ -141,6 +141,15 @@ fn cli_message_creating_patches() -> Result<()> { | |||
| 141 | Ok(()) | 141 | Ok(()) |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | fn is_cover_letter(event: &nostr::Event) -> bool { | ||
| 145 | event.kind.as_u64().eq(&PR_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) | ||
| 146 | } | ||
| 147 | |||
| 148 | fn is_patch(event: &nostr::Event) -> bool { | ||
| 149 | event.kind.as_u64().eq(&PATCH_KIND) | ||
| 150 | && !event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) | ||
| 151 | } | ||
| 152 | |||
| 144 | mod sends_pr_and_2_patches_to_3_relays { | 153 | mod sends_pr_and_2_patches_to_3_relays { |
| 145 | use futures::join; | 154 | use futures::join; |
| 146 | use test_utils::relay::Relay; | 155 | use test_utils::relay::Relay; |
| @@ -258,11 +267,7 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 258 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 267 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 259 | for relay in [&r53, &r55, &r56] { | 268 | for relay in [&r53, &r55, &r56] { |
| 260 | assert_eq!( | 269 | assert_eq!( |
| 261 | relay | 270 | relay.events.iter().filter(|e| is_cover_letter(e)).count(), |
| 262 | .events | ||
| 263 | .iter() | ||
| 264 | .filter(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 265 | .count(), | ||
| 266 | 1, | 271 | 1, |
| 267 | ); | 272 | ); |
| 268 | } | 273 | } |
| @@ -275,11 +280,7 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 275 | let (_, _, r53, r55, _) = prep_run_create_pr().await?; | 280 | let (_, _, r53, r55, _) = prep_run_create_pr().await?; |
| 276 | for relay in [&r53, &r55] { | 281 | for relay in [&r53, &r55] { |
| 277 | assert_eq!( | 282 | assert_eq!( |
| 278 | relay | 283 | relay.events.iter().filter(|e| is_cover_letter(e)).count(), |
| 279 | .events | ||
| 280 | .iter() | ||
| 281 | .filter(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 282 | .count(), | ||
| 283 | 1, | 284 | 1, |
| 284 | ); | 285 | ); |
| 285 | } | 286 | } |
| @@ -292,12 +293,8 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 292 | let (_, _, _, r55, r56) = prep_run_create_pr().await?; | 293 | let (_, _, _, r55, r56) = prep_run_create_pr().await?; |
| 293 | for relay in [&r55, &r56] { | 294 | for relay in [&r55, &r56] { |
| 294 | assert_eq!( | 295 | assert_eq!( |
| 295 | relay | 296 | relay.events.iter().filter(|e| is_cover_letter(e)).count(), |
| 296 | .events | 297 | 1 |
| 297 | .iter() | ||
| 298 | .filter(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 299 | .count(), | ||
| 300 | 1, | ||
| 301 | ); | 298 | ); |
| 302 | } | 299 | } |
| 303 | Ok(()) | 300 | Ok(()) |
| @@ -309,11 +306,7 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 309 | let (r51, r52, _, _, _) = prep_run_create_pr().await?; | 306 | let (r51, r52, _, _, _) = prep_run_create_pr().await?; |
| 310 | for relay in [&r51, &r52] { | 307 | for relay in [&r51, &r52] { |
| 311 | assert_eq!( | 308 | assert_eq!( |
| 312 | relay | 309 | relay.events.iter().filter(|e| is_cover_letter(e)).count(), |
| 313 | .events | ||
| 314 | .iter() | ||
| 315 | .filter(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 316 | .count(), | ||
| 317 | 0, | 310 | 0, |
| 318 | ); | 311 | ); |
| 319 | } | 312 | } |
| @@ -325,14 +318,7 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 325 | async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> { | 318 | async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> { |
| 326 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 319 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 327 | for relay in [&r53, &r55, &r56] { | 320 | for relay in [&r53, &r55, &r56] { |
| 328 | assert_eq!( | 321 | assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2,); |
| 329 | relay | ||
| 330 | .events | ||
| 331 | .iter() | ||
| 332 | .filter(|e| e.kind.as_u64().eq(&PATCH_KIND)) | ||
| 333 | .count(), | ||
| 334 | 2, | ||
| 335 | ); | ||
| 336 | } | 322 | } |
| 337 | Ok(()) | 323 | Ok(()) |
| 338 | } | 324 | } |
| @@ -343,11 +329,8 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 343 | { | 329 | { |
| 344 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 330 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 345 | for relay in [&r53, &r55, &r56] { | 331 | for relay in [&r53, &r55, &r56] { |
| 346 | let patch_events: Vec<&nostr::Event> = relay | 332 | let patch_events: Vec<&nostr::Event> = |
| 347 | .events | 333 | relay.events.iter().filter(|e| is_patch(e)).collect(); |
| 348 | .iter() | ||
| 349 | .filter(|e| e.kind.as_u64().eq(&PATCH_KIND)) | ||
| 350 | .collect(); | ||
| 351 | 334 | ||
| 352 | assert_eq!( | 335 | assert_eq!( |
| 353 | patch_events[0].content, | 336 | patch_events[0].content, |
| @@ -410,21 +393,19 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 410 | 393 | ||
| 411 | #[tokio::test] | 394 | #[tokio::test] |
| 412 | #[serial] | 395 | #[serial] |
| 413 | async fn pr_tags_repo_commit() -> Result<()> { | 396 | async fn root_commit_as_r() -> Result<()> { |
| 414 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 397 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 415 | let root_commit = GitTestRepo::default().initial_commit()?; | ||
| 416 | |||
| 417 | for relay in [&r53, &r55, &r56] { | 398 | for relay in [&r53, &r55, &r56] { |
| 418 | let pr_event: &nostr::Event = relay | 399 | let pr_event: &nostr::Event = |
| 419 | .events | 400 | relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); |
| 420 | .iter() | ||
| 421 | .find(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 422 | .unwrap(); | ||
| 423 | 401 | ||
| 424 | // root commit 'r' tag | 402 | assert_eq!( |
| 425 | assert!( | 403 | pr_event |
| 426 | pr_event.tags.iter().any(|t| t.as_vec()[0].eq("r") | 404 | .iter_tags() |
| 427 | && t.as_vec()[1].eq(&format!("r-{}", root_commit))) | 405 | .find(|t| t.as_vec()[0].eq("r")) |
| 406 | .unwrap() | ||
| 407 | .as_vec()[1], | ||
| 408 | "9ee507fc4357d7ee16a5d8901bedcd103f23c17d" | ||
| 428 | ); | 409 | ); |
| 429 | } | 410 | } |
| 430 | Ok(()) | 411 | Ok(()) |
| @@ -432,23 +413,55 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 432 | 413 | ||
| 433 | #[tokio::test] | 414 | #[tokio::test] |
| 434 | #[serial] | 415 | #[serial] |
| 435 | async fn pr_tags_title_as_name() -> Result<()> { | 416 | async fn a_tag_for_repo_event() -> Result<()> { |
| 436 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 417 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 437 | for relay in [&r53, &r55, &r56] { | 418 | for relay in [&r53, &r55, &r56] { |
| 438 | let pr_event: &nostr::Event = relay | 419 | let pr_event: &nostr::Event = |
| 439 | .events | 420 | relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); |
| 440 | .iter() | 421 | assert!(pr_event.iter_tags().any(|t| t.as_vec()[0].eq("a") |
| 441 | .find(|e| e.kind.as_u64().eq(&PR_KIND)) | 422 | && t.as_vec()[1].eq(&format!( |
| 442 | .unwrap(); | 423 | "{REPOSITORY_KIND}:{TEST_KEY_1_PUBKEY_HEX}:{}", |
| 424 | generate_repo_ref_event().identifier().unwrap() | ||
| 425 | )))); | ||
| 426 | } | ||
| 427 | Ok(()) | ||
| 428 | } | ||
| 443 | 429 | ||
| 444 | assert_eq!( | 430 | #[tokio::test] |
| 431 | #[serial] | ||
| 432 | async fn p_tags_for_maintainers() -> Result<()> { | ||
| 433 | let maintainers = &generate_repo_ref_event() | ||
| 434 | .iter_tags() | ||
| 435 | .find(|t| t.as_vec()[0].eq(&"maintainers")) | ||
| 436 | .unwrap() | ||
| 437 | .as_vec() | ||
| 438 | .clone()[1..]; | ||
| 439 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | ||
| 440 | for relay in [&r53, &r55, &r56] { | ||
| 441 | for m in maintainers { | ||
| 442 | let pr_event: &nostr::Event = | ||
| 443 | relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); | ||
| 444 | assert!( | ||
| 445 | pr_event | ||
| 446 | .iter_tags() | ||
| 447 | .any(|t| { t.as_vec()[0].eq("p") && t.as_vec()[1].eq(m) }) | ||
| 448 | ); | ||
| 449 | } | ||
| 450 | } | ||
| 451 | Ok(()) | ||
| 452 | } | ||
| 453 | |||
| 454 | #[tokio::test] | ||
| 455 | #[serial] | ||
| 456 | async fn t_tag_cover_letter() -> Result<()> { | ||
| 457 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | ||
| 458 | for relay in [&r53, &r55, &r56] { | ||
| 459 | let pr_event: &nostr::Event = | ||
| 460 | relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); | ||
| 461 | assert!( | ||
| 445 | pr_event | 462 | pr_event |
| 446 | .tags | 463 | .iter_tags() |
| 447 | .iter() | 464 | .any(|t| { t.as_vec()[0].eq("t") && t.as_vec()[1].eq(&"cover-letter") }) |
| 448 | .find(|t| t.as_vec()[0].eq("name")) | ||
| 449 | .unwrap() | ||
| 450 | .as_vec()[1], | ||
| 451 | "exampletitle" | ||
| 452 | ); | 465 | ); |
| 453 | } | 466 | } |
| 454 | Ok(()) | 467 | Ok(()) |
| @@ -456,23 +469,15 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 456 | 469 | ||
| 457 | #[tokio::test] | 470 | #[tokio::test] |
| 458 | #[serial] | 471 | #[serial] |
| 459 | async fn pr_tags_description() -> Result<()> { | 472 | async fn t_tag_root() -> Result<()> { |
| 460 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 473 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 461 | for relay in [&r53, &r55, &r56] { | 474 | for relay in [&r53, &r55, &r56] { |
| 462 | let pr_event: &nostr::Event = relay | 475 | let pr_event: &nostr::Event = |
| 463 | .events | 476 | relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); |
| 464 | .iter() | 477 | assert!( |
| 465 | .find(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 466 | .unwrap(); | ||
| 467 | |||
| 468 | assert_eq!( | ||
| 469 | pr_event | 478 | pr_event |
| 470 | .tags | 479 | .iter_tags() |
| 471 | .iter() | 480 | .any(|t| { t.as_vec()[0].eq("t") && t.as_vec()[1].eq(&"root") }) |
| 472 | .find(|t| t.as_vec()[0].eq("description")) | ||
| 473 | .unwrap() | ||
| 474 | .as_vec()[1], | ||
| 475 | "exampledescription" | ||
| 476 | ); | 481 | ); |
| 477 | } | 482 | } |
| 478 | Ok(()) | 483 | Ok(()) |
| @@ -483,17 +488,13 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 483 | async fn pr_tags_branch_name() -> Result<()> { | 488 | async fn pr_tags_branch_name() -> Result<()> { |
| 484 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 489 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 485 | for relay in [&r53, &r55, &r56] { | 490 | for relay in [&r53, &r55, &r56] { |
| 486 | let pr_event: &nostr::Event = relay | 491 | let pr_event: &nostr::Event = |
| 487 | .events | 492 | relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); |
| 488 | .iter() | ||
| 489 | .find(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 490 | .unwrap(); | ||
| 491 | 493 | ||
| 492 | // branch-name tag | 494 | // branch-name tag |
| 493 | assert_eq!( | 495 | assert_eq!( |
| 494 | pr_event | 496 | pr_event |
| 495 | .tags | 497 | .iter_tags() |
| 496 | .iter() | ||
| 497 | .find(|t| t.as_vec()[0].eq("branch-name")) | 498 | .find(|t| t.as_vec()[0].eq("branch-name")) |
| 498 | .unwrap() | 499 | .unwrap() |
| 499 | .as_vec()[1], | 500 | .as_vec()[1], |
| @@ -509,12 +510,7 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 509 | 510 | ||
| 510 | async fn prep() -> Result<nostr::Event> { | 511 | async fn prep() -> Result<nostr::Event> { |
| 511 | let (_, _, r53, _, _) = prep_run_create_pr().await?; | 512 | let (_, _, r53, _, _) = prep_run_create_pr().await?; |
| 512 | Ok(r53 | 513 | Ok(r53.events.iter().find(|e| is_patch(e)).unwrap().clone()) |
| 513 | .events | ||
| 514 | .iter() | ||
| 515 | .find(|e| e.kind.as_u64().eq(&PATCH_KIND)) | ||
| 516 | .unwrap() | ||
| 517 | .clone()) | ||
| 518 | } | 514 | } |
| 519 | 515 | ||
| 520 | #[tokio::test] | 516 | #[tokio::test] |
| @@ -561,6 +557,39 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 561 | 557 | ||
| 562 | #[tokio::test] | 558 | #[tokio::test] |
| 563 | #[serial] | 559 | #[serial] |
| 560 | async fn p_tags_for_maintainers() -> Result<()> { | ||
| 561 | let maintainers = &generate_repo_ref_event() | ||
| 562 | .iter_tags() | ||
| 563 | .find(|t| t.as_vec()[0].eq(&"maintainers")) | ||
| 564 | .unwrap() | ||
| 565 | .as_vec() | ||
| 566 | .clone()[1..]; | ||
| 567 | for m in maintainers { | ||
| 568 | assert!( | ||
| 569 | prep() | ||
| 570 | .await? | ||
| 571 | .iter_tags() | ||
| 572 | .any(|t| { t.as_vec()[0].eq("p") && t.as_vec()[1].eq(m) }) | ||
| 573 | ); | ||
| 574 | } | ||
| 575 | Ok(()) | ||
| 576 | } | ||
| 577 | |||
| 578 | #[tokio::test] | ||
| 579 | #[serial] | ||
| 580 | async fn a_tag_for_repo_event() -> Result<()> { | ||
| 581 | assert!(prep().await?.tags.iter().any(|t| { | ||
| 582 | t.as_vec()[0].eq("a") | ||
| 583 | && t.as_vec()[1].eq(&format!( | ||
| 584 | "{REPOSITORY_KIND}:{TEST_KEY_1_PUBKEY_HEX}:{}", | ||
| 585 | generate_repo_ref_event().identifier().unwrap() | ||
| 586 | )) | ||
| 587 | })); | ||
| 588 | Ok(()) | ||
| 589 | } | ||
| 590 | |||
| 591 | #[tokio::test] | ||
| 592 | #[serial] | ||
| 564 | async fn description_with_commit_message() -> Result<()> { | 593 | async fn description_with_commit_message() -> Result<()> { |
| 565 | assert_eq!( | 594 | assert_eq!( |
| 566 | prep() | 595 | prep() |
| @@ -612,18 +641,11 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 612 | async fn patch_tags_pr_event_as_root() -> Result<()> { | 641 | async fn patch_tags_pr_event_as_root() -> Result<()> { |
| 613 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; | 642 | let (_, _, r53, r55, r56) = prep_run_create_pr().await?; |
| 614 | for relay in [&r53, &r55, &r56] { | 643 | for relay in [&r53, &r55, &r56] { |
| 615 | let patch_events: Vec<&nostr::Event> = relay | 644 | let patch_events: Vec<&nostr::Event> = |
| 616 | .events | 645 | relay.events.iter().filter(|e| is_patch(e)).collect(); |
| 617 | .iter() | ||
| 618 | .filter(|e| e.kind.as_u64().eq(&PATCH_KIND)) | ||
| 619 | .collect(); | ||
| 620 | 646 | ||
| 621 | let most_recent_patch = patch_events[0]; | 647 | let most_recent_patch = patch_events[0]; |
| 622 | let pr_event = relay | 648 | let pr_event = relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); |
| 623 | .events | ||
| 624 | .iter() | ||
| 625 | .find(|e| e.kind.as_u64().eq(&PR_KIND)) | ||
| 626 | .unwrap(); | ||
| 627 | 649 | ||
| 628 | let root_event_tag = most_recent_patch | 650 | let root_event_tag = most_recent_patch |
| 629 | .tags | 651 | .tags |
| @@ -892,3 +914,8 @@ mod sends_pr_and_2_patches_to_3_relays { | |||
| 892 | } | 914 | } |
| 893 | } | 915 | } |
| 894 | } | 916 | } |
| 917 | |||
| 918 | mod without_cover_letter { | ||
| 919 | use super::*; | ||
| 920 | // TODO | ||
| 921 | } | ||