Changing the error imports

This commit is contained in:
João M. Bezerra 2021-03-26 13:46:28 -03:00
parent 3e241f8b08
commit ce26246fd4
20 changed files with 277 additions and 322 deletions

View File

@ -1,12 +1,14 @@
use std::{convert::TryFrom, fs, path::{Path, PathBuf}, vec::Vec};
use std::{
convert::TryFrom,
fs,
path::{Path, PathBuf},
vec::Vec,
};
use clap::{Arg, Values};
use colored::Colorize;
use error::Error;
use crate::error;
use crate::extension::Extension;
use crate::file::File;
use crate::{extension::Extension, file::File};
#[derive(PartialEq, Eq, Debug)]
pub enum CommandKind {
@ -68,9 +70,9 @@ pub fn get_matches() -> clap::ArgMatches<'static> {
}
impl TryFrom<clap::ArgMatches<'static>> for Command {
type Error = error::Error;
type Error = crate::Error;
fn try_from(matches: clap::ArgMatches<'static>) -> error::OuchResult<Command> {
fn try_from(matches: clap::ArgMatches<'static>) -> crate::Result<Command> {
let process_decompressible_input = |input_files: Values| {
let input_files =
input_files.map(|filename| (Path::new(filename), Extension::new(filename)));
@ -80,17 +82,21 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
(filename, Ok(_)) => {
let path = Path::new(filename);
if !path.exists() {
return Err(error::Error::FileNotFound(filename.into()))
return Err(crate::Error::FileNotFound(filename.into()));
}
},
}
(filename, Err(_)) => {
return Err(error::Error::InputsMustHaveBeenDecompressible(filename.into()));
return Err(crate::Error::InputsMustHaveBeenDecompressible(
filename.into(),
));
}
}
}
Ok(input_files
.map(|(filename, extension)| (fs::canonicalize(filename).unwrap(), extension.unwrap()))
.map(|(filename, extension)| {
(fs::canonicalize(filename).unwrap(), extension.unwrap())
})
.map(File::from)
.collect::<Vec<_>>())
};
@ -117,11 +123,11 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
if let Err(err) = canonical_path {
let path = PathBuf::from(filename);
if !path.exists() {
return Err(Error::FileNotFound(path))
return Err(crate::Error::FileNotFound(path));
}
eprintln!("{} {}", "[ERROR]".red(), err);
return Err(Error::IOError);
return Err(crate::Error::IOError);
}
}
@ -133,10 +139,9 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
path: output_file.into(),
contents_in_memory: None,
// extension: output_file_extension.ok(),
extension: Some(output_file_extension.unwrap())
extension: Some(output_file_extension.unwrap()),
}),
})
} else {
// Output not supplied
// Checking if input files are decompressible
@ -148,8 +153,8 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
output: Some(File {
path: output_file.into(),
contents_in_memory: None,
extension: None
})
extension: None,
}),
})
}
} else {

View File

@ -2,15 +2,17 @@ use std::{fs, io::Write, path::PathBuf};
use colored::Colorize;
use crate::{error::{Error, OuchResult}, extension::CompressionFormat, file::File};
use crate::utils::{ensure_exists, check_for_multiple_files};
use super::{Compressor, Entry};
use crate::{
extension::CompressionFormat,
file::File,
utils::{check_for_multiple_files, ensure_exists},
};
pub struct BzipCompressor {}
impl BzipCompressor {
fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> crate::Result<Vec<u8>> {
check_for_multiple_files(&files, &format)?;
let path = &files[0];
ensure_exists(path)?;
@ -19,43 +21,43 @@ impl BzipCompressor {
Self::compress_bytes(&*bytes)?
};
println!("{}: compressed {:?} into memory ({} bytes)", "info".yellow(), &path, contents.len());
println!(
"{}: compressed {:?} into memory ({} bytes)",
"info".yellow(),
&path,
contents.len()
);
Ok(contents)
}
fn compress_file_in_memory(file: File) -> OuchResult<Vec<u8>> {
fn compress_file_in_memory(file: File) -> crate::Result<Vec<u8>> {
// Ensure that our file has in-memory content
let bytes = match file.contents_in_memory {
Some(bytes) => bytes,
None => {
// TODO: error message,
return Err(Error::InvalidInput);
return Err(crate::Error::InvalidInput);
}
};
Self::compress_bytes(&*bytes)
}
fn compress_bytes(bytes: &[u8]) -> OuchResult<Vec<u8>> {
fn compress_bytes(bytes: &[u8]) -> crate::Result<Vec<u8>> {
let buffer = vec![];
let mut encoder = bzip2::write::BzEncoder::new(buffer, bzip2::Compression::new(6));
encoder.write_all(bytes)?;
Ok(encoder.finish()?)
}
}
// TODO: customizable compression level
impl Compressor for BzipCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
match from {
Entry::Files(files) => Ok(
Self::compress_files(files, CompressionFormat::Bzip)?
),
Entry::InMemory(file) => Ok(
Self::compress_file_in_memory(file)?
),
Entry::Files(files) => Ok(Self::compress_files(files, CompressionFormat::Bzip)?),
Entry::InMemory(file) => Ok(Self::compress_file_in_memory(file)?),
}
}
}

View File

@ -1,6 +1,6 @@
use std::path::PathBuf;
use crate::{error::OuchResult, file::File};
use crate::file::File;
// pub enum CompressionResult {
// ZipArchive(Vec<u8>),
@ -10,9 +10,9 @@ use crate::{error::OuchResult, file::File};
pub enum Entry {
Files(Vec<PathBuf>),
InMemory(File)
InMemory(File),
}
pub trait Compressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>>;
}
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>>;
}

View File

@ -2,18 +2,20 @@ use std::{fs, io::Write, path::PathBuf};
use colored::Colorize;
use crate::{error::OuchResult, extension::CompressionFormat, file::File};
use crate::utils::{
ensure_exists,
check_for_multiple_files
};
use super::{Compressor, Entry};
use crate::{
extension::CompressionFormat,
file::File,
utils::{check_for_multiple_files, ensure_exists},
};
pub struct GzipCompressor {}
impl GzipCompressor {
pub fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
pub fn compress_files(
files: Vec<PathBuf>,
format: CompressionFormat,
) -> crate::Result<Vec<u8>> {
check_for_multiple_files(&files, &format)?;
let path = &files[0];
@ -34,7 +36,7 @@ impl GzipCompressor {
Ok(bytes)
}
pub fn compress_file_in_memory(file: File) -> OuchResult<Vec<u8>> {
pub fn compress_file_in_memory(file: File) -> crate::Result<Vec<u8>> {
let file_contents = match file.contents_in_memory {
Some(bytes) => bytes,
None => {
@ -45,12 +47,9 @@ impl GzipCompressor {
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>) -> crate::Result<Vec<u8>> {
let buffer = vec![];
let mut encoder = flate2::write::GzEncoder::new(
buffer,
flate2::Compression::default(),
);
let mut encoder = flate2::write::GzEncoder::new(buffer, flate2::Compression::default());
encoder.write_all(&*bytes_to_compress)?;
Ok(encoder.finish()?)
@ -58,15 +57,11 @@ impl GzipCompressor {
}
impl Compressor for GzipCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
let format = CompressionFormat::Gzip;
match from {
Entry::Files(files) => Ok(
Self::compress_files(files, format)?
),
Entry::InMemory(file) => Ok(
Self::compress_file_in_memory(file)?
),
Entry::Files(files) => Ok(Self::compress_files(files, format)?),
Entry::InMemory(file) => Ok(Self::compress_file_in_memory(file)?),
}
}
}

View File

@ -2,18 +2,20 @@ use std::{fs, io::Write, path::PathBuf};
use colored::Colorize;
use crate::{error::{OuchResult}, extension::CompressionFormat, file::File};
use crate::utils::{
ensure_exists,
check_for_multiple_files
};
use super::{Compressor, Entry};
use crate::{
extension::CompressionFormat,
file::File,
utils::{check_for_multiple_files, ensure_exists},
};
pub struct LzmaCompressor {}
impl LzmaCompressor {
pub fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
pub fn compress_files(
files: Vec<PathBuf>,
format: CompressionFormat,
) -> crate::Result<Vec<u8>> {
check_for_multiple_files(&files, &format)?;
let path = &files[0];
@ -34,7 +36,7 @@ impl LzmaCompressor {
Ok(bytes)
}
pub fn compress_file_in_memory(file: File) -> OuchResult<Vec<u8>> {
pub fn compress_file_in_memory(file: File) -> crate::Result<Vec<u8>> {
let file_contents = match file.contents_in_memory {
Some(bytes) => bytes,
None => {
@ -45,7 +47,7 @@ impl LzmaCompressor {
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>) -> crate::Result<Vec<u8>> {
let buffer = vec![];
let mut encoder = xz2::write::XzEncoder::new(buffer, 6);
encoder.write_all(&*bytes_to_compress)?;
@ -55,7 +57,7 @@ impl LzmaCompressor {
}
impl Compressor for LzmaCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
let format = CompressionFormat::Lzma;
match from {
Entry::Files(files) => Self::compress_files(files, format),

View File

@ -1,14 +1,13 @@
mod tar;
mod zip;
mod bzip;
mod compressor;
mod gzip;
mod lzma;
mod compressor;
mod tar;
mod zip;
pub use compressor::Compressor;
pub use self::compressor::Entry;
pub use self::tar::TarCompressor;
pub use self::zip::ZipCompressor;
pub use self::bzip::BzipCompressor;
pub use self::gzip::GzipCompressor;
pub use self::lzma::LzmaCompressor;
pub use self::{
bzip::BzipCompressor, compressor::Entry, gzip::GzipCompressor, lzma::LzmaCompressor,
tar::TarCompressor, zip::ZipCompressor,
};

View File

@ -4,28 +4,23 @@ use colored::Colorize;
use tar::Builder;
use walkdir::WalkDir;
use crate::{
compressors::Compressor,
error::{Error, OuchResult},
file::File,
};
use super::compressor::Entry;
use crate::{compressors::Compressor, file::File};
pub struct TarCompressor {}
impl TarCompressor {
// TODO: implement this
fn make_archive_from_memory(_input: File) -> OuchResult<Vec<u8>> {
fn make_archive_from_memory(_input: File) -> crate::Result<Vec<u8>> {
println!(
"{}: .tar.tar and .zip.tar is currently unimplemented.",
"error".red()
);
Err(Error::InvalidZipArchive(""))
Err(crate::Error::InvalidZipArchive(""))
}
fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> OuchResult<Vec<u8>> {
let change_dir_and_return_parent = |filename: &PathBuf| -> OuchResult<PathBuf> {
fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> crate::Result<Vec<u8>> {
let change_dir_and_return_parent = |filename: &PathBuf| -> crate::Result<PathBuf> {
let previous_location = env::current_dir()?;
let parent = filename.parent().unwrap();
env::set_current_dir(parent)?;
@ -55,7 +50,7 @@ impl TarCompressor {
}
impl Compressor for TarCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
match from {
Entry::Files(filenames) => Self::make_archive_from_files(filenames),
Entry::InMemory(file) => Self::make_archive_from_memory(file),

View File

@ -1,20 +1,18 @@
use std::{io::{Cursor, Write}, path::PathBuf};
use std::{
io::{Cursor, Write},
path::PathBuf,
};
use walkdir::WalkDir;
use crate::{
compressors::Compressor,
error::{Error, OuchResult},
file::File,
};
use super::compressor::Entry;
use crate::{compressors::Compressor, file::File};
pub struct ZipCompressor {}
impl ZipCompressor {
// TODO: this function does not seem to be working correctly ;/
fn make_archive_from_memory(input: File) -> OuchResult<Vec<u8>> {
fn make_archive_from_memory(input: File) -> crate::Result<Vec<u8>> {
let buffer = vec![];
let mut writer = zip::ZipWriter::new(std::io::Cursor::new(buffer));
@ -23,7 +21,7 @@ impl ZipCompressor {
.file_stem()
.ok_or(
// TODO: Is this reachable?
Error::InvalidInput
crate::Error::InvalidInput,
)?
.to_string_lossy()
.into();
@ -38,20 +36,18 @@ impl ZipCompressor {
None => {
// TODO: error description, although this block should not be
// reachable
return Err(Error::InvalidInput);
return Err(crate::Error::InvalidInput);
}
};
writer.write_all(&*input_bytes)?;
let bytes = writer.finish().unwrap();
Ok(bytes.into_inner())
}
fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> OuchResult<Vec<u8>> {
fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> crate::Result<Vec<u8>> {
let buffer = vec![];
let mut writer = zip::ZipWriter::new(Cursor::new(buffer));
@ -65,17 +61,12 @@ impl ZipCompressor {
if entry_path.is_dir() {
continue;
}
writer
.start_file(
entry_path.to_string_lossy(),
options
)?;
writer.start_file(entry_path.to_string_lossy(), options)?;
let file_bytes = std::fs::read(entry.path())?;
writer.write_all(&*file_bytes)?;
}
}
let bytes = writer.finish().unwrap();
Ok(bytes.into_inner())
@ -83,7 +74,7 @@ impl ZipCompressor {
}
impl Compressor for ZipCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
match from {
Entry::Files(filenames) => Ok(Self::make_archive_from_files(filenames)?),
Entry::InMemory(file) => Ok(Self::make_archive_from_memory(file)?),

View File

@ -1,12 +1,12 @@
use std::path::PathBuf;
use crate::{error::OuchResult, file::File};
use crate::file::File;
pub enum DecompressionResult {
FilesUnpacked(Vec<PathBuf>),
FileInMemory(Vec<u8>)
FileInMemory(Vec<u8>),
}
pub trait Decompressor {
fn decompress(&self, from: File, into: &Option<File>) -> OuchResult<DecompressionResult>;
}
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult>;
}

View File

@ -1,18 +1,15 @@
mod decompressor;
mod tomemory;
mod tar;
mod tomemory;
mod zip;
pub use decompressor::Decompressor;
pub use decompressor::DecompressionResult;
pub use self::tar::TarDecompressor;
pub use self::zip::ZipDecompressor;
pub use decompressor::{DecompressionResult, Decompressor};
// These decompressors only decompress to memory,
// unlike {Tar, Zip}Decompressor which are capable of
// decompressing directly to storage
pub use self::tomemory::GzipDecompressor;
pub use self::tomemory::BzipDecompressor;
pub use self::tomemory::LzmaDecompressor;
pub use self::{
tar::TarDecompressor,
tomemory::{BzipDecompressor, GzipDecompressor, LzmaDecompressor},
zip::ZipDecompressor,
};

View File

@ -1,27 +1,29 @@
use std::{fs, io::{Cursor, Read}, path::{Path, PathBuf}};
use std::{
fs,
io::{Cursor, Read},
path::{Path, PathBuf},
};
use colored::Colorize;
use tar::{self, Archive};
use crate::{error::OuchResult, utils};
use crate::file::File;
use super::decompressor::{DecompressionResult, Decompressor};
use crate::{file::File, utils};
#[derive(Debug)]
pub struct TarDecompressor {}
impl TarDecompressor {
fn unpack_files(from: File, into: &Path) -> OuchResult<Vec<PathBuf>> {
println!("{}: attempting to decompress {:?}", "ouch".bright_blue(), &from.path);
fn unpack_files(from: File, into: &Path) -> crate::Result<Vec<PathBuf>> {
println!(
"{}: attempting to decompress {:?}",
"ouch".bright_blue(),
&from.path
);
let mut files_unpacked = vec![];
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 => {
let file = fs::File::open(&from.path)?;
tar::Archive::new(Box::new(file))
@ -50,7 +52,7 @@ impl TarDecompressor {
}
impl Decompressor for TarDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> OuchResult<DecompressionResult> {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> {
let destination_path = utils::get_destination_path(into);
utils::create_path_if_non_existent(destination_path)?;
@ -59,4 +61,4 @@ impl Decompressor for TarDecompressor {
Ok(DecompressionResult::FilesUnpacked(files_unpacked))
}
}
}

View File

@ -3,35 +3,32 @@ use std::{
path::Path,
};
use colored::Colorize;
use super::decompressor::{DecompressionResult, Decompressor};
use crate::utils;
// use niffler;
use crate::{extension::CompressionFormat, file::File};
use crate::{
error::OuchResult,
utils,
};
use super::decompressor::DecompressionResult;
use super::decompressor::Decompressor;
struct DecompressorToMemory {}
pub struct GzipDecompressor {}
pub struct LzmaDecompressor {}
pub struct BzipDecompressor {}
fn get_decoder<'a>(format: CompressionFormat, buffer: Box<dyn io::Read + Send + 'a>) -> Box<dyn io::Read + Send + 'a> {
fn get_decoder<'a>(
format: CompressionFormat,
buffer: Box<dyn io::Read + Send + 'a>,
) -> Box<dyn io::Read + Send + 'a> {
match format {
CompressionFormat::Bzip => Box::new(bzip2::read::BzDecoder::new(buffer)),
CompressionFormat::Gzip => Box::new(flate2::read::MultiGzDecoder::new(buffer)),
CompressionFormat::Lzma => Box::new(xz2::read::XzDecoder::new_multi_decoder(buffer)),
_other => unreachable!()
_other => unreachable!(),
}
}
impl DecompressorToMemory {
fn unpack_file(from: &Path, format: CompressionFormat) -> OuchResult<Vec<u8>> {
fn unpack_file(from: &Path, format: CompressionFormat) -> crate::Result<Vec<u8>> {
let file = std::fs::read(from)?;
let mut reader = get_decoder(format, Box::new(&file[..]));
@ -49,7 +46,11 @@ impl DecompressorToMemory {
Ok(buffer)
}
fn decompress(from: File, format: CompressionFormat, into: &Option<File>) -> OuchResult<DecompressionResult> {
fn decompress(
from: File,
format: CompressionFormat,
into: &Option<File>,
) -> crate::Result<DecompressionResult> {
let destination_path = utils::get_destination_path(into);
utils::create_path_if_non_existent(destination_path)?;
@ -61,19 +62,19 @@ impl DecompressorToMemory {
}
impl Decompressor for GzipDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> OuchResult<DecompressionResult> {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> {
DecompressorToMemory::decompress(from, CompressionFormat::Gzip, into)
}
}
impl Decompressor for BzipDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> OuchResult<DecompressionResult> {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> {
DecompressorToMemory::decompress(from, CompressionFormat::Bzip, into)
}
}
impl Decompressor for LzmaDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> OuchResult<DecompressionResult> {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> {
DecompressorToMemory::decompress(from, CompressionFormat::Lzma, into)
}
}
}

View File

@ -1,12 +1,14 @@
use std::{fs, io::{self, Cursor, Read, Seek}, path::{Path, PathBuf}};
use std::{
fs,
io::{self, Cursor, Read, Seek},
path::{Path, PathBuf},
};
use colored::Colorize;
use zip::{self, ZipArchive, read::ZipFile};
use crate::{error, file::File};
use crate::{error::OuchResult, utils};
use zip::{self, read::ZipFile, ZipArchive};
use super::decompressor::{DecompressionResult, Decompressor};
use crate::{file::File, utils};
pub struct ZipDecompressor {}
@ -26,7 +28,7 @@ impl ZipDecompressor {
pub fn zip_decompress<T>(
archive: &mut ZipArchive<T>,
into: &Path,
) -> error::OuchResult<Vec<PathBuf>>
) -> crate::Result<Vec<PathBuf>>
where
T: Read + Seek,
{
@ -72,33 +74,29 @@ impl ZipDecompressor {
Ok(unpacked_files)
}
fn unpack_files(from: File, into: &Path) -> OuchResult<Vec<PathBuf>> {
fn unpack_files(from: File, into: &Path) -> crate::Result<Vec<PathBuf>> {
println!(
"{}: attempting to decompress {:?}",
"ouch".bright_blue(),
&from.path
);
match from.contents_in_memory {
Some(bytes) => {
let mut archive = zip::ZipArchive::new(Cursor::new(bytes))?;
Ok(Self::zip_decompress(&mut archive, into)?)
},
}
None => {
let file = fs::File::open(&from.path)?;
let mut archive = zip::ZipArchive::new(file)?;
Ok(Self::zip_decompress(&mut archive, into)?)
}
}
}
}
impl Decompressor for ZipDecompressor {
fn decompress(&self, from: File, into: &Option<File>) -> OuchResult<DecompressionResult> {
fn decompress(&self, from: File, into: &Option<File>) -> crate::Result<DecompressionResult> {
let destination_path = utils::get_destination_path(into);
utils::create_path_if_non_existent(destination_path)?;

View File

@ -18,7 +18,7 @@ pub enum Error {
InputsMustHaveBeenDecompressible(PathBuf),
}
pub type OuchResult<T> = Result<T, Error>;
pub type Result<T> = std::result::Result<T, Error>;
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -26,10 +26,10 @@ impl fmt::Display for Error {
match self {
Error::MissingExtensionError(filename) => {
write!(f, "cannot compress to \'{}\', likely because it has an unsupported (or missing) extension.", filename)
},
}
Error::InputsMustHaveBeenDecompressible(file) => {
write!(f, "file '{:?}' is not decompressible", file)
},
}
Error::FileNotFound(file) => {
// TODO: check if file == ""
write!(f, "file {:?} not found!", file)
@ -63,7 +63,7 @@ impl From<zip::result::ZipError> for Error {
Io(io_err) => Self::from(io_err),
InvalidArchive(filename) => Self::InvalidZipArchive(filename),
FileNotFound => Self::FileNotFound("".into()),
UnsupportedArchive(filename) => Self::UnsupportedZipArchive(filename)
UnsupportedArchive(filename) => Self::UnsupportedZipArchive(filename),
}
}
}
@ -71,7 +71,6 @@ impl From<zip::result::ZipError> for Error {
impl From<walkdir::Error> for Error {
fn from(err: walkdir::Error) -> Self {
eprintln!("{}: {}", "error".red(), err);
Self::InvalidInput
}
}
}

View File

@ -2,31 +2,27 @@ use std::{ffi::OsStr, fs, io::Write, path::PathBuf};
use colored::Colorize;
use crate::compressors::{
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor, ZipCompressor,
use crate::{
cli::{Command, CommandKind},
compressors::{
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor,
ZipCompressor,
},
decompressors::{
BzipDecompressor, DecompressionResult, Decompressor, GzipDecompressor, LzmaDecompressor,
TarDecompressor, ZipDecompressor,
},
extension::{CompressionFormat, Extension},
file::File,
utils,
};
use crate::decompressors::{
BzipDecompressor, DecompressionResult, Decompressor, GzipDecompressor, LzmaDecompressor,
TarDecompressor, ZipDecompressor,
};
use crate::extension::{CompressionFormat, Extension};
use crate::cli::{Command, CommandKind};
use crate::error::{self, OuchResult};
use crate::file::File;
use crate::utils;
pub struct Evaluator {}
impl Evaluator {
pub fn get_compressor(
file: &File,
) -> error::OuchResult<(Option<Box<dyn Compressor>>, Box<dyn Compressor>)> {
) -> crate::Result<(Option<Box<dyn Compressor>>, Box<dyn Compressor>)> {
let extension = match &file.extension {
Some(extension) => extension.clone(),
None => {
@ -35,7 +31,7 @@ impl Evaluator {
"{}: reached Evaluator::get_decompressor without known extension.",
"internal error".red()
);
return Err(error::Error::InvalidInput);
return Err(crate::Error::InvalidInput);
}
};
@ -44,9 +40,7 @@ impl Evaluator {
let first_compressor: Option<Box<dyn Compressor>> = match extension.first_ext {
Some(ext) => match ext {
CompressionFormat::Tar => Some(Box::new(TarCompressor {})),
CompressionFormat::Zip => Some(Box::new(ZipCompressor {})),
// _other => Some(Box::new(NifflerCompressor {})),
_other => {
todo!();
@ -70,7 +64,7 @@ impl Evaluator {
pub fn get_decompressor(
file: &File,
) -> error::OuchResult<(Option<Box<dyn Decompressor>>, Box<dyn Decompressor>)> {
) -> crate::Result<(Option<Box<dyn Decompressor>>, Box<dyn Decompressor>)> {
let extension = match &file.extension {
Some(extension) => extension.clone(),
None => {
@ -79,28 +73,22 @@ impl Evaluator {
"{}: reached Evaluator::get_decompressor without known extension.",
"internal error".red()
);
return Err(error::Error::InvalidInput);
return Err(crate::Error::InvalidInput);
}
};
let second_decompressor: Box<dyn Decompressor> = match extension.second_ext {
CompressionFormat::Tar => Box::new(TarDecompressor {}),
CompressionFormat::Zip => Box::new(ZipDecompressor {}),
CompressionFormat::Gzip => Box::new(GzipDecompressor {}),
CompressionFormat::Lzma => Box::new(LzmaDecompressor {}),
CompressionFormat::Bzip => Box::new(BzipDecompressor {}),
};
let first_decompressor: Option<Box<dyn Decompressor>> = match extension.first_ext {
Some(ext) => match ext {
CompressionFormat::Tar => Some(Box::new(TarDecompressor {})),
CompressionFormat::Zip => Some(Box::new(ZipDecompressor {})),
_other => None,
},
None => None,
@ -116,18 +104,18 @@ impl Evaluator {
decompressor: Option<Box<dyn Decompressor>>,
output_file: &Option<File>,
extension: Option<Extension>,
) -> OuchResult<()> {
) -> crate::Result<()> {
let output_file_path = utils::get_destination_path(output_file);
let mut filename = file_path
.file_stem()
.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.
filename = OsStr::new("ouch-output");
}
let filename = PathBuf::from(filename);
// If there is a decompressor to use, we'll create a file in-memory and decompress it
@ -136,7 +124,6 @@ impl Evaluator {
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);
let mut f = fs::File::create(output_file_path.join(filename))?;
@ -160,7 +147,7 @@ impl Evaluator {
Ok(())
}
fn compress_files(files: Vec<PathBuf>, mut output: File) -> error::OuchResult<()> {
fn compress_files(files: Vec<PathBuf>, mut output: File) -> crate::Result<()> {
let (first_compressor, second_compressor) = Self::get_compressor(&output)?;
let output_path = output.path.clone();
@ -171,9 +158,7 @@ impl Evaluator {
let bytes = first_compressor.compress(entry)?;
output.contents_in_memory = Some(bytes);
entry = Entry::InMemory(output);
second_compressor.compress(entry)?
}
None => {
@ -193,7 +178,7 @@ impl Evaluator {
Ok(())
}
fn decompress_file(file: File, output: &Option<File>) -> error::OuchResult<()> {
fn decompress_file(file: File, output: &Option<File>) -> crate::Result<()> {
// let output_file = &command.output;
let (first_decompressor, second_decompressor) = Self::get_decompressor(&file)?;
@ -228,7 +213,7 @@ impl Evaluator {
Ok(())
}
pub fn evaluate(command: Command) -> error::OuchResult<()> {
pub fn evaluate(command: Command) -> crate::Result<()> {
let output = command.output.clone();
match command.kind {

View File

@ -5,7 +5,6 @@ use std::{
path::{Path, PathBuf},
};
use crate::error;
use CompressionFormat::*;
/// Represents the extension of a file, but only really caring about
@ -44,14 +43,14 @@ impl From<CompressionFormat> for Extension {
}
impl Extension {
pub fn new(filename: &str) -> error::OuchResult<Self> {
pub fn new(filename: &str) -> crate::Result<Self> {
let ext_from_str = |ext| match ext {
"zip" => Ok(Zip),
"tar" => Ok(Tar),
"gz" => Ok(Gzip),
"bz" | "bz2" => Ok(Bzip),
"xz" | "lz" | "lzma" => Ok(Lzma),
other => Err(error::Error::UnknownExtensionError(other.into())),
other => Err(crate::Error::UnknownExtensionError(other.into())),
};
let (first_ext, second_ext) = match get_extension_from_filename(filename) {
@ -59,7 +58,7 @@ impl Extension {
("", snd) => (None, snd),
(fst, snd) => (Some(fst), snd),
},
None => return Err(error::Error::MissingExtensionError(filename.into())),
None => return Err(crate::Error::MissingExtensionError(filename.into())),
};
let (first_ext, second_ext) = match (first_ext, second_ext) {
@ -96,12 +95,12 @@ pub enum CompressionFormat {
Zip,
}
fn extension_from_os_str(ext: &OsStr) -> Result<CompressionFormat, error::Error> {
fn extension_from_os_str(ext: &OsStr) -> Result<CompressionFormat, crate::Error> {
// let ext = Path::new(ext);
let ext = match ext.to_str() {
Some(str) => str,
None => return Err(error::Error::InvalidUnicode),
None => return Err(crate::Error::InvalidUnicode),
};
match ext {
@ -110,18 +109,18 @@ fn extension_from_os_str(ext: &OsStr) -> Result<CompressionFormat, error::Error>
"gz" => Ok(Gzip),
"bz" | "bz2" => Ok(Bzip),
"xz" | "lzma" | "lz" => Ok(Lzma),
other => Err(error::Error::UnknownExtensionError(other.into())),
other => Err(crate::Error::UnknownExtensionError(other.into())),
}
}
impl TryFrom<&PathBuf> for CompressionFormat {
type Error = error::Error;
type Error = crate::Error;
fn try_from(ext: &PathBuf) -> Result<Self, Self::Error> {
let ext = match ext.extension() {
Some(ext) => ext,
None => {
return Err(error::Error::MissingExtensionError(String::new()));
return Err(crate::Error::MissingExtensionError(String::new()));
}
};
extension_from_os_str(ext)
@ -129,13 +128,13 @@ impl TryFrom<&PathBuf> for CompressionFormat {
}
impl TryFrom<&str> for CompressionFormat {
type Error = error::Error;
type Error = crate::Error;
fn try_from(filename: &str) -> Result<Self, Self::Error> {
let filename = Path::new(filename);
let ext = match filename.extension() {
Some(ext) => ext,
None => return Err(error::Error::MissingExtensionError(String::new())),
None => return Err(crate::Error::MissingExtensionError(String::new())),
};
extension_from_os_str(ext)

View File

@ -2,7 +2,6 @@ use std::path::PathBuf;
use crate::extension::Extension;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct File {
/// File's (relative) path
@ -15,7 +14,7 @@ pub struct File {
///
/// So, for example, if a file has pathname "image.jpeg", it does have a JPEG extension but will
/// be represented as a None over here since that's not an extension we're particularly interested in
pub extension: Option<Extension>
pub extension: Option<Extension>,
}
impl From<(PathBuf, Extension)> for File {
@ -26,4 +25,4 @@ impl From<(PathBuf, Extension)> for File {
extension: Some(format),
}
}
}
}

View File

@ -1,6 +1,6 @@
use std::convert::TryFrom;
mod cli;
mod compressors;
mod decompressors;
mod error;
mod evaluator;
mod extension;
@ -8,25 +8,13 @@ mod file;
mod test;
mod utils;
mod compressors;
mod decompressors;
use std::convert::TryFrom;
pub use error::{Error, Result};
use evaluator::Evaluator;
fn main() -> error::OuchResult<()> {
let print_error = |err| {
println!("{}", err);
err
};
fn main() -> crate::Result<()> {
let matches = cli::get_matches();
let command = match cli::Command::try_from(matches) {
Ok(command) => command,
Err(err) => return Err(print_error(err))
};
match Evaluator::evaluate(command) {
Ok(_) => Ok(()),
Err(err) => Err(print_error(err))
}
let command = cli::Command::try_from(matches)?;
Evaluator::evaluate(command)
}

View File

@ -2,27 +2,27 @@
#[cfg(test)]
mod cli {
use crate::cli::clap_app;
use crate::cli::Command;
use crate::cli::CommandKind::*;
use crate::error::OuchResult;
use crate::extension::CompressionFormat::*;
use crate::extension::Extension;
use crate::file::File;
use std::{convert::TryFrom, fs, path::Path};
use crate::{
cli::{clap_app, Command, CommandKind::*},
extension::{CompressionFormat::*, Extension},
file::File,
};
// ouch's command-line logic uses fs::canonicalize on its inputs so we cannot
// use made-up files for testing.
// make_dummy_file therefores creates a small temporary file to bypass fs::canonicalize errors
fn make_dummy_file<'a, P>(path: P) -> OuchResult<()>
where P: AsRef<Path> + 'a {
fn make_dummy_file<'a, P>(path: P) -> crate::Result<()>
where
P: AsRef<Path> + 'a,
{
fs::write(path.as_ref(), &[2, 3, 4, 5, 6, 7, 8, 9, 10])?;
Ok(())
}
#[test]
fn decompress_files_into_folder() -> OuchResult<()> {
fn decompress_files_into_folder() -> crate::Result<()> {
make_dummy_file("file.zip")?;
let matches = clap_app().get_matches_from(vec!["ouch", "-i", "file.zip", "-o", "folder/"]);
let command_from_matches = Command::try_from(matches)?;
@ -30,13 +30,11 @@ mod cli {
assert_eq!(
command_from_matches,
Command {
kind: Decompression(vec![
File {
path: fs::canonicalize("file.zip")?,
contents_in_memory: None,
extension: Some(Extension::from(Zip))
}
]),
kind: Decompression(vec![File {
path: fs::canonicalize("file.zip")?,
contents_in_memory: None,
extension: Some(Extension::from(Zip))
}]),
output: Some(File {
path: "folder".into(),
contents_in_memory: None,
@ -51,22 +49,23 @@ mod cli {
}
#[test]
fn decompress_files() -> OuchResult<()> {
fn decompress_files() -> crate::Result<()> {
make_dummy_file("my-cool-file.zip")?;
make_dummy_file("file.tar")?;
let matches = clap_app().get_matches_from(vec!["ouch", "-i", "my-cool-file.zip", "file.tar"]);
let matches =
clap_app().get_matches_from(vec!["ouch", "-i", "my-cool-file.zip", "file.tar"]);
let command_from_matches = Command::try_from(matches)?;
assert_eq!(
command_from_matches,
Command {
kind: Decompression(vec![
File {
File {
path: fs::canonicalize("my-cool-file.zip")?,
contents_in_memory: None,
extension: Some(Extension::from(Zip))
},
File {
File {
path: fs::canonicalize("file.tar")?,
contents_in_memory: None,
extension: Some(Extension::from(Tar))
@ -83,8 +82,7 @@ mod cli {
}
#[test]
fn compress_files() -> OuchResult<()> {
fn compress_files() -> crate::Result<()> {
make_dummy_file("file")?;
make_dummy_file("file2.jpeg")?;
make_dummy_file("file3.ok")?;
@ -108,13 +106,11 @@ mod cli {
fs::canonicalize("file2.jpeg")?,
fs::canonicalize("file3.ok")?
]),
output: Some(
File {
path: "file.tar".into(),
contents_in_memory: None,
extension: Some(Extension::from(Tar))
}
),
output: Some(File {
path: "file.tar".into(),
contents_in_memory: None,
extension: Some(Extension::from(Tar))
}),
}
);
@ -131,20 +127,22 @@ mod cli_errors {
use std::convert::TryFrom;
use crate::cli::clap_app;
use crate::cli::Command;
use crate::error::Error;
use crate::error::OuchResult;
use crate::{
cli::{clap_app, Command},
error::crate::{Error, Result},
};
#[test]
fn compress_files() -> OuchResult<()> {
fn compress_files() -> crate::Result<()> {
let matches =
clap_app().get_matches_from(vec!["ouch", "-i", "a_file", "file2.jpeg", "file3.ok"]);
let res = Command::try_from(matches);
assert_eq!(
res,
Err(Error::InputsMustHaveBeenDecompressible("a_file".into()))
Err(crate::Error::InputsMustHaveBeenDecompressible(
"a_file".into()
))
);
Ok(())
@ -153,23 +151,23 @@ mod cli_errors {
#[cfg(test)]
mod extension_extraction {
use crate::{error::OuchResult, extension::Extension} ;
use crate::extension::CompressionFormat;
use std::{convert::TryFrom, path::PathBuf, str::FromStr};
use crate::{
error::crate::Result,
extension::{CompressionFormat, Extension},
};
#[test]
fn zip() -> OuchResult<()> {
fn zip() -> crate::Result<()> {
let path = PathBuf::from_str("filename.tar.zip").unwrap();
assert_eq!(
CompressionFormat::try_from(&path)?,
CompressionFormat::Zip
);
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Zip);
Ok(())
}
#[test]
fn tar_gz() -> OuchResult<()> {
fn tar_gz() -> crate::Result<()> {
let extension = Extension::new("folder.tar.gz")?;
assert_eq!(
@ -184,46 +182,34 @@ mod extension_extraction {
}
#[test]
fn tar() -> OuchResult<()> {
fn tar() -> crate::Result<()> {
let path = PathBuf::from_str("pictures.tar").unwrap();
assert_eq!(
CompressionFormat::try_from(&path)?,
CompressionFormat::Tar
);
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Tar);
Ok(())
}
#[test]
fn gz() -> OuchResult<()> {
fn gz() -> crate::Result<()> {
let path = PathBuf::from_str("passwords.tar.gz").unwrap();
assert_eq!(
CompressionFormat::try_from(&path)?,
CompressionFormat::Gzip
);
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Gzip);
Ok(())
}
#[test]
fn lzma() -> OuchResult<()> {
fn lzma() -> crate::Result<()> {
let path = PathBuf::from_str("mygame.tar.lzma").unwrap();
assert_eq!(
CompressionFormat::try_from(&path)?,
CompressionFormat::Lzma
);
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Lzma);
Ok(())
}
#[test]
fn bz() -> OuchResult<()> {
fn bz() -> crate::Result<()> {
let path = PathBuf::from_str("songs.tar.bz").unwrap();
assert_eq!(
CompressionFormat::try_from(&path)?,
CompressionFormat::Bzip
);
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Bzip);
Ok(())
}
}
}

View File

@ -1,29 +1,41 @@
use std::{fs, path::{Path, PathBuf}};
use std::{
fs,
path::{Path, PathBuf},
};
use colored::Colorize;
use crate::{error::{Error, OuchResult}, extension::CompressionFormat, file::File};
pub (crate) fn ensure_exists<'a, P>(path: P) -> OuchResult<()>
use crate::{extension::CompressionFormat, file::File};
pub(crate) fn ensure_exists<'a, P>(path: P) -> crate::Result<()>
where
P: AsRef<Path> + 'a {
let exists = path.as_ref().exists();
if !exists {
eprintln!("{}: could not find file {:?}", "[ERROR]".red(), path.as_ref());
return Err(Error::FileNotFound(PathBuf::from(path.as_ref())));
}
Ok(())
P: AsRef<Path> + 'a,
{
let exists = path.as_ref().exists();
if !exists {
eprintln!(
"{}: could not find file {:?}",
"[ERROR]".red(),
path.as_ref()
);
return Err(crate::Error::FileNotFound(PathBuf::from(path.as_ref())));
}
Ok(())
}
pub (crate) fn check_for_multiple_files(files: &[PathBuf], format: &CompressionFormat) -> OuchResult<()> {
pub(crate) fn check_for_multiple_files(
files: &[PathBuf],
format: &CompressionFormat,
) -> crate::Result<()> {
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);
return Err(crate::Error::InvalidInput);
}
Ok(())
}
pub (crate) fn create_path_if_non_existent(path: &Path) -> OuchResult<()> {
pub(crate) fn create_path_if_non_existent(path: &Path) -> crate::Result<()> {
if !path.exists() {
println!(
"{}: attempting to create folder {:?}.",
@ -40,7 +52,7 @@ pub (crate) fn create_path_if_non_existent(path: &Path) -> OuchResult<()> {
Ok(())
}
pub (crate) fn get_destination_path(dest: &Option<File>) -> &Path {
pub(crate) fn get_destination_path(dest: &Option<File>) -> &Path {
match dest {
Some(output) => {
// Must be None according to the way command-line arg. parsing in Ouch works