Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce new type for policy on how to handle overwrite questions #124

Merged
merged 1 commit into from
Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/archive/tar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ use walkdir::WalkDir;

use crate::{
info,
utils::{self, Bytes},
utils::{self, Bytes, QuestionPolicy},
};

pub fn unpack_archive(
reader: Box<dyn Read>,
output_folder: &Path,
skip_questions_positively: Option<bool>,
question_policy: QuestionPolicy,
) -> crate::Result<Vec<PathBuf>> {
let mut archive = tar::Archive::new(reader);

Expand All @@ -26,7 +26,7 @@ pub fn unpack_archive(
let mut file = file?;

let file_path = output_folder.join(file.path()?);
if file_path.exists() && !utils::user_wants_to_overwrite(&file_path, skip_questions_positively)? {
if file_path.exists() && !utils::user_wants_to_overwrite(&file_path, question_policy)? {
continue;
}

Expand Down
6 changes: 3 additions & 3 deletions src/archive/zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use zip::{self, read::ZipFile, ZipArchive};

use crate::{
info,
utils::{self, dir_is_empty,strip_cur_dir, Bytes},
utils::{self, dir_is_empty, strip_cur_dir, Bytes, QuestionPolicy},
};

use self::utf8::get_invalid_utf8_paths;
Expand All @@ -20,7 +20,7 @@ use self::utf8::get_invalid_utf8_paths;
pub fn unpack_archive<R>(
mut archive: ZipArchive<R>,
into: &Path,
skip_questions_positively: Option<bool>,
question_policy: QuestionPolicy,
) -> crate::Result<Vec<PathBuf>>
where
R: Read + Seek,
Expand All @@ -34,7 +34,7 @@ where
};

let file_path = into.join(file_path);
if file_path.exists() && !utils::user_wants_to_overwrite(&file_path, skip_questions_positively)? {
if file_path.exists() && !utils::user_wants_to_overwrite(&file_path, question_policy)? {
continue;
}

Expand Down
9 changes: 5 additions & 4 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::{

use clap::{Parser, ValueHint};

pub use crate::utils::QuestionPolicy;
use crate::Error;

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -53,18 +54,18 @@ pub enum Subcommand {
impl Opts {
/// A helper method that calls `clap::Parser::parse` and then translates relative paths to absolute.
/// Also determines if the user wants to skip questions or not
pub fn parse_args() -> crate::Result<(Self, Option<bool>)> {
pub fn parse_args() -> crate::Result<(Self, QuestionPolicy)> {
let mut opts: Self = Self::parse();

let (Subcommand::Compress { files, .. } | Subcommand::Decompress { files, .. }) = &mut opts.cmd;
*files = canonicalize_files(files)?;

let skip_questions_positively = if opts.yes {
Some(true)
QuestionPolicy::AlwaysYes
} else if opts.no {
Some(false)
QuestionPolicy::AlwaysNo
} else {
None
QuestionPolicy::Ask
};

Ok((opts, skip_questions_positively))
Expand Down
24 changes: 12 additions & 12 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
info,
utils::nice_directory_display,
utils::to_utf,
utils::{self, dir_is_empty},
utils::{self, dir_is_empty, QuestionPolicy},
Error,
};

Expand All @@ -38,7 +38,7 @@ fn represents_several_files(files: &[PathBuf]) -> bool {
files.iter().any(is_non_empty_dir) || files.len() > 1
}

pub fn run(args: Opts, skip_questions_positively: Option<bool>) -> crate::Result<()> {
pub fn run(args: Opts, question_policy: QuestionPolicy) -> crate::Result<()> {
match args.cmd {
Subcommand::Compress { files, output: output_path } => {
// Formats from path extension, like "file.tar.gz.xz" -> vec![Tar, Gzip, Lzma]
Expand Down Expand Up @@ -94,7 +94,7 @@ pub fn run(args: Opts, skip_questions_positively: Option<bool>) -> crate::Result
return Err(Error::with_reason(reason));
}

if output_path.exists() && !utils::user_wants_to_overwrite(&output_path, skip_questions_positively)? {
if output_path.exists() && !utils::user_wants_to_overwrite(&output_path, question_policy)? {
// User does not want to overwrite this file
return Ok(());
}
Expand Down Expand Up @@ -176,7 +176,7 @@ pub fn run(args: Opts, skip_questions_positively: Option<bool>) -> crate::Result
let output_folder = output_folder.as_ref().map(|path| path.as_ref());

for ((input_path, formats), file_name) in files.iter().zip(formats).zip(output_paths) {
decompress_file(input_path, formats, output_folder, file_name, skip_questions_positively)?;
decompress_file(input_path, formats, output_folder, file_name, question_policy)?;
}
}
}
Expand Down Expand Up @@ -289,7 +289,7 @@ fn decompress_file(
formats: Vec<extension::CompressionFormat>,
output_folder: Option<&Path>,
file_name: &Path,
skip_questions_positively: Option<bool>,
question_policy: QuestionPolicy,
) -> crate::Result<()> {
// TODO: improve error message
let reader = fs::File::open(&input_file_path)?;
Expand All @@ -311,7 +311,7 @@ fn decompress_file(
if let [Zip] = *formats.as_slice() {
utils::create_dir_if_non_existent(output_folder)?;
let zip_archive = zip::ZipArchive::new(reader)?;
let _files = crate::archive::zip::unpack_archive(zip_archive, output_folder, skip_questions_positively)?;
let _files = crate::archive::zip::unpack_archive(zip_archive, output_folder, question_policy)?;
info!("Successfully decompressed archive in {}.", nice_directory_display(output_folder));
return Ok(());
}
Expand Down Expand Up @@ -349,27 +349,27 @@ fn decompress_file(
info!("Successfully decompressed archive in {}.", nice_directory_display(output_path));
}
Tar => {
let _ = crate::archive::tar::unpack_archive(reader, output_folder, skip_questions_positively)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, question_policy)?;
info!("Successfully decompressed archive in {}.", nice_directory_display(output_folder));
}
Tgz => {
let reader = chain_reader_decoder(&Gzip, reader)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, skip_questions_positively)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, question_policy)?;
info!("Successfully decompressed archive in {}.", nice_directory_display(output_folder));
}
Tbz => {
let reader = chain_reader_decoder(&Bzip, reader)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, skip_questions_positively)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, question_policy)?;
info!("Successfully decompressed archive in {}.", nice_directory_display(output_folder));
}
Tlzma => {
let reader = chain_reader_decoder(&Lzma, reader)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, skip_questions_positively)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, question_policy)?;
info!("Successfully decompressed archive in {}.", nice_directory_display(output_folder));
}
Tzst => {
let reader = chain_reader_decoder(&Zstd, reader)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, skip_questions_positively)?;
let _ = crate::archive::tar::unpack_archive(reader, output_folder, question_policy)?;
info!("Successfully decompressed archive in {}.", nice_directory_display(output_folder));
}
Zip => {
Expand All @@ -384,7 +384,7 @@ fn decompress_file(
io::copy(&mut reader, &mut vec)?;
let zip_archive = zip::ZipArchive::new(io::Cursor::new(vec))?;

let _ = crate::archive::zip::unpack_archive(zip_archive, output_folder, skip_questions_positively)?;
let _ = crate::archive::zip::unpack_archive(zip_archive, output_folder, question_policy)?;

info!("Successfully decompressed archive in {}.", nice_directory_display(output_folder));
}
Expand Down
21 changes: 16 additions & 5 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ pub fn cd_into_same_dir_as(filename: &Path) -> crate::Result<PathBuf> {
Ok(previous_location)
}

pub fn user_wants_to_overwrite(path: &Path, skip_questions_positively: Option<bool>) -> crate::Result<bool> {
match skip_questions_positively {
Some(true) => Ok(true),
Some(false) => Ok(false),
None => {
pub fn user_wants_to_overwrite(path: &Path, question_policy: QuestionPolicy) -> crate::Result<bool> {
match question_policy {
QuestionPolicy::AlwaysYes => Ok(true),
QuestionPolicy::AlwaysNo => Ok(false),
QuestionPolicy::Ask => {
let path = to_utf(strip_cur_dir(path));
let path = Some(path.as_str());
let placeholder = Some("FILE");
Expand Down Expand Up @@ -126,6 +126,17 @@ impl std::fmt::Display for Bytes {
}
}

#[derive(Debug, PartialEq, Clone, Copy)]
/// How overwrite questions should be handled
pub enum QuestionPolicy {
/// Ask ever time
Ask,
/// Skip overwrite questions positively
AlwaysYes,
/// Skip overwrite questions negatively
AlwaysNo,
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
4 changes: 2 additions & 2 deletions tests/compress_and_decompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
};

use ouch::{
cli::{Opts, Subcommand},
cli::{Opts, QuestionPolicy, Subcommand},
commands::run,
};
use rand::{rngs::SmallRng, RngCore, SeedableRng};
Expand Down Expand Up @@ -183,7 +183,7 @@ fn extract_files(archive_path: &Path) -> Vec<PathBuf> {
output: Some(extraction_output_folder.clone()),
},
};
run(command, None).expect("Failed to extract");
run(command, QuestionPolicy::Ask).expect("Failed to extract");

fs::read_dir(extraction_output_folder).unwrap().map(Result::unwrap).map(|entry| entry.path()).collect()
}
Expand Down
6 changes: 3 additions & 3 deletions tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
};

use ouch::{
cli::{Opts, Subcommand},
cli::{Opts, QuestionPolicy, Subcommand},
commands::run,
};

Expand All @@ -30,7 +30,7 @@ pub fn compress_files(at: &Path, paths_to_compress: &[PathBuf], format: &str) ->
no: false,
cmd: Subcommand::Compress { files: paths_to_compress.to_vec(), output: archive_path.clone() },
};
run(command, None).expect("Failed to compress test dummy files");
run(command, QuestionPolicy::Ask).expect("Failed to compress test dummy files");

archive_path
}
Expand All @@ -55,7 +55,7 @@ pub fn extract_files(archive_path: &Path) -> Vec<PathBuf> {
output: Some(extraction_output_folder.clone()),
},
};
run(command, None).expect("Failed to extract");
run(command, QuestionPolicy::Ask).expect("Failed to extract");

fs::read_dir(extraction_output_folder).unwrap().map(Result::unwrap).map(|entry| entry.path()).collect()
}
Expand Down