diff --git a/src/commands.rs b/src/commands.rs index 25abe96..c07015c 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -326,22 +326,12 @@ fn decompress_file( Gzip | Bzip | Lzma | Zstd => { reader = chain_reader_decoder(&formats[0].compression_formats[0], reader)?; - let mut writer = match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) { - Ok(w) => w, - Err(e) if e.kind() == io::ErrorKind::AlreadyExists => { - if utils::user_wants_to_overwrite(&output_path, question_policy)? { - if output_path.is_dir() { - // We can't just use `fs::File::create(&output_path)` because it would return io::ErrorKind::IsADirectory - // ToDo: Maybe we should emphasise that `output_path` is a directory and everything inside it will be gone? - fs::remove_dir_all(&output_path)?; - } - fs::File::create(&output_path)? - } else { - return Ok(()); - } - } - Err(e) => return Err(Error::from(e)), - }; + let writer = utils::create_or_ask_overwrite(&output_path, question_policy)?; + if writer.is_none() { + // Means that the user doesn't want to overwrite + return Ok(()); + } + let mut writer = writer.unwrap(); io::copy(&mut reader, &mut writer)?; files_unpacked = vec![output_path]; diff --git a/src/utils.rs b/src/utils.rs index e8aaf52..e571bf8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -3,13 +3,35 @@ use std::{ cmp, env, ffi::OsStr, + io, path::Component, path::{Path, PathBuf}, }; use fs_err as fs; -use crate::{dialogs::Confirmation, info}; +use crate::{dialogs::Confirmation, info, Error}; + +/// Create the file if it doesn't exist and if it does then ask to overwrite it. +/// If the user doesn't want to overwrite then we return [`Ok(None)`] +pub fn create_or_ask_overwrite(path: &Path, question_policy: QuestionPolicy) -> Result, Error> { + match fs::OpenOptions::new().write(true).create_new(true).open(path) { + Ok(w) => Ok(Some(w)), + Err(e) if e.kind() == io::ErrorKind::AlreadyExists => { + if user_wants_to_overwrite(path, question_policy)? { + if path.is_dir() { + // We can't just use `fs::File::create(&path)` because it would return io::ErrorKind::IsADirectory + // ToDo: Maybe we should emphasise that `path` is a directory and everything inside it will be gone? + fs::remove_dir_all(path)?; + } + Ok(Some(fs::File::create(path)?)) + } else { + Ok(None) + } + } + Err(e) => Err(Error::from(e)), + } +} /// Checks if the given path represents an empty directory. pub fn dir_is_empty(dir_path: &Path) -> bool {