From 5618fd9883d45de1443a40abada944cbe3bb8dfd Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Fri, 9 Aug 2024 08:35:53 +0100 Subject: feat(remote): `push` new proposal issue new proposal when new branch is pushed into `prs/*` namespace, which doesn't match an existing proposal --- src/git_remote_helper.rs | 20 +++++++- src/sub_commands/send.rs | 14 +++++- tests/git_remote_helper.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 4 deletions(-) diff --git a/src/git_remote_helper.rs b/src/git_remote_helper.rs index 6997dfa..97db69a 100644 --- a/src/git_remote_helper.rs +++ b/src/git_remote_helper.rs @@ -814,8 +814,24 @@ async fn push( rejected_proposal_refspecs.push(refspec.to_string()); } } else { - // TODO new proposal / proposal no longer open - // / we couldn't + // TODO new proposal / couldn't find exisiting proposal + let (_, main_tip) = git_repo.get_main_or_master_branch()?; + let (mut ahead, _) = + git_repo.get_commits_ahead_behind(&main_tip, &tip_of_pushed_branch)?; + ahead.reverse(); + for patch in generate_cover_letter_and_patch_events( + None, + git_repo, + &ahead, + &signer, + repo_ref, + &None, + &[], + ) + .await? + { + events.push(patch); + } } } } diff --git a/src/sub_commands/send.rs b/src/sub_commands/send.rs index f492734..a005bd7 100644 --- a/src/sub_commands/send.rs +++ b/src/sub_commands/send.rs @@ -648,7 +648,11 @@ pub async fn generate_cover_letter_and_patch_events( vec![ Tag::custom( nostr::TagKind::Custom(std::borrow::Cow::Borrowed("branch-name")), - vec![branch_name], + vec![if let Some(branch_name) = branch_name.strip_prefix("prs/") { + branch_name.to_string() + } else { + branch_name + }], ), ] } @@ -687,7 +691,13 @@ pub async fn generate_cover_letter_and_patch_events( && !branch_name.eq("origin/main") && !branch_name.eq("origin/master") { - Some(branch_name) + Some( + if let Some(branch_name) = branch_name.strip_prefix("prs/") { + branch_name.to_string() + } else { + branch_name + }, + ) } else { None } diff --git a/tests/git_remote_helper.rs b/tests/git_remote_helper.rs index 7cf6799..17138e4 100644 --- a/tests/git_remote_helper.rs +++ b/tests/git_remote_helper.rs @@ -2004,4 +2004,126 @@ mod push { Ok(()) } + + #[tokio::test] + #[serial] + async fn push_new_pr_branch_creates_proposal() -> Result<()> { + let (events, source_git_repo) = prep_source_repo_and_events_including_proposals().await?; + let source_path = source_git_repo.dir.to_str().unwrap().to_string(); + + let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( + Relay::new(8051, None, None), + Relay::new(8052, None, None), + Relay::new(8053, None, None), + Relay::new(8055, None, None), + Relay::new(8056, None, None), + Relay::new(8057, None, None), + ); + r51.events = events.clone(); + r55.events = events.clone(); + + let before = r55.events.iter().cloned().collect::>(); + let branch_name = "prs/my-new-proposal"; + + let cli_tester_handle = std::thread::spawn(move || -> Result { + let mut git_repo = clone_git_repo_with_nostr_url()?; + git_repo.delete_dir_on_drop = false; + git_repo.create_branch(branch_name)?; + git_repo.checkout(branch_name)?; + + std::fs::write(git_repo.dir.join("new.md"), "some content")?; + git_repo.stage_and_commit("new.md")?; + + std::fs::write(git_repo.dir.join("new2.md"), "some content")?; + git_repo.stage_and_commit("new2.md")?; + + let mut p = CliTester::new_git_with_remote_helper_from_dir( + &git_repo.dir, + ["push", "-u", "origin", branch_name], + ); + cli_expect_nostr_fetch(&mut p)?; + p.expect(format!("fetching refs list: {}...\r\n\r", source_path).as_str())?; + p.expect(format!("To {}\r\n", get_nostr_remote_url()?).as_str())?; + let output = p.expect_end_eventually()?; + + for p in [51, 52, 53, 55, 56, 57] { + relay::shutdown_relay(8000 + p)?; + } + + Ok(output) + }); + // launch relays + let _ = join!( + r51.listen_until_close(), + r52.listen_until_close(), + r53.listen_until_close(), + r55.listen_until_close(), + r56.listen_until_close(), + r57.listen_until_close(), + ); + + let output = cli_tester_handle.join().unwrap()?; + + assert_eq!( + output, + format!(" * [new branch] {branch_name} -> {branch_name}\r\nbranch '{branch_name}' set up to track 'origin/{branch_name}'.\r\n").as_str(), + ); + + let new_events = r55 + .events + .iter() + .cloned() + .collect::>() + .difference(&before) + .cloned() + .collect::>(); + assert_eq!(new_events.len(), 2); + + let proposal = new_events + .iter() + .find(|e| e.iter_tags().any(|t| t.as_vec()[1].eq("root"))) + .unwrap(); + + assert!( + proposal.content.contains("new.md"), + "first patch is proposal root" + ); + + assert!( + proposal.content.contains("[PATCH 1/2]"), + "proposal root labeled with[PATCH 1/2] event: {proposal:?}", + ); + + assert_eq!( + proposal + .iter_tags() + .find(|t| t.as_vec()[0].eq("branch-name")) + .unwrap() + .as_vec()[1], + branch_name.replace("prs/", ""), + ); + + let second_patch = new_events + .iter() + .find(|e| e.content.contains("new2.md")) + .unwrap(); + + assert!( + second_patch.content.contains("[PATCH 2/2]"), + "second patch labeled with [PATCH 2/2]" + ); + + assert_eq!( + proposal.id().to_string(), + second_patch + .tags + .iter() + .find(|t| t.is_root()) + .unwrap() + .as_vec()[1], + "second patch sets proposal id as root" + ); + + Ok(()) + } } -- cgit v1.2.3