Refactoring and Clippy warnings

This commit is contained in:
João M. Bezerra 2021-03-25 20:50:42 -03:00
parent e1da79c2ac
commit 755cc2a40d
9 changed files with 107 additions and 134 deletions

View File

@ -33,7 +33,7 @@ pub fn clap_app<'a, 'b>() -> clap::App<'a, 'b> {
.after_help( .after_help(
"ouch infers what to based on the extensions of the input files and output file received. "ouch infers what to based on the extensions of the input files and output file received.
Examples: `ouch -i movies.tar.gz classes.zip -o Videos/` in order to decompress files into a folder. Examples: `ouch -i movies.tar.gz classes.zip -o Videos/` in order to decompress files into a folder.
`ouch -i headers/ sources/ Makefile -o my-project.tar.gz` `ouch -i headers/ sources/ Makefile -o my-project.tar.gz`
`ouch -i image{1..50}.jpeg -o images.zip` `ouch -i image{1..50}.jpeg -o images.zip`
Please relate any issues or contribute at https://github.com/vrmiguel/ouch") Please relate any issues or contribute at https://github.com/vrmiguel/ouch")
.author("Vinícius R. Miguel") .author("Vinícius R. Miguel")
@ -107,7 +107,7 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
let output_file = matches.value_of("output").unwrap(); // Safe unwrap since we've established that output was supplied let output_file = matches.value_of("output").unwrap(); // Safe unwrap since we've established that output was supplied
let output_file_extension = Extension::new(output_file); let output_file_extension = Extension::new(output_file);
let output_is_compressible = output_file_extension.is_ok(); let output_is_compressible = output_file_extension.is_ok();
if output_is_compressible { if output_is_compressible {
// The supplied output is compressible, so we'll compress our inputs to it // The supplied output is compressible, so we'll compress our inputs to it
@ -127,14 +127,15 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
let input_files = canonical_paths.map(Result::unwrap).collect(); let input_files = canonical_paths.map(Result::unwrap).collect();
return Ok(Command { Ok(Command {
kind: CommandKind::Compression(input_files), kind: CommandKind::Compression(input_files),
output: Some(File { output: Some(File {
path: output_file.into(), path: output_file.into(),
contents_in_memory: None, contents_in_memory: None,
// extension: output_file_extension.ok(),
extension: Some(output_file_extension.unwrap()) extension: Some(output_file_extension.unwrap())
}), }),
}); })
} else { } else {
// Output not supplied // Output not supplied
@ -142,14 +143,14 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
let input_files = process_decompressible_input(input_files)?; let input_files = process_decompressible_input(input_files)?;
return Ok(Command { Ok(Command {
kind: CommandKind::Decompression(input_files), kind: CommandKind::Decompression(input_files),
output: Some(File { output: Some(File {
path: output_file.into(), path: output_file.into(),
contents_in_memory: None, contents_in_memory: None,
extension: None extension: None
}) })
}); })
} }
} else { } else {
// else: output file not supplied // else: output file not supplied
@ -157,10 +158,10 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
// Case 2: error // Case 2: error
let input_files = process_decompressible_input(input_files)?; let input_files = process_decompressible_input(input_files)?;
return Ok(Command { Ok(Command {
kind: CommandKind::Decompression(input_files), kind: CommandKind::Decompression(input_files),
output: None, output: None,
}); })
} }
} }
} }

View File

@ -20,7 +20,7 @@ impl BzipCompressor {
}; };
println!("{}: compressed {:?} into memory ({} bytes)", "info".yellow(), &path, contents.len()); println!("{}: compressed {:?} into memory ({} bytes)", "info".yellow(), &path, contents.len());
Ok(contents) Ok(contents)
} }
@ -34,7 +34,7 @@ impl BzipCompressor {
} }
}; };
Ok(Self::compress_bytes(&*bytes)?) Self::compress_bytes(&*bytes)
} }
fn compress_bytes(bytes: &[u8]) -> OuchResult<Vec<u8>> { fn compress_bytes(bytes: &[u8]) -> OuchResult<Vec<u8>> {
@ -58,4 +58,4 @@ impl Compressor for BzipCompressor {
), ),
} }
} }
} }

View File

@ -42,7 +42,7 @@ impl GzipCompressor {
} }
}; };
Ok(Self::compress_bytes(file_contents)?) Self::compress_bytes(file_contents)
} }
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> { pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> {

View File

@ -42,9 +42,9 @@ impl LzmaCompressor {
} }
}; };
Ok(Self::compress_bytes(file_contents)?) Self::compress_bytes(file_contents)
} }
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> { pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> {
let buffer = vec![]; let buffer = vec![];
let mut encoder = xz2::write::XzEncoder::new(buffer, 6); let mut encoder = xz2::write::XzEncoder::new(buffer, 6);
@ -58,12 +58,8 @@ impl Compressor for LzmaCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> { fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
let format = CompressionFormat::Lzma; let format = CompressionFormat::Lzma;
match from { match from {
Entry::Files(files) => Ok( Entry::Files(files) => Self::compress_files(files, format),
Self::compress_files(files, format)? Entry::InMemory(file) => Self::compress_file_in_memory(file),
),
Entry::InMemory(file) => Ok(
Self::compress_file_in_memory(file)?
),
} }
} }
} }

View File

@ -4,32 +4,37 @@ use colored::Colorize;
use tar::Builder; use tar::Builder;
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::{compressors::Compressor, error::{Error, OuchResult}, file::File}; use crate::{
compressors::Compressor,
error::{Error, OuchResult},
file::File,
};
use super::compressor::Entry; use super::compressor::Entry;
pub struct TarCompressor {} pub struct TarCompressor {}
impl TarCompressor { impl TarCompressor {
// TODO: implement this // TODO: implement this
fn make_archive_from_memory(_input: File) -> OuchResult<Vec<u8>> { fn make_archive_from_memory(_input: File) -> OuchResult<Vec<u8>> {
println!("{}: .tar.tar and .zip.tar is currently unimplemented.", "error".red()); println!(
"{}: .tar.tar and .zip.tar is currently unimplemented.",
"error".red()
);
Err(Error::InvalidZipArchive("")) Err(Error::InvalidZipArchive(""))
} }
fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> OuchResult<Vec<u8>> { fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> OuchResult<Vec<u8>> {
let change_dir_and_return_parent = |filename: &PathBuf| -> OuchResult<PathBuf> {
let change_dir_and_return_parent = |filename: &PathBuf| -> OuchResult<PathBuf> {
let previous_location = env::current_dir()?; let previous_location = env::current_dir()?;
let parent = filename.parent().unwrap(); let parent = filename.parent().unwrap();
env::set_current_dir(parent)?; env::set_current_dir(parent)?;
Ok(previous_location) Ok(previous_location)
}; };
let buf = Vec::new(); let buf = Vec::new();
let mut b = Builder::new(buf); let mut b = Builder::new(buf);
for filename in input_filenames { for filename in input_filenames {
let previous_location = change_dir_and_return_parent(&filename)?; let previous_location = change_dir_and_return_parent(&filename)?;
// Safe unwrap since this filename came from `fs::canonicalize`. // Safe unwrap since this filename came from `fs::canonicalize`.
@ -44,25 +49,16 @@ impl TarCompressor {
} }
env::set_current_dir(previous_location)?; env::set_current_dir(previous_location)?;
} }
Ok(b.into_inner()?) Ok(b.into_inner()?)
} }
} }
impl Compressor for TarCompressor { impl Compressor for TarCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> { fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
match from { match from {
Entry::Files(filenames) => { Entry::Files(filenames) => Self::make_archive_from_files(filenames),
Ok( Entry::InMemory(file) => Self::make_archive_from_memory(file),
Self::make_archive_from_files(filenames)? }
)
},
Entry::InMemory(file) => {
Ok(
Self::make_archive_from_memory(file)?
)
}
}
} }
} }

View File

@ -42,10 +42,10 @@ impl ZipCompressor {
} }
}; };
writer.write(&*input_bytes)?; writer.write_all(&*input_bytes)?;
let bytes = writer.finish().unwrap(); let bytes = writer.finish().unwrap();
Ok(bytes.into_inner()) Ok(bytes.into_inner())
@ -67,14 +67,14 @@ impl ZipCompressor {
} }
writer writer
.start_file( .start_file(
entry_path.to_string_lossy(), entry_path.to_string_lossy(),
options options
)?; )?;
let file_bytes = std::fs::read(entry.path())?; let file_bytes = std::fs::read(entry.path())?;
writer.write(&*file_bytes)?; writer.write_all(&*file_bytes)?;
} }
} }
let bytes = writer.finish().unwrap(); let bytes = writer.finish().unwrap();

View File

@ -3,29 +3,15 @@ use std::{ffi::OsStr, fs, io::Write, path::PathBuf};
use colored::Colorize; use colored::Colorize;
use crate::compressors::{ use crate::compressors::{
Entry, BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor, ZipCompressor,
Compressor,
TarCompressor,
ZipCompressor,
GzipCompressor,
BzipCompressor,
LzmaCompressor
}; };
use crate::decompressors::{ use crate::decompressors::{
Decompressor, BzipDecompressor, DecompressionResult, Decompressor, GzipDecompressor, LzmaDecompressor,
TarDecompressor, TarDecompressor, ZipDecompressor,
ZipDecompressor,
GzipDecompressor,
BzipDecompressor,
LzmaDecompressor,
DecompressionResult
}; };
use crate::extension::{ use crate::extension::{CompressionFormat, Extension};
Extension,
CompressionFormat
};
use crate::cli::{Command, CommandKind}; use crate::cli::{Command, CommandKind};
@ -41,19 +27,21 @@ impl Evaluator {
pub fn get_compressor( pub fn get_compressor(
file: &File, file: &File,
) -> error::OuchResult<(Option<Box<dyn Compressor>>, Box<dyn Compressor>)> { ) -> error::OuchResult<(Option<Box<dyn Compressor>>, Box<dyn Compressor>)> {
if file.extension.is_none() { let extension = match &file.extension {
// This block *should* be unreachable Some(extension) => extension.clone(),
eprintln!( None => {
"{}: reached Evaluator::get_decompressor without known extension.", // This block *should* be unreachable
"internal error".red() eprintln!(
); "{}: reached Evaluator::get_decompressor without known extension.",
return Err(error::Error::InvalidInput); "internal error".red()
} );
let extension = file.extension.clone().unwrap(); return Err(error::Error::InvalidInput);
}
};
// Supported first compressors: // Supported first compressors:
// .tar and .zip // .tar and .zip
let first_compressor: Option<Box<dyn Compressor>> = match extension.first_ext { let first_compressor: Option<Box<dyn Compressor>> = match extension.first_ext {
Some(ext) => match ext { Some(ext) => match ext {
CompressionFormat::Tar => Some(Box::new(TarCompressor {})), CompressionFormat::Tar => Some(Box::new(TarCompressor {})),
@ -70,8 +58,8 @@ impl Evaluator {
// Supported second compressors: // Supported second compressors:
// any // any
let second_compressor: Box<dyn Compressor> = match extension.second_ext { let second_compressor: Box<dyn Compressor> = match extension.second_ext {
CompressionFormat::Tar => Box::new(TarCompressor {}), CompressionFormat::Tar => Box::new(TarCompressor {}),
CompressionFormat::Zip => Box::new(ZipCompressor {}), CompressionFormat::Zip => Box::new(ZipCompressor {}),
CompressionFormat::Bzip => Box::new(BzipCompressor {}), CompressionFormat::Bzip => Box::new(BzipCompressor {}),
CompressionFormat::Gzip => Box::new(GzipCompressor {}), CompressionFormat::Gzip => Box::new(GzipCompressor {}),
CompressionFormat::Lzma => Box::new(LzmaCompressor {}), CompressionFormat::Lzma => Box::new(LzmaCompressor {}),
@ -83,15 +71,17 @@ impl Evaluator {
pub fn get_decompressor( pub fn get_decompressor(
file: &File, file: &File,
) -> error::OuchResult<(Option<Box<dyn Decompressor>>, Box<dyn Decompressor>)> { ) -> error::OuchResult<(Option<Box<dyn Decompressor>>, Box<dyn Decompressor>)> {
if file.extension.is_none() { let extension = match &file.extension {
// This block *should* be unreachable Some(extension) => extension.clone(),
eprintln!( None => {
"{}: reached Evaluator::get_decompressor without known extension.", // This block *should* be unreachable
"internal error".red() eprintln!(
); "{}: reached Evaluator::get_decompressor without known extension.",
return Err(error::Error::InvalidInput); "internal error".red()
} );
let extension = file.extension.clone().unwrap(); return Err(error::Error::InvalidInput);
}
};
let second_decompressor: Box<dyn Decompressor> = match extension.second_ext { let second_decompressor: Box<dyn Decompressor> = match extension.second_ext {
CompressionFormat::Tar => Box::new(TarDecompressor {}), CompressionFormat::Tar => Box::new(TarDecompressor {}),
@ -102,8 +92,7 @@ impl Evaluator {
CompressionFormat::Lzma => Box::new(LzmaDecompressor {}), CompressionFormat::Lzma => Box::new(LzmaDecompressor {}),
CompressionFormat::Bzip => Box::new(BzipDecompressor {}) CompressionFormat::Bzip => Box::new(BzipDecompressor {}),
}; };
let first_decompressor: Option<Box<dyn Decompressor>> = match extension.first_ext { let first_decompressor: Option<Box<dyn Decompressor>> = match extension.first_ext {
@ -132,7 +121,7 @@ impl Evaluator {
let mut filename = file_path let mut filename = file_path
.file_stem() .file_stem()
.unwrap_or(output_file_path.as_os_str()); .unwrap_or_else(|| output_file_path.as_os_str());
if filename == "." { if filename == "." {
// I believe this is only possible when the supplied inout has a name // I believe this is only possible when the supplied inout has a name
// of the sort `.tar` or `.zip' and no output has been supplied. // of the sort `.tar` or `.zip' and no output has been supplied.
@ -141,16 +130,20 @@ impl Evaluator {
let filename = PathBuf::from(filename); let filename = PathBuf::from(filename);
if decompressor.is_none() { // If there is a decompressor to use, we'll create a file in-memory and decompress it
// There is no more processing to be done on the input file (or there is but currently unsupported) let decompressor = match decompressor {
// Therefore, we'll save what we have in memory into a file. Some(decompressor) => decompressor,
None => {
// There is no more processing to be done on the input file (or there is but currently unsupported)
// Therefore, we'll save what we have in memory into a file.
println!("{}: saving to {:?}.", "info".yellow(), filename); println!("{}: saving to {:?}.", "info".yellow(), filename);
let mut f = fs::File::create(output_file_path.join(filename))?; let mut f = fs::File::create(output_file_path.join(filename))?;
f.write_all(&bytes)?; f.write_all(&bytes)?;
return Ok(()); return Ok(());
} }
};
let file = File { let file = File {
path: filename, path: filename,
@ -158,10 +151,6 @@ impl Evaluator {
extension, extension,
}; };
let decompressor = decompressor.unwrap();
// If there is a decompressor to use, we'll create a file in-memory and decompress it
let decompression_result = decompressor.decompress(file, output_file)?; let decompression_result = decompressor.decompress(file, output_file)?;
if let DecompressionResult::FileInMemory(_) = decompression_result { if let DecompressionResult::FileInMemory(_) = decompression_result {
// Should not be reachable. // Should not be reachable.
@ -174,7 +163,6 @@ impl Evaluator {
fn compress_files(files: Vec<PathBuf>, mut output: File) -> error::OuchResult<()> { fn compress_files(files: Vec<PathBuf>, mut output: File) -> error::OuchResult<()> {
let (first_compressor, second_compressor) = Self::get_compressor(&output)?; let (first_compressor, second_compressor) = Self::get_compressor(&output)?;
let output_path = output.path.clone(); let output_path = output.path.clone();
let bytes = match first_compressor { let bytes = match first_compressor {
@ -187,17 +175,20 @@ impl Evaluator {
entry = Entry::InMemory(output); entry = Entry::InMemory(output);
second_compressor.compress(entry)? second_compressor.compress(entry)?
}, }
None => { None => {
let entry = Entry::Files(files); let entry = Entry::Files(files);
second_compressor.compress(entry)? second_compressor.compress(entry)?
} }
}; };
println!("{}: writing to {:?}. ({} bytes)", "info".yellow(), &output_path, bytes.len()); println!(
fs::write( "{}: writing to {:?}. ({} bytes)",
output_path, "info".yellow(),
bytes)?; &output_path,
bytes.len()
);
fs::write(output_path, bytes)?;
Ok(()) Ok(())
} }

View File

@ -1,57 +1,47 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use colored::Colorize;
mod cli; mod cli;
mod error; mod error;
mod evaluator;
mod extension; mod extension;
mod file; mod file;
mod test; mod test;
mod evaluator;
mod utils; mod utils;
mod compressors; mod compressors;
mod decompressors; mod decompressors;
fn main() -> error::OuchResult<()>{ fn main() -> error::OuchResult<()> {
let print_error = |err| { let print_error = |err| {
println!("{}", err); println!("{}", err);
}; };
let matches = cli::get_matches(); let matches = cli::get_matches();
match cli::Command::try_from(matches) { cli::Command::try_from(matches)
Ok(command) => { .map(|command| evaluator::Evaluator::evaluate(command).unwrap_or_else(print_error))
match evaluator::Evaluator::evaluate(command) { .unwrap_or_else(print_error);
Ok(_) => {},
Err(err) => print_error(err)
}
}
Err(err) => {
print_error(err)
}
}
Ok(()) Ok(())
} }
// fn main() -> error::OuchResult<()> { // fn main() -> error::OuchResult<()> {
// use tar::{Builder}; // use tar::{Builder};
// use walkdir::WalkDir; // use walkdir::WalkDir;
//
// let mut b = Builder::new(Vec::new()); // let mut b = Builder::new(Vec::new());
//
// for entry in WalkDir::new("src") { // for entry in WalkDir::new("src") {
// let entry = entry?; // let entry = entry?;
// let mut file = std::fs::File::open(entry.path())?; // let mut file = std::fs::File::open(entry.path())?;
// b.append_file(entry.path(), &mut file)?; // b.append_file(entry.path(), &mut file)?;
// } // }
//
// // let mut file = std::fs::File::open("Cargo.toml")?; // // let mut file = std::fs::File::open("Cargo.toml")?;
// // b.append_file("Cargo.toml", &mut file)?; // // b.append_file("Cargo.toml", &mut file)?;
//
// let bytes = b.into_inner()?; // let bytes = b.into_inner()?;
//
// std::fs::write("daaaaamn.tar", bytes)?; // std::fs::write("daaaaamn.tar", bytes)?;
//
// Ok(()) // Ok(())
// } // }

View File

@ -14,8 +14,7 @@ where
Ok(()) Ok(())
} }
pub (crate) fn check_for_multiple_files(files: &Vec<PathBuf>, format: &CompressionFormat) -> OuchResult<()> { pub (crate) fn check_for_multiple_files(files: &[PathBuf], format: &CompressionFormat) -> OuchResult<()> {
if files.len() != 1 { if files.len() != 1 {
eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "[ERROR]".red(), format, format); eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "[ERROR]".red(), format, format);
return Err(Error::InvalidInput); return Err(Error::InvalidInput);
@ -51,4 +50,4 @@ pub (crate) fn get_destination_path(dest: &Option<File>) -> &Path {
} }
None => Path::new("."), None => Path::new("."),
} }
} }