mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-06 11:35:45 +00:00
Changing the error imports
This commit is contained in:
parent
3e241f8b08
commit
ce26246fd4
39
src/cli.rs
39
src/cli.rs
@ -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 {
|
||||
|
@ -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)?),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>>;
|
||||
}
|
||||
|
@ -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)?),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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),
|
||||
|
@ -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)?),
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
11
src/error.rs
11
src/error.rs
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
src/main.rs
26
src/main.rs
@ -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)
|
||||
}
|
||||
|
120
src/test.rs
120
src/test.rs
@ -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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
src/utils.rs
40
src/utils.rs
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user