diff --git a/src/commands/decompress.rs b/src/commands/decompress.rs index e3654e9..bdcec28 100644 --- a/src/commands/decompress.rs +++ b/src/commands/decompress.rs @@ -323,6 +323,8 @@ fn smart_unpack( (temp_dir_path.to_owned(), output_file_path.to_owned()) }; + // Before moving, need to check if a file with the same name already exists + // If it does, need to ask the user what to do new_path = match utils::resolve_path(&new_path, question_policy)? { Some(path) => path, None => return Ok(ControlFlow::Break(())), diff --git a/src/utils/fs.rs b/src/utils/fs.rs index 9c95a79..420b945 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -19,6 +19,7 @@ pub fn is_path_stdin(path: &Path) -> bool { path.as_os_str() == "-" } +/// Check if &Path exists, if it does then ask the user if they want to overwrite or rename it pub fn resolve_path(path: &Path, question_policy: QuestionPolicy) -> crate::Result> { if path.exists() { match user_wants_to_overwrite(path, question_policy)? { @@ -46,6 +47,7 @@ pub fn remove_file_or_dir(path: &Path) -> crate::Result<()> { Ok(()) } +/// Create a new path renaming the "filename" from &Path until find a free name pub fn rename_for_available_filename(path: &Path) -> PathBuf { let mut renamed_path = rename_or_increment_filename(path); while renamed_path.exists() { @@ -54,6 +56,8 @@ pub fn rename_for_available_filename(path: &Path) -> PathBuf { renamed_path } +/// Create a new path renaming the "filename" from &Path to `filename_1` +/// or `filename_2`, `filename_3` until find a free name pub fn rename_or_increment_filename(path: &Path) -> PathBuf { let parent = path.parent().unwrap_or_else(|| Path::new("")); let filename = path.file_stem().and_then(|s| s.to_str()).unwrap_or(""); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 18f5b46..444cf1f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -19,7 +19,7 @@ pub use self::{ }, fs::{ cd_into_same_dir_as, create_dir_if_non_existent, is_path_stdin, remove_file_or_dir, - rename_for_available_filename, resolve_path, try_infer_extension, + rename_for_available_filename, resolve_path_conflict, try_infer_extension, }, question::{ ask_to_create_file, user_wants_to_continue, user_wants_to_overwrite, FileConflitOperation, QuestionAction, diff --git a/src/utils/question.rs b/src/utils/question.rs index 2206f92..b826415 100644 --- a/src/utils/question.rs +++ b/src/utils/question.rs @@ -38,10 +38,15 @@ pub enum QuestionAction { } #[derive(Default)] +/// Determines which action to do when there is a file conflict pub enum FileConflitOperation { #[default] + /// Cancel the operation Cancel, + /// Overwrite the existing file with the new one Overwrite, + /// Rename the file + /// It'll be put "_1" at the end of the filename or "_2","_3","_4".. if already exists Rename, } @@ -56,7 +61,7 @@ pub fn user_wants_to_overwrite(path: &Path, question_policy: QuestionPolicy) -> } } -/// Check if QuestionPolicy flags were set, otherwise, ask user if they want to overwrite. +/// Ask the user if they want to overwrite or rename the &Path pub fn ask_file_conflict_operation(path: &Path) -> Result { use FileConflitOperation as Op; @@ -127,8 +132,7 @@ pub fn user_wants_to_continue( } /// Choise dialog for end user with [option1/option2/...] question. -/// -/// If the placeholder is found in the prompt text, it will be replaced to form the final message. +/// Each option is a [Choice] entity, holding a value "T" returned when that option is selected pub struct ChoicePrompt<'a, T: Default> { /// The message to be displayed with the placeholder text in it. /// e.g.: "Do you want to overwrite 'FILE'?" @@ -137,6 +141,8 @@ pub struct ChoicePrompt<'a, T: Default> { pub choises: Vec>, } +/// A single choice showed as a option to user in a [ChoicePrompt] +/// It holds a label and a color to display to user and a real value to be returned pub struct Choice<'a, T: Default> { label: &'a str, value: T, @@ -155,7 +161,8 @@ impl<'a, T: Default> ChoicePrompt<'a, T> { } } - /// Creates user message and receives a boolean input to be used on the program + /// Creates user message and receives a input to be compared with choises "label" + /// and returning the real value of the choise selected pub fn ask(mut self) -> crate::Result { let message = self.prompt;