From 7799b0edd16b0c97eb58ba2de62be27134a76122 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 23 Jan 2024 00:00:00 +0000 Subject: feat(prs-list): check for clean repo before checking out PR branch add confirm prompt before checking out branch and applying changes --- src/git.rs | 14 +++++++++++++- src/sub_commands/prs/list.rs | 23 ++++++++++++++++++++--- tests/prs_list.rs | 23 ++++++++++++++++++++--- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/git.rs b/src/git.rs index 41520c6..e832c23 100644 --- a/src/git.rs +++ b/src/git.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use std::{env::current_dir, path::Path}; use anyhow::{bail, Context, Result}; -use git2::{Oid, Revwalk}; +use git2::{DiffOptions, Oid, Revwalk}; use nostr::prelude::{sha1::Hash as Sha1Hash, Hash}; use crate::sub_commands::prs::list::tag_value; @@ -52,6 +52,8 @@ pub trait RepoActions { base_commit: &Sha1Hash, latest_commit: &Sha1Hash, ) -> Result<(Vec, Vec)>; + // including (un)staged changes and (un)tracked files + fn has_outstanding_changes(&self) -> Result; fn make_patch_from_commit(&self, commit: &Sha1Hash) -> Result; fn extract_commit_pgp_signature(&self, commit: &Sha1Hash) -> Result; fn checkout(&self, ref_name: &str) -> Result; @@ -242,6 +244,16 @@ impl RepoActions for Repo { .to_owned()) } + // including (un)staged changes and (un)tracked files + fn has_outstanding_changes(&self) -> Result { + let diff = self.git_repo.diff_tree_to_workdir_with_index( + Some(&self.git_repo.head()?.peel_to_tree()?), + Some(DiffOptions::new().include_untracked(true)), + )?; + + Ok(diff.deltas().len().gt(&0)) + } + fn get_commits_ahead_behind( &self, base_commit: &Sha1Hash, diff --git a/src/sub_commands/prs/list.rs b/src/sub_commands/prs/list.rs index a6aa8b7..f896f5a 100644 --- a/src/sub_commands/prs/list.rs +++ b/src/sub_commands/prs/list.rs @@ -1,11 +1,11 @@ -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; #[cfg(not(test))] use crate::client::Client; #[cfg(test)] use crate::client::MockConnect; use crate::{ - cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms}, + cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms}, client::Connect, git::{Repo, RepoActions}, repo_ref, @@ -134,7 +134,7 @@ pub async fn launch( .map(std::borrow::ToOwned::to_owned) .collect(); - // TODO: are there outstanding changes to prevent checking out a new branch? + confirm_checkout(&git_repo)?; let most_recent_pr_patch_chain = get_most_recent_patch_with_ancestors(commits_events) .context("cannot get most recent patch for PR")?; @@ -192,6 +192,23 @@ pub async fn launch( Ok(()) } +fn confirm_checkout(git_repo: &Repo) -> Result<()> { + if !Interactor::default().confirm( + PromptConfirmParms::default() + .with_prompt("check out branch?") + .with_default(true), + )? { + bail!("Exiting..."); + } + + if git_repo.has_outstanding_changes()? { + bail!( + "cannot pull PR branch when repository is not clean. discard or stash (un)staged changes and try again." + ); + } + Ok(()) +} + pub fn tag_value(event: &nostr::Event, tag_name: &str) -> Result { Ok(event .tags diff --git a/tests/prs_list.rs b/tests/prs_list.rs index 7bc3935..7f753c0 100644 --- a/tests/prs_list.rs +++ b/tests/prs_list.rs @@ -141,7 +141,9 @@ mod when_main_branch_is_uptodate { ], )?; c.succeeds_with(0, true)?; - + let mut confirm = + p.expect_confirm_eventually("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect_end_eventually_and_print()?; for p in [51, 52, 53, 55, 56] { @@ -200,6 +202,8 @@ mod when_main_branch_is_uptodate { )?; c.succeeds_with(0, true)?; p.expect("finding commits...\r\n")?; + let mut confirm = p.expect_confirm("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect("checked out PR branch. pulled 2 new commits\r\n")?; p.expect_end()?; @@ -302,7 +306,9 @@ mod when_main_branch_is_uptodate { ], )?; c.succeeds_with(2, true)?; - + let mut confirm = + p.expect_confirm_eventually("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect_end_eventually_and_print()?; for p in [51, 52, 53, 55, 56] { @@ -361,6 +367,8 @@ mod when_main_branch_is_uptodate { )?; c.succeeds_with(2, true)?; p.expect("finding commits...\r\n")?; + let mut confirm = p.expect_confirm("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect("checked out PR branch. pulled 2 new commits\r\n")?; p.expect_end()?; @@ -478,6 +486,9 @@ mod when_main_branch_is_uptodate { ], )?; c.succeeds_with(0, true)?; + let mut confirm = + p.expect_confirm_eventually("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect_end_eventually_and_print()?; for p in [51, 52, 53, 55, 56] { @@ -544,6 +555,8 @@ mod when_main_branch_is_uptodate { )?; c.succeeds_with(0, true)?; p.expect("finding commits...\r\n")?; + let mut confirm = p.expect_confirm("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect("checked out PR branch. no new commits to pull\r\n")?; p.expect_end()?; @@ -632,7 +645,9 @@ mod when_main_branch_is_uptodate { ], )?; c.succeeds_with(0, true)?; - + let mut confirm = + p.expect_confirm_eventually("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect_end_eventually_and_print()?; for p in [51, 52, 53, 55, 56] { @@ -699,6 +714,8 @@ mod when_main_branch_is_uptodate { )?; c.succeeds_with(0, true)?; p.expect("finding commits...\r\n")?; + let mut confirm = p.expect_confirm("check out branch?", Some(true))?; + confirm.succeeds_with(None)?; p.expect("checked out PR branch. pulled 1 new commits\r\n")?; p.expect_end()?; -- cgit v1.2.3