summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/lib.rs35
-rw-r--r--tests/cli.rs27
3 files changed, 61 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f57cb64..ec28d1b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Updated crates.io metadata to mark the primary upstream repo as Codeberg.
+- When deleting a repo, you are now asked first to confirm if you are sure
+ you're deleting the right repo.
## [0.2.0] - 2023-07-17
diff --git a/src/lib.rs b/src/lib.rs
index 62c050a..fded885 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,7 +5,7 @@ pub mod user_info;
use comfy_table::Table;
use humansize::{format_size, BINARY};
use parser::*;
-use rustyline::error::ReadlineError;
+use rustyline::{error::ReadlineError, DefaultEditor};
use std::{io, ops::ControlFlow};
use thiserror::Error;
@@ -60,8 +60,15 @@ pub fn run_command(user_input: &str) -> Result<ControlFlow<(), ()>, ShackleError
println!("Successfully created \"{}\"", init_result.path.display());
}
Ok(ShackleCommand::Delete(DeleteArgs { directory })) => {
- git::delete(&directory)?;
- println!("Successfully deleted \"{}\"", directory.display());
+ if confirm_risky_action(format!(
+ "Are you sure you want to delete \"{}\"?",
+ directory.display()
+ ))? {
+ git::delete(&directory)?;
+ println!("Successfully deleted \"{}\"", directory.display());
+ } else {
+ println!("Action cancelled");
+ }
}
Ok(ShackleCommand::Housekeeping(HousekeepingArgs { directory })) => match directory {
Some(directory) => {
@@ -92,6 +99,28 @@ pub fn run_command(user_input: &str) -> Result<ControlFlow<(), ()>, ShackleError
Ok(ControlFlow::Continue(()))
}
+fn confirm_risky_action(prompt: String) -> Result<bool, ShackleError> {
+ let mut rl = DefaultEditor::new()?;
+ loop {
+ let user_input = rl
+ .readline(&format!("{} (yes/no) ", prompt))
+ .map(|user_input| user_input.to_lowercase())?;
+
+ match user_input.trim() {
+ "" => {}
+ "yes" => {
+ return Ok(true);
+ }
+ "no" => {
+ return Ok(false);
+ }
+ _ => {
+ println!("Please answer 'yes' or 'no'.");
+ }
+ }
+ }
+}
+
#[derive(Error, Debug)]
pub enum ShackleError {
#[error(transparent)]
diff --git a/tests/cli.rs b/tests/cli.rs
index 34249c2..633c7bd 100644
--- a/tests/cli.rs
+++ b/tests/cli.rs
@@ -284,6 +284,11 @@ fn can_delete_a_repo() -> Result<()> {
verify_repo_exists(&repo_dir);
c.p.send_line(&format!("delete \"{repo_path}\""))?;
+ c.p.exp_string(&format!(
+ "Are you sure you want to delete \"{repo_path}\"? (yes/no)"
+ ))?;
+
+ c.p.send_line("yes")?;
c.p.exp_string(&format!("Successfully deleted \"{repo_path}\""))?;
verify_repo_does_not_exist(&repo_dir);
@@ -291,6 +296,28 @@ fn can_delete_a_repo() -> Result<()> {
}
#[test]
+fn repo_is_not_deleted_if_you_say_youre_not_sure() -> Result<()> {
+ let mut c = TestContext::new_interactive()?;
+ let repo_path = personal_repo_path(REPO_NAME);
+ let repo_dir = c.personal_repo_dir(REPO_NAME);
+
+ c.p.send_line(&format!("init {}", REPO_NAME))?;
+ c.expect_successful_init_message(&repo_path)?;
+ verify_repo_exists(&repo_dir);
+
+ c.p.send_line(&format!("delete \"{repo_path}\""))?;
+ c.p.exp_string(&format!(
+ "Are you sure you want to delete \"{repo_path}\"? (yes/no)"
+ ))?;
+
+ c.p.send_line("no")?;
+ c.p.exp_string(&format!("Action cancelled"))?;
+ verify_repo_exists(&repo_dir);
+
+ Ok(())
+}
+
+#[test]
fn git_housekeeping_repacks_objects() -> Result<()> {
let mut c = TestContext::new_interactive()?;
let repo_path = personal_repo_path(REPO_NAME);