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(
"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.
`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`
Please relate any issues or contribute at https://github.com/vrmiguel/ouch")
.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_extension = Extension::new(output_file);
let output_is_compressible = output_file_extension.is_ok();
if output_is_compressible {
// 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();
return Ok(Command {
Ok(Command {
kind: CommandKind::Compression(input_files),
output: Some(File {
path: output_file.into(),
contents_in_memory: None,
// extension: output_file_extension.ok(),
extension: Some(output_file_extension.unwrap())
}),
});
})
} else {
// Output not supplied
@ -142,14 +143,14 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
let input_files = process_decompressible_input(input_files)?;
return Ok(Command {
Ok(Command {
kind: CommandKind::Decompression(input_files),
output: Some(File {
path: output_file.into(),
contents_in_memory: None,
extension: None
})
});
})
}
} else {
// else: output file not supplied
@ -157,10 +158,10 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
// Case 2: error
let input_files = process_decompressible_input(input_files)?;
return Ok(Command {
Ok(Command {
kind: CommandKind::Decompression(input_files),
output: None,
});
})
}
}
}

View File

@ -20,7 +20,7 @@ impl BzipCompressor {
};
println!("{}: compressed {:?} into memory ({} bytes)", "info".yellow(), &path, contents.len());
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>> {
@ -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>> {

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>> {
let buffer = vec![];
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>> {
let format = CompressionFormat::Lzma;
match from {
Entry::Files(files) => Ok(
Self::compress_files(files, format)?
),
Entry::InMemory(file) => Ok(
Self::compress_file_in_memory(file)?
),
Entry::Files(files) => Self::compress_files(files, format),
Entry::InMemory(file) => Self::compress_file_in_memory(file),
}
}
}
}

View File

@ -4,32 +4,37 @@ use colored::Colorize;
use tar::Builder;
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;
pub struct TarCompressor {}
impl TarCompressor {
// TODO: implement this
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(""))
}
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 parent = filename.parent().unwrap();
env::set_current_dir(parent)?;
Ok(previous_location)
};
let buf = Vec::new();
let mut b = Builder::new(buf);
for filename in input_filenames {
let previous_location = change_dir_and_return_parent(&filename)?;
// Safe unwrap since this filename came from `fs::canonicalize`.
@ -44,25 +49,16 @@ impl TarCompressor {
}
env::set_current_dir(previous_location)?;
}
Ok(b.into_inner()?)
}
}
impl Compressor for TarCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
match from {
Entry::Files(filenames) => {
Ok(
Self::make_archive_from_files(filenames)?
)
},
Entry::InMemory(file) => {
Ok(
Self::make_archive_from_memory(file)?
)
}
}
Entry::Files(filenames) => Self::make_archive_from_files(filenames),
Entry::InMemory(file) => 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();
Ok(bytes.into_inner())
@ -67,14 +67,14 @@ impl ZipCompressor {
}
writer
.start_file(
entry_path.to_string_lossy(),
entry_path.to_string_lossy(),
options
)?;
let file_bytes = std::fs::read(entry.path())?;
writer.write(&*file_bytes)?;
writer.write_all(&*file_bytes)?;
}
}
let bytes = writer.finish().unwrap();

View File

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

View File

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

View File

@ -14,8 +14,7 @@ where
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 {
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);
@ -51,4 +50,4 @@ pub (crate) fn get_destination_path(dest: &Option<File>) -> &Path {
}
None => Path::new("."),
}
}
}