From ef552c12a6604c4b834f80b68c342d7f9668aa4b Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Wed, 27 Nov 2024 10:13:19 +0000 Subject: feat: remove `pull` `push` and `fetch` ngit cmds to simplify the api and encourage use of the git remote helper --- src/bin/ngit/cli.rs | 6 - src/bin/ngit/main.rs | 3 - src/bin/ngit/sub_commands/fetch.rs | 37 --- src/bin/ngit/sub_commands/mod.rs | 3 - src/bin/ngit/sub_commands/pull.rs | 203 ------------ src/bin/ngit/sub_commands/push.rs | 215 ------------- tests/ngit_pull.rs | 617 ------------------------------------- tests/ngit_push.rs | 531 ------------------------------- 8 files changed, 1615 deletions(-) delete mode 100644 src/bin/ngit/sub_commands/fetch.rs delete mode 100644 src/bin/ngit/sub_commands/pull.rs delete mode 100644 src/bin/ngit/sub_commands/push.rs delete mode 100644 tests/ngit_pull.rs delete mode 100644 tests/ngit_push.rs diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs index 9caf4d7..3a5b4e7 100644 --- a/src/bin/ngit/cli.rs +++ b/src/bin/ngit/cli.rs @@ -53,18 +53,12 @@ pub fn extract_signer_cli_arguments(args: &Cli) -> Result> { #[derive(Subcommand)] pub enum Commands { - /// update cache with latest updates from nostr - Fetch(sub_commands::fetch::SubCommandArgs), /// signal you are this repo's maintainer accepting proposals via nostr Init(sub_commands::init::SubCommandArgs), /// issue commits as a proposal Send(sub_commands::send::SubCommandArgs), /// list proposals; checkout, apply or download selected List, - /// send proposal revision - Push(sub_commands::push::SubCommandArgs), - /// fetch and apply new proposal commits / revisions linked to branch - Pull, /// login, logout or export keys Account(AccountSubCommandArgs), } diff --git a/src/bin/ngit/main.rs b/src/bin/ngit/main.rs index a49267b..a6e3e11 100644 --- a/src/bin/ngit/main.rs +++ b/src/bin/ngit/main.rs @@ -20,11 +20,8 @@ async fn main() -> Result<()> { AccountCommands::Logout => sub_commands::logout::launch().await, AccountCommands::ExportKeys => sub_commands::export_keys::launch().await, }, - Commands::Fetch(args) => sub_commands::fetch::launch(&cli, args).await, Commands::Init(args) => sub_commands::init::launch(&cli, args).await, Commands::List => sub_commands::list::launch().await, - Commands::Pull => sub_commands::pull::launch().await, - Commands::Push(args) => sub_commands::push::launch(&cli, args).await, Commands::Send(args) => sub_commands::send::launch(&cli, args, false).await, } } diff --git a/src/bin/ngit/sub_commands/fetch.rs b/src/bin/ngit/sub_commands/fetch.rs deleted file mode 100644 index dc548fd..0000000 --- a/src/bin/ngit/sub_commands/fetch.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::collections::HashSet; - -use anyhow::{Context, Result}; -use clap; -use nostr::nips::nip01::Coordinate; - -use crate::{ - cli::Cli, - client::{fetching_with_report, Client, Connect}, - git::{Repo, RepoActions}, - repo_ref::get_repo_coordinates, -}; - -#[derive(clap::Args)] -pub struct SubCommandArgs { - /// address pointer to repo announcement - #[arg(long, action)] - repo: Vec, -} - -pub async fn launch(args: &Cli, command_args: &SubCommandArgs) -> Result<()> { - let _ = args; - let git_repo = Repo::discover().context("failed to find a git repository")?; - let client = Client::default(); - let repo_coordinates = if command_args.repo.is_empty() { - get_repo_coordinates(&git_repo, &client).await? - } else { - let mut repo_coordinates = HashSet::new(); - for repo in &command_args.repo { - repo_coordinates.insert(Coordinate::parse(repo.clone())?); - } - repo_coordinates - }; - fetching_with_report(git_repo.get_path()?, &client, &repo_coordinates).await?; - client.disconnect().await?; - Ok(()) -} diff --git a/src/bin/ngit/sub_commands/mod.rs b/src/bin/ngit/sub_commands/mod.rs index b6b1e3b..b59b88f 100644 --- a/src/bin/ngit/sub_commands/mod.rs +++ b/src/bin/ngit/sub_commands/mod.rs @@ -1,9 +1,6 @@ pub mod export_keys; -pub mod fetch; pub mod init; pub mod list; pub mod login; pub mod logout; -pub mod pull; -pub mod push; pub mod send; diff --git a/src/bin/ngit/sub_commands/pull.rs b/src/bin/ngit/sub_commands/pull.rs deleted file mode 100644 index f459c8e..0000000 --- a/src/bin/ngit/sub_commands/pull.rs +++ /dev/null @@ -1,203 +0,0 @@ -use anyhow::{bail, Context, Result}; -use ngit::git_events::is_event_proposal_root_for_branch; -use nostr_sdk::PublicKey; - -use crate::{ - client::{ - fetching_with_report, get_all_proposal_patch_events_from_cache, - get_proposals_and_revisions_from_cache, get_repo_ref_from_cache, Client, Connect, - }, - git::{str_to_sha1, Repo, RepoActions}, - git_events::{get_commit_id_from_patch, get_most_recent_patch_with_ancestors, tag_value}, - repo_ref::get_repo_coordinates, -}; - -#[allow(clippy::too_many_lines)] -pub async fn launch() -> Result<()> { - let git_repo = Repo::discover().context("failed to find a git repository")?; - let git_repo_path = git_repo.get_path()?; - - let (main_or_master_branch_name, _) = git_repo - .get_main_or_master_branch() - .context("no main or master branch")?; - - let branch_name = git_repo - .get_checked_out_branch_name() - .context("failed to get checked out branch name")?; - - if branch_name == main_or_master_branch_name { - bail!("checkout a branch associated with a proposal first") - } - let client = Client::default(); - - let repo_coordinates = get_repo_coordinates(&git_repo, &client).await?; - fetching_with_report(git_repo_path, &client, &repo_coordinates).await?; - - let repo_ref = get_repo_ref_from_cache(Some(git_repo_path), &repo_coordinates).await?; - - let logged_in_public_key = - if let Ok(Some(npub)) = git_repo.get_git_config_item("nostr.npub", None) { - PublicKey::parse(npub).ok() - } else { - None - }; - - let proposal_root_event = - get_proposals_and_revisions_from_cache(git_repo_path, repo_ref.coordinates()) - .await? - .iter() - .find(|e| { - is_event_proposal_root_for_branch(e, &branch_name, &logged_in_public_key) - .unwrap_or(false) - }) - .context("failed to find proposal that matches the current branch name")? - .clone(); - - let commit_events = - get_all_proposal_patch_events_from_cache(git_repo_path, &repo_ref, &proposal_root_event.id) - .await?; - - let most_recent_proposal_patch_chain = - get_most_recent_patch_with_ancestors(commit_events.clone()) - .context("failed to get most recent patch for proposal")?; - - let local_branch_tip = git_repo.get_tip_of_branch(&branch_name)?; - - let (main_branch_name, master_tip) = git_repo.get_main_or_master_branch()?; - - let (local_ahead_of_main, local_beind_main) = - git_repo.get_commits_ahead_behind(&master_tip, &local_branch_tip)?; - - let proposal_base_commit = str_to_sha1(&tag_value( - most_recent_proposal_patch_chain - .last() - .context("there should be at least one patch as we have already checked for this")?, - "parent-commit", - )?) - .context("failed to get valid parent commit id from patch")?; - - let (_, proposal_behind_main) = - git_repo.get_commits_ahead_behind(&master_tip, &proposal_base_commit)?; - - let proposal_tip = - str_to_sha1( - &get_commit_id_from_patch(most_recent_proposal_patch_chain.first().context( - "there should be at least one patch as we have already checked for this", - )?) - .context("failed to get valid commit_id from patch")?, - ) - .context("failed to get valid commit_id from patch")?; - - // if uptodate - if proposal_tip.eq(&local_branch_tip) { - println!("branch already up-to-date"); - } - // if new appendments - else if most_recent_proposal_patch_chain.iter().any(|patch| { - get_commit_id_from_patch(patch) - .unwrap_or_default() - .eq(&local_branch_tip.to_string()) - }) { - check_clean(&git_repo)?; - let applied = git_repo - .apply_patch_chain(&branch_name, most_recent_proposal_patch_chain) - .context("failed to apply patch chain")?; - println!("applied {} new commits", applied.len(),); - } - // if parent commit doesnt exist - else if !git_repo.does_commit_exist(&proposal_base_commit.to_string())? { - println!( - "a new version of the proposal has a prant commit that doesnt exist in your local repository." - ); - println!("your '{main_branch_name}' branch may not be up-to-date."); - println!("manually run `git pull` on '{main_branch_name}' and try again"); - } - // if new revision and no local changes (tip of local in proposal history) - else if commit_events.iter().any(|patch| { - get_commit_id_from_patch(patch) - .unwrap_or_default() - .eq(&local_branch_tip.to_string()) - }) { - check_clean(&git_repo)?; - - git_repo.create_branch_at_commit(&branch_name, &proposal_base_commit.to_string())?; - let applied = git_repo - .apply_patch_chain(&branch_name, most_recent_proposal_patch_chain) - .context("failed to apply patch chain")?; - - println!( - "pulled new version of proposal ({} ahead {} behind '{main_branch_name}'), replacing old version ({} ahead {} behind '{main_branch_name}')", - applied.len(), - proposal_behind_main.len(), - local_ahead_of_main.len(), - local_beind_main.len(), - ); - } - // if tip of proposal in branch in history (local appendments made to up-to-date - // proposal) - else if git_repo.ancestor_of(&local_branch_tip, &proposal_tip)? { - let (local_ahead_of_proposal, _) = git_repo - .get_commits_ahead_behind(&proposal_tip, &local_branch_tip) - .context("failed to get commits ahead behind for propsal_top and local_branch_tip")?; - println!( - "local proposal branch exists with {} unpublished commits on top of the most up-to-date version of the proposal", - local_ahead_of_proposal.len() - ); - } else { - println!("you have an amended/rebase version the proposal that is unpublished"); - // user probably has a unpublished amended or rebase version of the latest - // proposal version - // if tip of proposal commits exist (were once part of branch but have been - // amended and git clean up job hasn't removed them) - if git_repo.does_commit_exist(&proposal_tip.to_string())? { - println!( - "you have previously applied the latest version of the proposal ({} ahead {} behind '{main_branch_name}') but your local proposal branch has amended or rebased it ({} ahead {} behind '{main_branch_name}')", - most_recent_proposal_patch_chain.len(), - proposal_behind_main.len(), - local_ahead_of_main.len(), - local_beind_main.len(), - ); - } - // user probably has a unpublished amended or rebase version of an older - // proposal version - else { - println!( - "your local proposal branch ({} ahead {} behind '{main_branch_name}') has conflicting changes with the latest published proposal ({} ahead {} behind '{main_branch_name}')", - local_ahead_of_main.len(), - local_beind_main.len(), - most_recent_proposal_patch_chain.len(), - proposal_behind_main.len(), - ); - - println!( - "its likely that you have rebased / amended an old proposal version because git has no record of the latest proposal commit." - ); - println!( - "it is possible that you have been working off the latest version and git has delete this commit as part of a clean up" - ); - } - println!("to view the latest proposal but retain your changes:"); - println!(" 1) create a new branch off the tip commit of this one to store your changes"); - println!(" 2) run `ngit list` and checkout the latest published version of this proposal"); - - println!("if you are confident in your changes consider running `ngit push --force`"); - - // TODO: this copy could be refined further based on this: - // - amended commits in the proposal - // - if local_base eq proposal base - // - amended an older version of proposal - // - if local_base is behind proposal_base - // - rebased the proposal - // - if local_base is ahead of proposal_base - } - Ok(()) -} - -fn check_clean(git_repo: &Repo) -> Result<()> { - if git_repo.has_outstanding_changes()? { - bail!( - "failed to pull proposal branch when repository is not clean. discard or stash (un)staged changes and try again." - ); - } - Ok(()) -} diff --git a/src/bin/ngit/sub_commands/push.rs b/src/bin/ngit/sub_commands/push.rs deleted file mode 100644 index 89b2364..0000000 --- a/src/bin/ngit/sub_commands/push.rs +++ /dev/null @@ -1,215 +0,0 @@ -use anyhow::{bail, Context, Result}; -use ngit::{ - client::send_events, - git_events::{is_event_proposal_root_for_branch, tag_value}, -}; -use nostr_sdk::PublicKey; - -use crate::{ - cli::{extract_signer_cli_arguments, Cli}, - client::{ - fetching_with_report, get_all_proposal_patch_events_from_cache, - get_proposals_and_revisions_from_cache, get_repo_ref_from_cache, Client, Connect, - }, - git::{identify_ahead_behind, str_to_sha1, Repo, RepoActions}, - git_events::{ - generate_patch_event, get_commit_id_from_patch, get_most_recent_patch_with_ancestors, - }, - login, - repo_ref::get_repo_coordinates, - sub_commands, -}; - -#[derive(Debug, clap::Args)] -pub struct SubCommandArgs { - #[arg(long, action)] - /// send proposal revision from checked out proposal branch - force: bool, -} - -#[allow(clippy::too_many_lines)] -pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { - let git_repo = Repo::discover().context("failed to find a git repository")?; - let git_repo_path = git_repo.get_path()?; - - let (main_or_master_branch_name, _) = git_repo - .get_main_or_master_branch() - .context("no main or master branch")?; - - let root_commit = git_repo - .get_root_commit() - .context("failed to get root commit of the repository")?; - - let branch_name = git_repo - .get_checked_out_branch_name() - .context("failed to get checked out branch name")?; - - if branch_name == main_or_master_branch_name { - bail!("checkout a branch associated with a proposal first") - } - let mut client = Client::default(); - - let repo_coordinates = get_repo_coordinates(&git_repo, &client).await?; - - fetching_with_report(git_repo_path, &client, &repo_coordinates).await?; - - let repo_ref = get_repo_ref_from_cache(Some(git_repo_path), &repo_coordinates).await?; - - let logged_in_public_key = - if let Ok(Some(npub)) = git_repo.get_git_config_item("nostr.npub", None) { - PublicKey::parse(npub).ok() - } else { - None - }; - - let proposal_root_event = - get_proposals_and_revisions_from_cache(git_repo_path, repo_ref.coordinates()) - .await? - .iter() - .find(|e| { - is_event_proposal_root_for_branch(e, &branch_name, &logged_in_public_key) - .unwrap_or(false) - }) - .context("failed to find proposal that matches the current branch name")? - .clone(); - - let commit_events = - get_all_proposal_patch_events_from_cache(git_repo_path, &repo_ref, &proposal_root_event.id) - .await?; - - let most_recent_proposal_patch_chain = get_most_recent_patch_with_ancestors(commit_events) - .context("failed to get most recent patch for proposal")?; - - let branch_tip = git_repo.get_tip_of_branch(&branch_name)?; - - let most_recent_patch_commit_id = str_to_sha1( - &get_commit_id_from_patch( - most_recent_proposal_patch_chain - .first() - .context("no patches found")?, - ) - .context("latest patch event doesnt have a commit tag")?, - ) - .context("latest patch event commit tag isn't a valid SHA1 hash")?; - - let proposal_base_commit_id = str_to_sha1( - &tag_value( - most_recent_proposal_patch_chain - .last() - .context("no patches found")?, - "parent-commit", - ) - .context("patch is incorrectly formatted")?, - ) - .context("latest patch event parent-commit tag isn't a valid SHA1 hash")?; - - if most_recent_patch_commit_id.eq(&branch_tip) { - bail!("proposal already up-to-date with local branch"); - } - - if args.force { - println!("preparing to force push proposal revision..."); - sub_commands::send::launch( - cli_args, - &sub_commands::send::SubCommandArgs { - // if not ahead of master prompt, otherwise assume proposal revision is all commits - // ahead - since_or_range: if let Ok((_, _, ahead, _)) = - identify_ahead_behind(&git_repo, &None, &None) - { - if ahead.is_empty() { - String::new() - } else { - format!("HEAD~{}", ahead.len()) - } - } else { - String::new() - }, - in_reply_to: vec![proposal_root_event.id.to_string()], - title: None, - description: None, - no_cover_letter: true, - }, - true, - ) - .await?; - println!("force pushed proposal revision"); - return Ok(()); - } - - if most_recent_proposal_patch_chain.iter().any(|e| { - let c = tag_value(e, "parent-commit").unwrap_or_default(); - c.eq(&branch_tip.to_string()) - }) { - bail!("proposal is ahead of local branch"); - } - - let Ok((ahead, behind)) = git_repo - .get_commits_ahead_behind(&most_recent_patch_commit_id, &branch_tip) - .context("the latest patch in proposal doesnt share an ancestor with your branch.") - else { - if git_repo.ancestor_of(&proposal_base_commit_id, &branch_tip)? { - bail!("local unpublished proposal ammendments. consider force pushing."); - } - bail!("local unpublished proposal has been rebased. consider force pushing"); - }; - - if !behind.is_empty() { - bail!( - "your local proposal branch is {} behind patches on nostr. consider rebasing or force pushing", - behind.len() - ) - } - - println!( - "{} commits ahead. preparing to create creating patch events.", - ahead.len() - ); - - let (signer, user_ref, _) = login::login_or_signup( - &Some(&git_repo), - &extract_signer_cli_arguments(cli_args).unwrap_or(None), - &cli_args.password, - Some(&client), - ) - .await?; - - let mut patch_events: Vec = vec![]; - for commit in &ahead { - patch_events.push( - generate_patch_event( - &git_repo, - &root_commit, - commit, - Some(proposal_root_event.id), - &signer, - &repo_ref, - patch_events.last().map(|e| e.id), - None, - None, - &None, - &[], - ) - .await - .context("failed to make patch event from commit")?, - ); - } - println!("pushing {} commits", ahead.len()); - - client.set_signer(signer).await; - - send_events( - &client, - Some(git_repo_path), - patch_events, - user_ref.relays.write(), - repo_ref.relays.clone(), - !cli_args.disable_cli_spinners, - false, - ) - .await?; - - println!("pushed {} commits", ahead.len()); - - Ok(()) -} diff --git a/tests/ngit_pull.rs b/tests/ngit_pull.rs deleted file mode 100644 index 2fb9229..0000000 --- a/tests/ngit_pull.rs +++ /dev/null @@ -1,617 +0,0 @@ -use anyhow::Result; -use futures::join; -use serial_test::serial; -use test_utils::{git::GitTestRepo, relay::Relay, *}; - -mod when_main_is_checked_out { - use super::*; - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn cli_show_error() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - cli_tester_create_proposals()?; - - let test_repo = create_repo_with_proposal_branch_pulled_and_checkedout(1)?; - - test_repo.checkout("main")?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("Error: checkout a branch associated with a proposal first\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } -} - -mod when_branch_doesnt_exist { - use super::*; - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn cli_show_error() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - cli_tester_create_proposals()?; - - let test_repo = GitTestRepo::default(); - test_repo.populate()?; - - test_repo.create_branch("random-name")?; - test_repo.checkout("random-name")?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect( - "Error: failed to find proposal that matches the current branch name\r\n", - )?; - - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } -} - -mod when_branch_is_checked_out { - use super::*; - - mod when_branch_is_up_to_date { - use super::*; - - mod cli_prompts { - use super::*; - #[tokio::test] - #[serial] - async fn cli_show_up_to_date() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - let (_, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect("branch already up-to-date\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } - } - - mod when_branch_is_behind { - use super::*; - - async fn prep_and_run() -> Result<(GitTestRepo, GitTestRepo)> { - // fallback (51,52) user write (53, 55) repo (55, 56) - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = - std::thread::spawn(move || -> Result<(GitTestRepo, GitTestRepo)> { - let (originating_repo, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - let branch_name = - remove_latest_commit_so_proposal_branch_is_behind_and_checkout_main( - &test_repo, - )?; - test_repo.checkout(&branch_name)?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect_end_eventually()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok((originating_repo, test_repo)) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - let res = cli_tester_handle.join().unwrap()?; - - Ok(res) - } - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn cli_applied_1_commit() -> Result<()> { - // fallback (51,52) user write (53, 55) repo (55, 56) - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = - std::thread::spawn(move || -> Result<(GitTestRepo, GitTestRepo)> { - let (originating_repo, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - let branch_name = - remove_latest_commit_so_proposal_branch_is_behind_and_checkout_main( - &test_repo, - )?; - test_repo.checkout(&branch_name)?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect_end_with("applied 1 new commits\r\n")?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok((originating_repo, test_repo)) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - - Ok(()) - } - } - - #[tokio::test] - #[serial] - async fn proposal_branch_tip_is_most_recent_patch() -> Result<()> { - let (originating_repo, test_repo) = prep_and_run().await?; - assert_eq!( - originating_repo.get_tip_of_local_branch(FEATURE_BRANCH_NAME_1)?, - test_repo.get_tip_of_local_branch(&get_proposal_branch_name( - &test_repo, - FEATURE_BRANCH_NAME_1 - )?)?, - ); - Ok(()) - } - } - - mod when_latest_proposal_amended_locally { - use super::*; - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn cli_output_correct() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - let (_, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - amend_last_commit(&test_repo, "add ammended-commit.md")?; - - // run test - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect( - "you have an amended/rebase version the proposal that is unpublished\r\n", - )?; - p.expect("you have previously applied the latest version of the proposal (2 ahead 0 behind 'main') but your local proposal branch has amended or rebased it (2 ahead 0 behind 'main')\r\n")?; - p.expect("to view the latest proposal but retain your changes:\r\n")?; - p.expect(" 1) create a new branch off the tip commit of this one to store your changes\r\n")?; - p.expect(" 2) run `ngit list` and checkout the latest published version of this proposal\r\n")?; - p.expect("if you are confident in your changes consider running `ngit push --force`\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - println!("{:?}", r55.events); - Ok(()) - } - } - } - - mod when_local_commits_on_uptodate_proposal { - use super::*; - async fn prep_and_run() -> Result<(GitTestRepo, GitTestRepo)> { - // fallback (51,52) user write (53, 55) repo (55, 56) - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn( - move || -> Result<(GitTestRepo, GitTestRepo)> { - let (originating_repo, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - // add another commit (so we have a local branch 1 ahead) - std::fs::write(test_repo.dir.join("ammended-commit.md"), "some content")?; - test_repo.stage_and_commit("add ammended-commit.md")?; - - // run test - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect("local proposal branch exists with 1 unpublished commits on top of the most up-to-date version of the proposal\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok((originating_repo, test_repo)) - }, - ); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - let res = cli_tester_handle.join().unwrap()?; - - Ok(res) - } - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn prompts_to_choose_from_proposal_titles() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - let (_, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - // add another commit (so we have a local branch 1 ahead) - std::fs::write(test_repo.dir.join("ammended-commit.md"), "some content")?; - test_repo.stage_and_commit("add ammended-commit.md")?; - - // run test - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect("local proposal branch exists with 1 unpublished commits on top of the most up-to-date version of the proposal\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - println!("{:?}", r55.events); - Ok(()) - } - } - - #[tokio::test] - #[serial] - async fn didnt_overwrite_local_appendments() -> Result<()> { - let (originating_repo, test_repo) = prep_and_run().await?; - assert_ne!( - test_repo.get_tip_of_local_branch(&get_proposal_branch_name( - &test_repo, - FEATURE_BRANCH_NAME_1 - )?)?, - originating_repo.get_tip_of_local_branch(FEATURE_BRANCH_NAME_1)?, - ); - Ok(()) - } - } - mod when_latest_event_rebases_branch { - use tokio::task::JoinHandle; - - use super::*; - - async fn prep_and_run() -> Result<(GitTestRepo, GitTestRepo)> { - // fallback (51,52) user write (53, 55) repo (55, 56) - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle: JoinHandle> = - tokio::task::spawn_blocking(move || { - let (originating_repo, test_repo) = create_proposals_with_first_rebased_and_repo_with_latest_main_and_unrebased_proposal()?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect_end_eventually_and_print()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok((originating_repo, test_repo)) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - let res = cli_tester_handle.await??; - - Ok(res) - } - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn prompts_to_choose_from_proposal_titles() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle: JoinHandle> = tokio::task::spawn_blocking( - move || { - let (_, test_repo) = create_proposals_with_first_rebased_and_repo_with_latest_main_and_unrebased_proposal()?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["pull"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect_end_with("pulled new version of proposal (2 ahead 0 behind 'main'), replacing old version (2 ahead 1 behind 'main')\r\n")?; - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }, - ); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.await??; - println!("{:?}", r55.events); - Ok(()) - } - } - - #[tokio::test] - #[serial] - async fn proposal_branch_tip_is_most_recent_proposal_revision_tip() -> Result<()> { - let (originating_repo, test_repo) = prep_and_run().await?; - assert_eq!( - originating_repo.get_tip_of_local_branch(FEATURE_BRANCH_NAME_1)?, - test_repo.get_tip_of_local_branch(&get_proposal_branch_name( - &test_repo, - FEATURE_BRANCH_NAME_1 - )?)?, - ); - Ok(()) - } - } -} diff --git a/tests/ngit_push.rs b/tests/ngit_push.rs deleted file mode 100644 index d4b3894..0000000 --- a/tests/ngit_push.rs +++ /dev/null @@ -1,531 +0,0 @@ -use anyhow::Result; -use futures::join; -use serial_test::serial; -use test_utils::{git::GitTestRepo, relay::Relay, *}; - -mod when_main_is_checked_out { - use super::*; - - #[test] - fn cli_returns_error() -> Result<()> { - let test_repo = GitTestRepo::default(); - test_repo.populate()?; - create_and_populate_branch(&test_repo, FEATURE_BRANCH_NAME_1, "a", false)?; - test_repo.checkout("main")?; - let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]); - p.expect("Error: checkout a branch associated with a proposal first\r\n")?; - p.expect_end()?; - Ok(()) - } -} - -mod when_proposal_isnt_associated_with_branch_name { - use super::*; - - mod cli_prompts { - - use super::*; - - #[tokio::test] - #[serial] - async fn cli_show_error() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - cli_tester_create_proposals()?; - - let test_repo = GitTestRepo::default(); - test_repo.populate()?; - - test_repo.create_branch("random-name")?; - test_repo.checkout("random-name")?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect_end_with( - "Error: failed to find proposal that matches the current branch name\r\n", - )?; - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } -} - -mod when_branch_is_checked_out { - use super::*; - - mod when_branch_is_up_to_date { - use super::*; - - mod cli_prompts { - use super::*; - #[tokio::test] - #[serial] - async fn cli_show_up_to_date() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - let (_, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect_end_with("Error: proposal already up-to-date with local branch\r\n")?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } - } - - mod when_branch_is_behind { - use super::*; - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn cli_show_proposal_ahead_error() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - let (_, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - let branch_name = - remove_latest_commit_so_proposal_branch_is_behind_and_checkout_main( - &test_repo, - )?; - - test_repo.checkout(&branch_name)?; - // run test - let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect("Error: proposal is ahead of local branch\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } - } - - mod when_branch_is_ahead { - use super::*; - - mod cli_prompts { - use test_utils::relay::expect_send_with_progress; - - use super::*; - - #[tokio::test] - #[serial] - async fn cli_applied_1_commit() -> Result<()> { - // fallback (51,52) user write (53, 55) repo (55, 56) - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = - std::thread::spawn(move || -> Result<(GitTestRepo, GitTestRepo)> { - let (originating_repo, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - // add another commit (so we have an ammened local branch) - std::fs::write(test_repo.dir.join("ammended-commit.md"), "some content")?; - test_repo.stage_and_commit("add ammended-commit.md")?; - - // run test - let mut p = CliTester::new_from_dir( - &test_repo.dir, - [ - "--nsec", - TEST_KEY_1_NSEC, - "--password", - TEST_PASSWORD, - "--disable-cli-spinners", - "push", - ], - ); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect( - "1 commits ahead. preparing to create creating patch events.\r\n", - )?; - p.expect("logged in as fred via cli arguments\r\n")?; - p.expect("pushing 1 commits\r\n")?; - - expect_send_with_progress( - &mut p, - vec![ - (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), - (" [my-relay] ws://localhost:8053", true, ""), - (" [repo-relay] ws://localhost:8056", true, ""), - (" [default] ws://localhost:8051", true, ""), - (" [default] ws://localhost:8052", true, ""), - ], - 1, - )?; - p.expect_eventually("pushed 1 commits\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok((originating_repo, test_repo)) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - - Ok(()) - } - } - - async fn prep_and_run() -> Result<(GitTestRepo, Vec)> { - // fallback (51,52) user write (53, 55) repo (55, 56) - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result { - let (_, test_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - - // add another commit (so we have an ammened local branch) - std::fs::write(test_repo.dir.join("ammended-commit.md"), "some content")?; - test_repo.stage_and_commit("add ammended-commit.md")?; - - // run test - - let mut p = CliTester::new_from_dir( - &test_repo.dir, - [ - "--nsec", - TEST_KEY_1_NSEC, - "--password", - TEST_PASSWORD, - "--disable-cli-spinners", - "push", - ], - ); - p.expect_end_eventually()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(test_repo) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - let res = cli_tester_handle.join().unwrap()?; - - Ok((res, r55.events.clone())) - } - #[tokio::test] - #[serial] - async fn commits_issued_as_patch_event() -> Result<()> { - let (test_repo, r55_events) = prep_and_run().await?; - - let commit_id = test_repo - .get_tip_of_local_branch(&test_repo.get_checked_out_branch_name()?)? - .to_string(); - assert!(r55_events.iter().any(|e| { - e.tags - .iter() - .any(|t| t.as_slice()[0].eq("commit") && t.as_slice()[1].eq(&commit_id)) - })); - Ok(()) - } - } - - mod when_branch_has_been_rebased { - use super::*; - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn cli_shows_unpublished_rebase_error() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - let (_, tmp_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - let branch_name = tmp_repo.get_checked_out_branch_name()?; - - let test_repo = GitTestRepo::default(); - test_repo.populate()?; - - // simulate rebase - std::fs::write(test_repo.dir.join("amazing.md"), "some content")?; - test_repo.stage_and_commit("commit for rebasing on top of")?; - create_and_populate_branch(&test_repo, &branch_name, "a", true)?; - - let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]); - // p.expect_end_eventually_and_print()?; - - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect( - "Error: local unpublished proposal has been rebased. consider force pushing\r\n", - )?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } - mod with_force_flag { - use super::*; - - mod cli_prompts { - use super::*; - - #[tokio::test] - #[serial] - async fn cli_shows_revision_sent() -> Result<()> { - let (mut r51, mut r52, mut r53, mut r55, mut r56) = ( - 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), - ); - - r51.events.push(generate_test_key_1_relay_list_event()); - r51.events.push(generate_test_key_1_metadata_event("fred")); - r51.events.push(generate_repo_ref_event()); - - r55.events.push(generate_repo_ref_event()); - r55.events.push(generate_test_key_1_metadata_event("fred")); - r55.events.push(generate_test_key_1_relay_list_event()); - - let cli_tester_handle = std::thread::spawn(move || -> Result<()> { - let (_, tmp_repo) = - create_proposals_and_repo_with_proposal_pulled_and_checkedout(1)?; - let branch_name = tmp_repo.get_checked_out_branch_name()?; - - let test_repo = GitTestRepo::default(); - test_repo.populate()?; - - // simulate rebase - std::fs::write(test_repo.dir.join("amazing.md"), "some content")?; - test_repo.stage_and_commit("commit for rebasing on top of")?; - create_and_populate_branch(&test_repo, &branch_name, "a", false)?; - let mut p = CliTester::new_from_dir( - &test_repo.dir, - [ - "--nsec", - TEST_KEY_1_NSEC, - "--password", - TEST_PASSWORD, - "--disable-cli-spinners", - "push", - "--force", - ], - ); - p.expect("fetching updates...\r\n")?; - p.expect_eventually("\r\n")?; // some updates listed here - p.expect("preparing to force push proposal revision...\r\n")?; - // standard output from `ngit send` - p.expect("creating proposal revision for: ")?; - // proposal id will be printed in this gap - p.expect_eventually("\r\n")?; - p.expect("creating proposal from 2 commits:\r\n")?; - p.expect("355bdf1 add a4.md\r\n")?; - p.expect("dbd1115 add a3.md\r\n")?; - p.expect("logged in as fred via cli arguments\r\n")?; - p.expect("posting 2 patches without a covering letter...\r\n")?; - - relay::expect_send_with_progress( - &mut p, - vec![ - (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), - (" [my-relay] ws://localhost:8053", true, ""), - (" [repo-relay] ws://localhost:8056", true, ""), - (" [default] ws://localhost:8051", true, ""), - (" [default] ws://localhost:8052", true, ""), - ], - 2, - )?; - // end standard `ngit send output` - p.expect_after_whitespace("force pushed proposal revision\r\n")?; - p.expect_end()?; - - for p in [51, 52, 53, 55, 56] { - relay::shutdown_relay(8000 + p)?; - } - Ok(()) - }); - - // launch relay - let _ = join!( - r51.listen_until_close(), - r52.listen_until_close(), - r53.listen_until_close(), - r55.listen_until_close(), - r56.listen_until_close(), - ); - cli_tester_handle.join().unwrap()?; - Ok(()) - } - } - } - } -} -- cgit v1.2.3