Use the the -y and -n flags when decompressing .tar and .zip

This commit is contained in:
Vinícius Rodrigues Miguel 2021-03-29 01:37:01 -03:00
parent c7cf1112b6
commit 0f0b086943
8 changed files with 58 additions and 36 deletions

View File

@ -22,7 +22,7 @@ pub enum CommandKind {
), ),
} }
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Flags { pub enum Flags {
// No flags supplied // No flags supplied
None, None,

View File

@ -1,6 +1,9 @@
use std::path::PathBuf; use std::path::PathBuf;
use crate::file::File; use crate::{
cli::Flags,
file::File
};
pub enum DecompressionResult { pub enum DecompressionResult {
FilesUnpacked(Vec<PathBuf>), FilesUnpacked(Vec<PathBuf>),
@ -8,5 +11,5 @@ pub enum DecompressionResult {
} }
pub trait Decompressor { pub trait Decompressor {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult>; fn decompress(&self, from: File, into: &Option<File>, flags: Flags) -> crate::Result<DecompressionResult>;
} }

View File

@ -8,13 +8,13 @@ use colored::Colorize;
use tar::{self, Archive}; use tar::{self, Archive};
use super::decompressor::{DecompressionResult, Decompressor}; use super::decompressor::{DecompressionResult, Decompressor};
use crate::{file::File, utils, dialogs::Confirmation}; use crate::{cli::Flags, dialogs::Confirmation, file::File, utils};
#[derive(Debug)] #[derive(Debug)]
pub struct TarDecompressor {} pub struct TarDecompressor {}
impl TarDecompressor { impl TarDecompressor {
fn unpack_files(from: File, into: &Path) -> crate::Result<Vec<PathBuf>> { fn unpack_files(from: File, into: &Path, flags: Flags) -> crate::Result<Vec<PathBuf>> {
println!( println!(
"{}: attempting to decompress {:?}", "{}: attempting to decompress {:?}",
"ouch".bright_blue(), "ouch".bright_blue(),
@ -24,7 +24,9 @@ impl TarDecompressor {
let confirm = Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE")); let confirm = Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE"));
let mut archive: Archive<Box<dyn Read>> = match from.contents_in_memory { let mut archive: Archive<Box<dyn Read>> = match from.contents_in_memory {
Some(bytes) => tar::Archive::new(Box::new(Cursor::new(bytes))), Some(bytes) => {
tar::Archive::new(Box::new(Cursor::new(bytes)))
},
None => { None => {
let file = fs::File::open(&from.path)?; let file = fs::File::open(&from.path)?;
tar::Archive::new(Box::new(file)) tar::Archive::new(Box::new(file))
@ -36,8 +38,7 @@ impl TarDecompressor {
let file_path = PathBuf::from(into).join(file.path()?); let file_path = PathBuf::from(into).join(file.path()?);
if file_path.exists() { if file_path.exists() {
let file_path_str = &*file_path.to_string_lossy(); if !utils::permission_for_overwriting(&file_path, flags, &confirm)? {
if !confirm.ask(Some(file_path_str))? {
// The user does not want to overwrite the file // The user does not want to overwrite the file
continue; continue;
} }
@ -61,12 +62,12 @@ impl TarDecompressor {
} }
impl Decompressor for TarDecompressor { impl Decompressor for TarDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> { fn decompress(&self, from: File, into: &Option<File>, flags: Flags) -> crate::Result<DecompressionResult> {
let destination_path = utils::get_destination_path(into); let destination_path = utils::get_destination_path(into);
utils::create_path_if_non_existent(destination_path)?; utils::create_path_if_non_existent(destination_path)?;
let files_unpacked = Self::unpack_files(from, destination_path)?; let files_unpacked = Self::unpack_files(from, destination_path, flags)?;
Ok(DecompressionResult::FilesUnpacked(files_unpacked)) Ok(DecompressionResult::FilesUnpacked(files_unpacked))
} }

View File

@ -6,7 +6,7 @@ use std::{
use colored::Colorize; use colored::Colorize;
use super::decompressor::{DecompressionResult, Decompressor}; use super::decompressor::{DecompressionResult, Decompressor};
use crate::utils; use crate::{cli::Flags, utils};
// use niffler; // use niffler;
use crate::{extension::CompressionFormat, file::File}; use crate::{extension::CompressionFormat, file::File};
@ -62,19 +62,19 @@ impl DecompressorToMemory {
} }
impl Decompressor for GzipDecompressor { impl Decompressor for GzipDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> { fn decompress(&self, from: File, into: &Option<File>, _: Flags) -> crate::Result<DecompressionResult> {
DecompressorToMemory::decompress(from, CompressionFormat::Gzip, into) DecompressorToMemory::decompress(from, CompressionFormat::Gzip, into)
} }
} }
impl Decompressor for BzipDecompressor { impl Decompressor for BzipDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> { fn decompress(&self, from: File, into: &Option<File>, _: Flags) -> crate::Result<DecompressionResult> {
DecompressorToMemory::decompress(from, CompressionFormat::Bzip, into) DecompressorToMemory::decompress(from, CompressionFormat::Bzip, into)
} }
} }
impl Decompressor for LzmaDecompressor { impl Decompressor for LzmaDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> { fn decompress(&self, from: File, into: &Option<File>, _: Flags) -> crate::Result<DecompressionResult> {
DecompressorToMemory::decompress(from, CompressionFormat::Lzma, into) DecompressorToMemory::decompress(from, CompressionFormat::Lzma, into)
} }
} }

View File

@ -8,7 +8,7 @@ use colored::Colorize;
use zip::{self, read::ZipFile, ZipArchive}; use zip::{self, read::ZipFile, ZipArchive};
use super::decompressor::{DecompressionResult, Decompressor}; use super::decompressor::{DecompressionResult, Decompressor};
use crate::{dialogs::Confirmation, file::File, utils}; use crate::{cli::Flags, dialogs::Confirmation, file::File, utils};
#[cfg(unix)] #[cfg(unix)]
fn __unix_set_permissions(file_path: &PathBuf, file: &ZipFile) { fn __unix_set_permissions(file_path: &PathBuf, file: &ZipFile) {
@ -37,6 +37,7 @@ impl ZipDecompressor {
pub fn zip_decompress<T>( pub fn zip_decompress<T>(
archive: &mut ZipArchive<T>, archive: &mut ZipArchive<T>,
into: &Path, into: &Path,
flags: Flags,
) -> crate::Result<Vec<PathBuf>> ) -> crate::Result<Vec<PathBuf>>
where where
T: Read + Seek, T: Read + Seek,
@ -52,8 +53,7 @@ impl ZipDecompressor {
let file_path = into.join(file_path); let file_path = into.join(file_path);
if file_path.exists() { if file_path.exists() {
let file_path_str = &*file_path.as_path().to_string_lossy(); if !utils::permission_for_overwriting(&file_path, flags, &confirm)? {
if !confirm.ask(Some(file_path_str))? {
// The user does not want to overwrite the file // The user does not want to overwrite the file
continue; continue;
} }
@ -94,35 +94,42 @@ impl ZipDecompressor {
Ok(unpacked_files) Ok(unpacked_files)
} }
fn unpack_files(from: File, into: &Path) -> crate::Result<Vec<PathBuf>> { fn unpack_files(from: File, into: &Path, flags: Flags) -> crate::Result<Vec<PathBuf>> {
println!( println!(
"{}: attempting to decompress {:?}", "{} decompressing {:?}",
"ouch".bright_blue(), "[OUCH]".bright_blue(),
&from.path &from.path
); );
match from.contents_in_memory { match from.contents_in_memory {
Some(bytes) => { Some(bytes) => {
// Decompressing a .zip archive loaded up in memory
let mut archive = zip::ZipArchive::new(Cursor::new(bytes))?; let mut archive = zip::ZipArchive::new(Cursor::new(bytes))?;
Ok(Self::zip_decompress(&mut archive, into)?) Ok(Self::zip_decompress(&mut archive, into, flags)?)
} }
None => { None => {
// Decompressing a .zip archive from the file system
let file = fs::File::open(&from.path)?; let file = fs::File::open(&from.path)?;
let mut archive = zip::ZipArchive::new(file)?; let mut archive = zip::ZipArchive::new(file)?;
Ok(Self::zip_decompress(&mut archive, into)?) Ok(Self::zip_decompress(&mut archive, into, flags)?)
} }
} }
} }
} }
impl Decompressor for ZipDecompressor { impl Decompressor for ZipDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> { fn decompress(
&self,
from: File,
into: &Option<File>,
flags: Flags,
) -> crate::Result<DecompressionResult> {
let destination_path = utils::get_destination_path(into); let destination_path = utils::get_destination_path(into);
utils::create_path_if_non_existent(destination_path)?; utils::create_path_if_non_existent(destination_path)?;
let files_unpacked = Self::unpack_files(from, destination_path)?; let files_unpacked = Self::unpack_files(from, destination_path, flags)?;
Ok(DecompressionResult::FilesUnpacked(files_unpacked)) Ok(DecompressionResult::FilesUnpacked(files_unpacked))
} }

View File

@ -3,7 +3,7 @@ use std::{ffi::OsStr, fs, io::Write, path::PathBuf};
use colored::Colorize; use colored::Colorize;
use crate::{ use crate::{
cli::{Command, CommandKind}, cli::{Flags, Command, CommandKind},
compressors::{ compressors::{
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor, BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor,
ZipCompressor, ZipCompressor,
@ -98,13 +98,13 @@ impl Evaluator {
Ok((first_decompressor, second_decompressor)) Ok((first_decompressor, second_decompressor))
} }
// todo: move this folder into decompressors/ later on
fn decompress_file_in_memory( fn decompress_file_in_memory(
bytes: Vec<u8>, bytes: Vec<u8>,
file_path: PathBuf, file_path: PathBuf,
decompressor: Option<Box<dyn Decompressor>>, decompressor: Option<Box<dyn Decompressor>>,
output_file: &Option<File>, output_file: &Option<File>,
extension: Option<Extension>, extension: Option<Extension>,
flags: Flags
) -> crate::Result<()> { ) -> crate::Result<()> {
let output_file_path = utils::get_destination_path(output_file); let output_file_path = utils::get_destination_path(output_file);
@ -139,7 +139,7 @@ impl Evaluator {
extension, extension,
}; };
let decompression_result = decompressor.decompress(file, output_file)?; let decompression_result = decompressor.decompress(file, output_file, flags)?;
if let DecompressionResult::FileInMemory(_) = decompression_result { if let DecompressionResult::FileInMemory(_) = decompression_result {
// Should not be reachable. // Should not be reachable.
unreachable!(); unreachable!();
@ -152,6 +152,7 @@ impl Evaluator {
let confirm = Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE")); let confirm = Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE"));
let (first_compressor, second_compressor) = Self::get_compressor(&output)?; let (first_compressor, second_compressor) = Self::get_compressor(&output)?;
// TODO: use -y and -n here
let output_path = output.path.clone(); let output_path = output.path.clone();
if output_path.exists() { if output_path.exists() {
let output_path_str = &*output_path.to_string_lossy(); let output_path_str = &*output_path.to_string_lossy();
@ -188,14 +189,13 @@ impl Evaluator {
Ok(()) Ok(())
} }
fn decompress_file(file: File, output: &Option<File>) -> crate::Result<()> { fn decompress_file(file: File, output: &Option<File>, flags: Flags) -> crate::Result<()> {
// let output_file = &command.output;
let (first_decompressor, second_decompressor) = Self::get_decompressor(&file)?; let (first_decompressor, second_decompressor) = Self::get_decompressor(&file)?;
let file_path = file.path.clone(); let file_path = file.path.clone();
let extension = file.extension.clone(); let extension = file.extension.clone();
let decompression_result = second_decompressor.decompress(file, output)?; let decompression_result = second_decompressor.decompress(file, output, flags)?;
match decompression_result { match decompression_result {
DecompressionResult::FileInMemory(bytes) => { DecompressionResult::FileInMemory(bytes) => {
@ -207,6 +207,7 @@ impl Evaluator {
first_decompressor, first_decompressor,
output, output,
extension, extension,
flags
)?; )?;
} }
DecompressionResult::FilesUnpacked(_files) => { DecompressionResult::FilesUnpacked(_files) => {
@ -223,7 +224,7 @@ impl Evaluator {
Ok(()) Ok(())
} }
pub fn evaluate(command: Command) -> crate::Result<()> { pub fn evaluate(command: Command, flags: Flags) -> crate::Result<()> {
let output = command.output.clone(); let output = command.output.clone();
match command.kind { match command.kind {
@ -234,7 +235,7 @@ impl Evaluator {
} }
CommandKind::Decompression(files_to_decompress) => { CommandKind::Decompression(files_to_decompress) => {
for file in files_to_decompress { for file in files_to_decompress {
Self::decompress_file(file, &output)?; Self::decompress_file(file, &output, flags)?;
} }
} }
} }

View File

@ -14,7 +14,6 @@ use evaluator::Evaluator;
fn main() -> crate::Result<()> { fn main() -> crate::Result<()> {
let matches = cli::get_matches(); let matches = cli::get_matches();
// let command = cli::Command::try_from(matches)?; let (command, flags) = cli::parse_matches(matches)?;
let (command, _flags) = cli::parse_matches(matches)?; Evaluator::evaluate(command, flags)
Evaluator::evaluate(command)
} }

View File

@ -5,7 +5,7 @@ use std::{
use colored::Colorize; use colored::Colorize;
use crate::{extension::CompressionFormat, file::File}; use crate::{cli::Flags, dialogs::Confirmation, extension::CompressionFormat, file::File};
pub(crate) fn ensure_exists<'a, P>(path: P) -> crate::Result<()> pub(crate) fn ensure_exists<'a, P>(path: P) -> crate::Result<()>
where where
@ -90,3 +90,14 @@ pub(crate) fn change_dir_and_return_parent(filename: &PathBuf) -> crate::Result<
env::set_current_dir(parent)?; env::set_current_dir(parent)?;
Ok(previous_location) Ok(previous_location)
} }
pub fn permission_for_overwriting(path: &PathBuf, flags: Flags, confirm: &Confirmation) -> crate::Result<bool> {
match flags {
Flags::AlwaysYes => return Ok(true),
Flags::AlwaysNo => return Ok(false),
Flags::None => {}
}
let file_path_str = &*path.as_path().to_string_lossy();
Ok(confirm.ask(Some(file_path_str))?)
}