decompressors/zip: Add confirmation dialog for file overwriting

This commit is contained in:
Vinícius Rodrigues Miguel 2021-03-28 13:56:00 -03:00
parent 91f411439a
commit 7954eb07fd
4 changed files with 88 additions and 19 deletions

View File

@ -8,7 +8,7 @@ use colored::Colorize;
use zip::{self, read::ZipFile, ZipArchive};
use super::decompressor::{DecompressionResult, Decompressor};
use crate::{file::File, utils};
use crate::{dialogs::Confirmation, file::File, utils};
#[cfg(unix)]
fn __unix_set_permissions(file_path: &PathBuf, file: &ZipFile) {
@ -41,6 +41,7 @@ impl ZipDecompressor {
where
T: Read + Seek,
{
let confirm = Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE"));
let mut unpacked_files = vec![];
for idx in 0..archive.len() {
let mut file = archive.by_index(idx)?;
@ -50,28 +51,36 @@ impl ZipDecompressor {
};
let file_path = into.join(file_path);
if file_path.exists() {
let file_path_str = &*file_path.as_path().to_string_lossy();
if confirm.ask(Some(file_path_str))? {
continue;
}
}
Self::check_for_comments(&file);
let is_dir = (&*file.name()).ends_with('/');
if is_dir {
println!("File {} extracted to \"{}\"", idx, file_path.display());
fs::create_dir_all(&file_path)?;
} else {
if let Some(p) = file_path.parent() {
if !p.exists() {
fs::create_dir_all(&p)?;
}
match (&*file.name()).ends_with('/') {
_is_dir @ true => {
println!("File {} extracted to \"{}\"", idx, file_path.display());
fs::create_dir_all(&file_path)?;
}
_is_file @ false => {
if let Some(path) = file_path.parent() {
if !path.exists() {
fs::create_dir_all(&path)?;
}
}
println!(
"{}: \"{}\" extracted. ({} bytes)",
"info".yellow(),
file_path.display(),
file.size()
);
let mut output_file = fs::File::create(&file_path)?;
io::copy(&mut file, &mut output_file)?;
}
println!(
"{}: \"{}\" extracted. ({} bytes)",
"info".yellow(),
file_path.display(),
file.size()
);
let mut outfile = fs::File::create(&file_path)?;
io::copy(&mut file, &mut outfile)?;
}
#[cfg(unix)]

47
src/dialogs.rs Normal file
View File

@ -0,0 +1,47 @@
use std::io::{self, Write};
use colored::Colorize;
pub struct Confirmation<'a> {
pub prompt: &'a str,
pub placeholder: Option<&'a str>,
}
#[derive(Debug)]
pub struct Error;
impl<'a> Confirmation<'a> {
pub fn new(prompt: &'a str, pattern: Option<&'a str>) -> Self {
Self {
prompt,
placeholder: pattern,
}
}
pub fn ask(&self, substitute: Option<&'a str>) -> crate::Result<bool> {
let message = match (self.placeholder, substitute) {
(None, _) => self.prompt.into(),
(Some(_), None) => return Err(crate::Error::InternalError),
(Some(placeholder), Some(subs)) => self.prompt.replace(placeholder, subs),
};
loop {
print!("{} [{}/{}] ", message, "Y".bright_green(), "n".bright_red());
io::stdout().flush()?;
let mut answer = String::new();
io::stdin().read_line(&mut answer)?;
let trimmed_answer = answer.trim().to_ascii_lowercase();
if trimmed_answer.is_empty() {
return Ok(true);
}
match trimmed_answer.to_ascii_lowercase().as_ref() {
"y" | "yes" => return Ok(true),
"n" | "no" => return Ok(false),
_ => {}
}
}
}
}

View File

@ -16,6 +16,7 @@ pub enum Error {
PermissionDenied,
UnsupportedZipArchive(&'static str),
InputsMustHaveBeenDecompressible(PathBuf),
InternalError,
}
pub type Result<T> = std::result::Result<T, Error>;

View File

@ -1,6 +1,7 @@
mod cli;
mod compressors;
mod decompressors;
mod dialogs;
mod error;
mod evaluator;
mod extension;
@ -18,3 +19,14 @@ fn main() -> crate::Result<()> {
let command = cli::Command::try_from(matches)?;
Evaluator::evaluate(command)
}
// fn main() -> crate::Result<()> {
// let dialog = dialogs::Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE"));
// match dialog.ask(Some("file.tar.gz"))? {
// true => println!("deleting"),
// false => println!("keeping")
// };
// Ok(())
// }