mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-07 20:15:27 +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 clap::{Arg, Values};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use error::Error;
|
|
||||||
|
|
||||||
use crate::error;
|
use crate::{extension::Extension, file::File};
|
||||||
use crate::extension::Extension;
|
|
||||||
use crate::file::File;
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub enum CommandKind {
|
pub enum CommandKind {
|
||||||
@ -68,9 +70,9 @@ pub fn get_matches() -> clap::ArgMatches<'static> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<clap::ArgMatches<'static>> for Command {
|
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 process_decompressible_input = |input_files: Values| {
|
||||||
let input_files =
|
let input_files =
|
||||||
input_files.map(|filename| (Path::new(filename), Extension::new(filename)));
|
input_files.map(|filename| (Path::new(filename), Extension::new(filename)));
|
||||||
@ -80,17 +82,21 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
|
|||||||
(filename, Ok(_)) => {
|
(filename, Ok(_)) => {
|
||||||
let path = Path::new(filename);
|
let path = Path::new(filename);
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return Err(error::Error::FileNotFound(filename.into()))
|
return Err(crate::Error::FileNotFound(filename.into()));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
(filename, Err(_)) => {
|
(filename, Err(_)) => {
|
||||||
return Err(error::Error::InputsMustHaveBeenDecompressible(filename.into()));
|
return Err(crate::Error::InputsMustHaveBeenDecompressible(
|
||||||
|
filename.into(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(input_files
|
Ok(input_files
|
||||||
.map(|(filename, extension)| (fs::canonicalize(filename).unwrap(), extension.unwrap()))
|
.map(|(filename, extension)| {
|
||||||
|
(fs::canonicalize(filename).unwrap(), extension.unwrap())
|
||||||
|
})
|
||||||
.map(File::from)
|
.map(File::from)
|
||||||
.collect::<Vec<_>>())
|
.collect::<Vec<_>>())
|
||||||
};
|
};
|
||||||
@ -117,11 +123,11 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
|
|||||||
if let Err(err) = canonical_path {
|
if let Err(err) = canonical_path {
|
||||||
let path = PathBuf::from(filename);
|
let path = PathBuf::from(filename);
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return Err(Error::FileNotFound(path))
|
return Err(crate::Error::FileNotFound(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("{} {}", "[ERROR]".red(), err);
|
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(),
|
path: output_file.into(),
|
||||||
contents_in_memory: None,
|
contents_in_memory: None,
|
||||||
// extension: output_file_extension.ok(),
|
// extension: output_file_extension.ok(),
|
||||||
extension: Some(output_file_extension.unwrap())
|
extension: Some(output_file_extension.unwrap()),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Output not supplied
|
// Output not supplied
|
||||||
// Checking if input files are decompressible
|
// Checking if input files are decompressible
|
||||||
@ -148,8 +153,8 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
|
|||||||
output: Some(File {
|
output: Some(File {
|
||||||
path: output_file.into(),
|
path: output_file.into(),
|
||||||
contents_in_memory: None,
|
contents_in_memory: None,
|
||||||
extension: None
|
extension: None,
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,15 +2,17 @@ use std::{fs, io::Write, path::PathBuf};
|
|||||||
|
|
||||||
use colored::Colorize;
|
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 super::{Compressor, Entry};
|
||||||
|
use crate::{
|
||||||
|
extension::CompressionFormat,
|
||||||
|
file::File,
|
||||||
|
utils::{check_for_multiple_files, ensure_exists},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct BzipCompressor {}
|
pub struct BzipCompressor {}
|
||||||
|
|
||||||
impl 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)?;
|
check_for_multiple_files(&files, &format)?;
|
||||||
let path = &files[0];
|
let path = &files[0];
|
||||||
ensure_exists(path)?;
|
ensure_exists(path)?;
|
||||||
@ -19,43 +21,43 @@ impl BzipCompressor {
|
|||||||
Self::compress_bytes(&*bytes)?
|
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)
|
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
|
// Ensure that our file has in-memory content
|
||||||
let bytes = match file.contents_in_memory {
|
let bytes = match file.contents_in_memory {
|
||||||
Some(bytes) => bytes,
|
Some(bytes) => bytes,
|
||||||
None => {
|
None => {
|
||||||
// TODO: error message,
|
// TODO: error message,
|
||||||
return Err(Error::InvalidInput);
|
return Err(crate::Error::InvalidInput);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::compress_bytes(&*bytes)
|
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 buffer = vec![];
|
||||||
let mut encoder = bzip2::write::BzEncoder::new(buffer, bzip2::Compression::new(6));
|
let mut encoder = bzip2::write::BzEncoder::new(buffer, bzip2::Compression::new(6));
|
||||||
encoder.write_all(bytes)?;
|
encoder.write_all(bytes)?;
|
||||||
Ok(encoder.finish()?)
|
Ok(encoder.finish()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: customizable compression level
|
// TODO: customizable compression level
|
||||||
impl Compressor for BzipCompressor {
|
impl Compressor for BzipCompressor {
|
||||||
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
|
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
|
||||||
match from {
|
match from {
|
||||||
Entry::Files(files) => Ok(
|
Entry::Files(files) => Ok(Self::compress_files(files, CompressionFormat::Bzip)?),
|
||||||
Self::compress_files(files, CompressionFormat::Bzip)?
|
Entry::InMemory(file) => Ok(Self::compress_file_in_memory(file)?),
|
||||||
),
|
|
||||||
Entry::InMemory(file) => Ok(
|
|
||||||
Self::compress_file_in_memory(file)?
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{error::OuchResult, file::File};
|
use crate::file::File;
|
||||||
|
|
||||||
// pub enum CompressionResult {
|
// pub enum CompressionResult {
|
||||||
// ZipArchive(Vec<u8>),
|
// ZipArchive(Vec<u8>),
|
||||||
@ -10,9 +10,9 @@ use crate::{error::OuchResult, file::File};
|
|||||||
|
|
||||||
pub enum Entry {
|
pub enum Entry {
|
||||||
Files(Vec<PathBuf>),
|
Files(Vec<PathBuf>),
|
||||||
InMemory(File)
|
InMemory(File),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Compressor {
|
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 colored::Colorize;
|
||||||
|
|
||||||
use crate::{error::OuchResult, extension::CompressionFormat, file::File};
|
|
||||||
use crate::utils::{
|
|
||||||
ensure_exists,
|
|
||||||
check_for_multiple_files
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{Compressor, Entry};
|
use super::{Compressor, Entry};
|
||||||
|
use crate::{
|
||||||
|
extension::CompressionFormat,
|
||||||
|
file::File,
|
||||||
|
utils::{check_for_multiple_files, ensure_exists},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct GzipCompressor {}
|
pub struct GzipCompressor {}
|
||||||
|
|
||||||
impl 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)?;
|
check_for_multiple_files(&files, &format)?;
|
||||||
|
|
||||||
let path = &files[0];
|
let path = &files[0];
|
||||||
@ -34,7 +36,7 @@ impl GzipCompressor {
|
|||||||
Ok(bytes)
|
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 {
|
let file_contents = match file.contents_in_memory {
|
||||||
Some(bytes) => bytes,
|
Some(bytes) => bytes,
|
||||||
None => {
|
None => {
|
||||||
@ -45,12 +47,9 @@ impl GzipCompressor {
|
|||||||
Self::compress_bytes(file_contents)
|
Self::compress_bytes(file_contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> {
|
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> crate::Result<Vec<u8>> {
|
||||||
let buffer = vec![];
|
let buffer = vec![];
|
||||||
let mut encoder = flate2::write::GzEncoder::new(
|
let mut encoder = flate2::write::GzEncoder::new(buffer, flate2::Compression::default());
|
||||||
buffer,
|
|
||||||
flate2::Compression::default(),
|
|
||||||
);
|
|
||||||
encoder.write_all(&*bytes_to_compress)?;
|
encoder.write_all(&*bytes_to_compress)?;
|
||||||
|
|
||||||
Ok(encoder.finish()?)
|
Ok(encoder.finish()?)
|
||||||
@ -58,15 +57,11 @@ impl GzipCompressor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Compressor for 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;
|
let format = CompressionFormat::Gzip;
|
||||||
match from {
|
match from {
|
||||||
Entry::Files(files) => Ok(
|
Entry::Files(files) => Ok(Self::compress_files(files, format)?),
|
||||||
Self::compress_files(files, format)?
|
Entry::InMemory(file) => Ok(Self::compress_file_in_memory(file)?),
|
||||||
),
|
|
||||||
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 colored::Colorize;
|
||||||
|
|
||||||
use crate::{error::{OuchResult}, extension::CompressionFormat, file::File};
|
|
||||||
use crate::utils::{
|
|
||||||
ensure_exists,
|
|
||||||
check_for_multiple_files
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{Compressor, Entry};
|
use super::{Compressor, Entry};
|
||||||
|
use crate::{
|
||||||
|
extension::CompressionFormat,
|
||||||
|
file::File,
|
||||||
|
utils::{check_for_multiple_files, ensure_exists},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct LzmaCompressor {}
|
pub struct LzmaCompressor {}
|
||||||
|
|
||||||
impl 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)?;
|
check_for_multiple_files(&files, &format)?;
|
||||||
|
|
||||||
let path = &files[0];
|
let path = &files[0];
|
||||||
@ -34,7 +36,7 @@ impl LzmaCompressor {
|
|||||||
Ok(bytes)
|
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 {
|
let file_contents = match file.contents_in_memory {
|
||||||
Some(bytes) => bytes,
|
Some(bytes) => bytes,
|
||||||
None => {
|
None => {
|
||||||
@ -45,7 +47,7 @@ impl LzmaCompressor {
|
|||||||
Self::compress_bytes(file_contents)
|
Self::compress_bytes(file_contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> {
|
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> crate::Result<Vec<u8>> {
|
||||||
let buffer = vec![];
|
let buffer = vec![];
|
||||||
let mut encoder = xz2::write::XzEncoder::new(buffer, 6);
|
let mut encoder = xz2::write::XzEncoder::new(buffer, 6);
|
||||||
encoder.write_all(&*bytes_to_compress)?;
|
encoder.write_all(&*bytes_to_compress)?;
|
||||||
@ -55,7 +57,7 @@ impl LzmaCompressor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Compressor for 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;
|
let format = CompressionFormat::Lzma;
|
||||||
match from {
|
match from {
|
||||||
Entry::Files(files) => Self::compress_files(files, format),
|
Entry::Files(files) => Self::compress_files(files, format),
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
mod tar;
|
|
||||||
mod zip;
|
|
||||||
mod bzip;
|
mod bzip;
|
||||||
|
mod compressor;
|
||||||
mod gzip;
|
mod gzip;
|
||||||
mod lzma;
|
mod lzma;
|
||||||
mod compressor;
|
mod tar;
|
||||||
|
mod zip;
|
||||||
|
|
||||||
pub use compressor::Compressor;
|
pub use compressor::Compressor;
|
||||||
pub use self::compressor::Entry;
|
|
||||||
pub use self::tar::TarCompressor;
|
pub use self::{
|
||||||
pub use self::zip::ZipCompressor;
|
bzip::BzipCompressor, compressor::Entry, gzip::GzipCompressor, lzma::LzmaCompressor,
|
||||||
pub use self::bzip::BzipCompressor;
|
tar::TarCompressor, zip::ZipCompressor,
|
||||||
pub use self::gzip::GzipCompressor;
|
};
|
||||||
pub use self::lzma::LzmaCompressor;
|
|
||||||
|
@ -4,28 +4,23 @@ use colored::Colorize;
|
|||||||
use tar::Builder;
|
use tar::Builder;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use crate::{
|
|
||||||
compressors::Compressor,
|
|
||||||
error::{Error, OuchResult},
|
|
||||||
file::File,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::compressor::Entry;
|
use super::compressor::Entry;
|
||||||
|
use crate::{compressors::Compressor, file::File};
|
||||||
|
|
||||||
pub struct TarCompressor {}
|
pub struct TarCompressor {}
|
||||||
|
|
||||||
impl TarCompressor {
|
impl TarCompressor {
|
||||||
// TODO: implement this
|
// TODO: implement this
|
||||||
fn make_archive_from_memory(_input: File) -> OuchResult<Vec<u8>> {
|
fn make_archive_from_memory(_input: File) -> crate::Result<Vec<u8>> {
|
||||||
println!(
|
println!(
|
||||||
"{}: .tar.tar and .zip.tar is currently unimplemented.",
|
"{}: .tar.tar and .zip.tar is currently unimplemented.",
|
||||||
"error".red()
|
"error".red()
|
||||||
);
|
);
|
||||||
Err(Error::InvalidZipArchive(""))
|
Err(crate::Error::InvalidZipArchive(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
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 change_dir_and_return_parent = |filename: &PathBuf| -> OuchResult<PathBuf> {
|
let change_dir_and_return_parent = |filename: &PathBuf| -> crate::Result<PathBuf> {
|
||||||
let previous_location = env::current_dir()?;
|
let previous_location = env::current_dir()?;
|
||||||
let parent = filename.parent().unwrap();
|
let parent = filename.parent().unwrap();
|
||||||
env::set_current_dir(parent)?;
|
env::set_current_dir(parent)?;
|
||||||
@ -55,7 +50,7 @@ impl TarCompressor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Compressor for TarCompressor {
|
impl Compressor for TarCompressor {
|
||||||
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
|
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
|
||||||
match from {
|
match from {
|
||||||
Entry::Files(filenames) => Self::make_archive_from_files(filenames),
|
Entry::Files(filenames) => Self::make_archive_from_files(filenames),
|
||||||
Entry::InMemory(file) => Self::make_archive_from_memory(file),
|
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 walkdir::WalkDir;
|
||||||
|
|
||||||
use crate::{
|
|
||||||
compressors::Compressor,
|
|
||||||
error::{Error, OuchResult},
|
|
||||||
file::File,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::compressor::Entry;
|
use super::compressor::Entry;
|
||||||
|
use crate::{compressors::Compressor, file::File};
|
||||||
|
|
||||||
pub struct ZipCompressor {}
|
pub struct ZipCompressor {}
|
||||||
|
|
||||||
impl ZipCompressor {
|
impl ZipCompressor {
|
||||||
// TODO: this function does not seem to be working correctly ;/
|
// 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 buffer = vec![];
|
||||||
let mut writer = zip::ZipWriter::new(std::io::Cursor::new(buffer));
|
let mut writer = zip::ZipWriter::new(std::io::Cursor::new(buffer));
|
||||||
|
|
||||||
@ -23,7 +21,7 @@ impl ZipCompressor {
|
|||||||
.file_stem()
|
.file_stem()
|
||||||
.ok_or(
|
.ok_or(
|
||||||
// TODO: Is this reachable?
|
// TODO: Is this reachable?
|
||||||
Error::InvalidInput
|
crate::Error::InvalidInput,
|
||||||
)?
|
)?
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.into();
|
.into();
|
||||||
@ -38,20 +36,18 @@ impl ZipCompressor {
|
|||||||
None => {
|
None => {
|
||||||
// TODO: error description, although this block should not be
|
// TODO: error description, although this block should not be
|
||||||
// reachable
|
// reachable
|
||||||
return Err(Error::InvalidInput);
|
return Err(crate::Error::InvalidInput);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
writer.write_all(&*input_bytes)?;
|
writer.write_all(&*input_bytes)?;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let bytes = writer.finish().unwrap();
|
let bytes = writer.finish().unwrap();
|
||||||
|
|
||||||
Ok(bytes.into_inner())
|
Ok(bytes.into_inner())
|
||||||
}
|
}
|
||||||
|
|
||||||
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 buffer = vec![];
|
||||||
let mut writer = zip::ZipWriter::new(Cursor::new(buffer));
|
let mut writer = zip::ZipWriter::new(Cursor::new(buffer));
|
||||||
|
|
||||||
@ -65,17 +61,12 @@ impl ZipCompressor {
|
|||||||
if entry_path.is_dir() {
|
if entry_path.is_dir() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
writer
|
writer.start_file(entry_path.to_string_lossy(), options)?;
|
||||||
.start_file(
|
|
||||||
entry_path.to_string_lossy(),
|
|
||||||
options
|
|
||||||
)?;
|
|
||||||
let file_bytes = std::fs::read(entry.path())?;
|
let file_bytes = std::fs::read(entry.path())?;
|
||||||
writer.write_all(&*file_bytes)?;
|
writer.write_all(&*file_bytes)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let bytes = writer.finish().unwrap();
|
let bytes = writer.finish().unwrap();
|
||||||
|
|
||||||
Ok(bytes.into_inner())
|
Ok(bytes.into_inner())
|
||||||
@ -83,7 +74,7 @@ impl ZipCompressor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Compressor for ZipCompressor {
|
impl Compressor for ZipCompressor {
|
||||||
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
|
fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
|
||||||
match from {
|
match from {
|
||||||
Entry::Files(filenames) => Ok(Self::make_archive_from_files(filenames)?),
|
Entry::Files(filenames) => Ok(Self::make_archive_from_files(filenames)?),
|
||||||
Entry::InMemory(file) => Ok(Self::make_archive_from_memory(file)?),
|
Entry::InMemory(file) => Ok(Self::make_archive_from_memory(file)?),
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{error::OuchResult, file::File};
|
use crate::file::File;
|
||||||
|
|
||||||
pub enum DecompressionResult {
|
pub enum DecompressionResult {
|
||||||
FilesUnpacked(Vec<PathBuf>),
|
FilesUnpacked(Vec<PathBuf>),
|
||||||
FileInMemory(Vec<u8>)
|
FileInMemory(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Decompressor {
|
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 decompressor;
|
||||||
mod tomemory;
|
|
||||||
mod tar;
|
mod tar;
|
||||||
|
mod tomemory;
|
||||||
mod zip;
|
mod zip;
|
||||||
|
|
||||||
|
pub use decompressor::{DecompressionResult, Decompressor};
|
||||||
pub use decompressor::Decompressor;
|
|
||||||
pub use decompressor::DecompressionResult;
|
|
||||||
|
|
||||||
pub use self::tar::TarDecompressor;
|
|
||||||
pub use self::zip::ZipDecompressor;
|
|
||||||
|
|
||||||
// These decompressors only decompress to memory,
|
// These decompressors only decompress to memory,
|
||||||
// unlike {Tar, Zip}Decompressor which are capable of
|
// unlike {Tar, Zip}Decompressor which are capable of
|
||||||
// decompressing directly to storage
|
// decompressing directly to storage
|
||||||
pub use self::tomemory::GzipDecompressor;
|
pub use self::{
|
||||||
pub use self::tomemory::BzipDecompressor;
|
tar::TarDecompressor,
|
||||||
pub use self::tomemory::LzmaDecompressor;
|
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 colored::Colorize;
|
||||||
use tar::{self, Archive};
|
use tar::{self, Archive};
|
||||||
|
|
||||||
use crate::{error::OuchResult, utils};
|
|
||||||
use crate::file::File;
|
|
||||||
|
|
||||||
use super::decompressor::{DecompressionResult, Decompressor};
|
use super::decompressor::{DecompressionResult, Decompressor};
|
||||||
|
use crate::{file::File, utils};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TarDecompressor {}
|
pub struct TarDecompressor {}
|
||||||
|
|
||||||
impl TarDecompressor {
|
impl TarDecompressor {
|
||||||
|
fn unpack_files(from: File, into: &Path) -> crate::Result<Vec<PathBuf>> {
|
||||||
fn unpack_files(from: File, into: &Path) -> OuchResult<Vec<PathBuf>> {
|
println!(
|
||||||
|
"{}: attempting to decompress {:?}",
|
||||||
println!("{}: attempting to decompress {:?}", "ouch".bright_blue(), &from.path);
|
"ouch".bright_blue(),
|
||||||
|
&from.path
|
||||||
|
);
|
||||||
let mut files_unpacked = vec![];
|
let mut files_unpacked = vec![];
|
||||||
|
|
||||||
let mut archive: Archive<Box<dyn Read>> = match from.contents_in_memory {
|
let mut archive: Archive<Box<dyn Read>> = match from.contents_in_memory {
|
||||||
Some(bytes) => {
|
Some(bytes) => tar::Archive::new(Box::new(Cursor::new(bytes))),
|
||||||
tar::Archive::new(Box::new(Cursor::new(bytes)))
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let file = fs::File::open(&from.path)?;
|
let file = fs::File::open(&from.path)?;
|
||||||
tar::Archive::new(Box::new(file))
|
tar::Archive::new(Box::new(file))
|
||||||
@ -50,7 +52,7 @@ impl TarDecompressor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Decompressor for 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);
|
let destination_path = utils::get_destination_path(into);
|
||||||
|
|
||||||
utils::create_path_if_non_existent(destination_path)?;
|
utils::create_path_if_non_existent(destination_path)?;
|
||||||
|
@ -3,35 +3,32 @@ use std::{
|
|||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
|
||||||
|
use super::decompressor::{DecompressionResult, Decompressor};
|
||||||
|
use crate::utils;
|
||||||
// use niffler;
|
// use niffler;
|
||||||
|
|
||||||
use crate::{extension::CompressionFormat, file::File};
|
use crate::{extension::CompressionFormat, file::File};
|
||||||
use crate::{
|
|
||||||
error::OuchResult,
|
|
||||||
utils,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::decompressor::DecompressionResult;
|
|
||||||
use super::decompressor::Decompressor;
|
|
||||||
|
|
||||||
struct DecompressorToMemory {}
|
struct DecompressorToMemory {}
|
||||||
pub struct GzipDecompressor {}
|
pub struct GzipDecompressor {}
|
||||||
pub struct LzmaDecompressor {}
|
pub struct LzmaDecompressor {}
|
||||||
pub struct BzipDecompressor {}
|
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 {
|
match format {
|
||||||
CompressionFormat::Bzip => Box::new(bzip2::read::BzDecoder::new(buffer)),
|
CompressionFormat::Bzip => Box::new(bzip2::read::BzDecoder::new(buffer)),
|
||||||
CompressionFormat::Gzip => Box::new(flate2::read::MultiGzDecoder::new(buffer)),
|
CompressionFormat::Gzip => Box::new(flate2::read::MultiGzDecoder::new(buffer)),
|
||||||
CompressionFormat::Lzma => Box::new(xz2::read::XzDecoder::new_multi_decoder(buffer)),
|
CompressionFormat::Lzma => Box::new(xz2::read::XzDecoder::new_multi_decoder(buffer)),
|
||||||
_other => unreachable!()
|
_other => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecompressorToMemory {
|
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 file = std::fs::read(from)?;
|
||||||
|
|
||||||
let mut reader = get_decoder(format, Box::new(&file[..]));
|
let mut reader = get_decoder(format, Box::new(&file[..]));
|
||||||
@ -49,7 +46,11 @@ impl DecompressorToMemory {
|
|||||||
Ok(buffer)
|
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);
|
let destination_path = utils::get_destination_path(into);
|
||||||
|
|
||||||
utils::create_path_if_non_existent(destination_path)?;
|
utils::create_path_if_non_existent(destination_path)?;
|
||||||
@ -61,19 +62,19 @@ impl DecompressorToMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Decompressor for GzipDecompressor {
|
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)
|
DecompressorToMemory::decompress(from, CompressionFormat::Gzip, into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decompressor for BzipDecompressor {
|
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)
|
DecompressorToMemory::decompress(from, CompressionFormat::Bzip, into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decompressor for LzmaDecompressor {
|
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)
|
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 colored::Colorize;
|
||||||
use zip::{self, ZipArchive, read::ZipFile};
|
use zip::{self, read::ZipFile, ZipArchive};
|
||||||
|
|
||||||
use crate::{error, file::File};
|
|
||||||
use crate::{error::OuchResult, utils};
|
|
||||||
|
|
||||||
use super::decompressor::{DecompressionResult, Decompressor};
|
use super::decompressor::{DecompressionResult, Decompressor};
|
||||||
|
use crate::{file::File, utils};
|
||||||
|
|
||||||
pub struct ZipDecompressor {}
|
pub struct ZipDecompressor {}
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ impl ZipDecompressor {
|
|||||||
pub fn zip_decompress<T>(
|
pub fn zip_decompress<T>(
|
||||||
archive: &mut ZipArchive<T>,
|
archive: &mut ZipArchive<T>,
|
||||||
into: &Path,
|
into: &Path,
|
||||||
) -> error::OuchResult<Vec<PathBuf>>
|
) -> crate::Result<Vec<PathBuf>>
|
||||||
where
|
where
|
||||||
T: Read + Seek,
|
T: Read + Seek,
|
||||||
{
|
{
|
||||||
@ -72,8 +74,7 @@ impl ZipDecompressor {
|
|||||||
Ok(unpacked_files)
|
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!(
|
println!(
|
||||||
"{}: attempting to decompress {:?}",
|
"{}: attempting to decompress {:?}",
|
||||||
"ouch".bright_blue(),
|
"ouch".bright_blue(),
|
||||||
@ -84,21 +85,18 @@ impl ZipDecompressor {
|
|||||||
Some(bytes) => {
|
Some(bytes) => {
|
||||||
let mut archive = zip::ZipArchive::new(Cursor::new(bytes))?;
|
let mut archive = zip::ZipArchive::new(Cursor::new(bytes))?;
|
||||||
Ok(Self::zip_decompress(&mut archive, into)?)
|
Ok(Self::zip_decompress(&mut archive, into)?)
|
||||||
},
|
}
|
||||||
None => {
|
None => {
|
||||||
let file = fs::File::open(&from.path)?;
|
let file = fs::File::open(&from.path)?;
|
||||||
let mut archive = zip::ZipArchive::new(file)?;
|
let mut archive = zip::ZipArchive::new(file)?;
|
||||||
Ok(Self::zip_decompress(&mut archive, into)?)
|
Ok(Self::zip_decompress(&mut archive, into)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decompressor for ZipDecompressor {
|
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);
|
let destination_path = utils::get_destination_path(into);
|
||||||
|
|
||||||
utils::create_path_if_non_existent(destination_path)?;
|
utils::create_path_if_non_existent(destination_path)?;
|
||||||
|
@ -18,7 +18,7 @@ pub enum Error {
|
|||||||
InputsMustHaveBeenDecompressible(PathBuf),
|
InputsMustHaveBeenDecompressible(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type OuchResult<T> = Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
@ -26,10 +26,10 @@ impl fmt::Display for Error {
|
|||||||
match self {
|
match self {
|
||||||
Error::MissingExtensionError(filename) => {
|
Error::MissingExtensionError(filename) => {
|
||||||
write!(f, "cannot compress to \'{}\', likely because it has an unsupported (or missing) extension.", filename)
|
write!(f, "cannot compress to \'{}\', likely because it has an unsupported (or missing) extension.", filename)
|
||||||
},
|
}
|
||||||
Error::InputsMustHaveBeenDecompressible(file) => {
|
Error::InputsMustHaveBeenDecompressible(file) => {
|
||||||
write!(f, "file '{:?}' is not decompressible", file)
|
write!(f, "file '{:?}' is not decompressible", file)
|
||||||
},
|
}
|
||||||
Error::FileNotFound(file) => {
|
Error::FileNotFound(file) => {
|
||||||
// TODO: check if file == ""
|
// TODO: check if file == ""
|
||||||
write!(f, "file {:?} not found!", 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),
|
Io(io_err) => Self::from(io_err),
|
||||||
InvalidArchive(filename) => Self::InvalidZipArchive(filename),
|
InvalidArchive(filename) => Self::InvalidZipArchive(filename),
|
||||||
FileNotFound => Self::FileNotFound("".into()),
|
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 {
|
impl From<walkdir::Error> for Error {
|
||||||
fn from(err: walkdir::Error) -> Self {
|
fn from(err: walkdir::Error) -> Self {
|
||||||
eprintln!("{}: {}", "error".red(), err);
|
eprintln!("{}: {}", "error".red(), err);
|
||||||
|
|
||||||
Self::InvalidInput
|
Self::InvalidInput
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,31 +2,27 @@ use std::{ffi::OsStr, fs, io::Write, path::PathBuf};
|
|||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
|
||||||
use crate::compressors::{
|
use crate::{
|
||||||
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor, ZipCompressor,
|
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 {}
|
pub struct Evaluator {}
|
||||||
|
|
||||||
impl Evaluator {
|
impl Evaluator {
|
||||||
pub fn get_compressor(
|
pub fn get_compressor(
|
||||||
file: &File,
|
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 {
|
let extension = match &file.extension {
|
||||||
Some(extension) => extension.clone(),
|
Some(extension) => extension.clone(),
|
||||||
None => {
|
None => {
|
||||||
@ -35,7 +31,7 @@ impl Evaluator {
|
|||||||
"{}: reached Evaluator::get_decompressor without known extension.",
|
"{}: reached Evaluator::get_decompressor without known extension.",
|
||||||
"internal error".red()
|
"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 {
|
let first_compressor: Option<Box<dyn Compressor>> = match extension.first_ext {
|
||||||
Some(ext) => match ext {
|
Some(ext) => match ext {
|
||||||
CompressionFormat::Tar => Some(Box::new(TarCompressor {})),
|
CompressionFormat::Tar => Some(Box::new(TarCompressor {})),
|
||||||
|
|
||||||
CompressionFormat::Zip => Some(Box::new(ZipCompressor {})),
|
CompressionFormat::Zip => Some(Box::new(ZipCompressor {})),
|
||||||
|
|
||||||
// _other => Some(Box::new(NifflerCompressor {})),
|
// _other => Some(Box::new(NifflerCompressor {})),
|
||||||
_other => {
|
_other => {
|
||||||
todo!();
|
todo!();
|
||||||
@ -70,7 +64,7 @@ impl Evaluator {
|
|||||||
|
|
||||||
pub fn get_decompressor(
|
pub fn get_decompressor(
|
||||||
file: &File,
|
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 {
|
let extension = match &file.extension {
|
||||||
Some(extension) => extension.clone(),
|
Some(extension) => extension.clone(),
|
||||||
None => {
|
None => {
|
||||||
@ -79,28 +73,22 @@ impl Evaluator {
|
|||||||
"{}: reached Evaluator::get_decompressor without known extension.",
|
"{}: reached Evaluator::get_decompressor without known extension.",
|
||||||
"internal error".red()
|
"internal error".red()
|
||||||
);
|
);
|
||||||
return Err(error::Error::InvalidInput);
|
return Err(crate::Error::InvalidInput);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let second_decompressor: Box<dyn Decompressor> = match extension.second_ext {
|
let second_decompressor: Box<dyn Decompressor> = match extension.second_ext {
|
||||||
CompressionFormat::Tar => Box::new(TarDecompressor {}),
|
CompressionFormat::Tar => Box::new(TarDecompressor {}),
|
||||||
|
|
||||||
CompressionFormat::Zip => Box::new(ZipDecompressor {}),
|
CompressionFormat::Zip => Box::new(ZipDecompressor {}),
|
||||||
|
|
||||||
CompressionFormat::Gzip => Box::new(GzipDecompressor {}),
|
CompressionFormat::Gzip => Box::new(GzipDecompressor {}),
|
||||||
|
|
||||||
CompressionFormat::Lzma => Box::new(LzmaDecompressor {}),
|
CompressionFormat::Lzma => Box::new(LzmaDecompressor {}),
|
||||||
|
|
||||||
CompressionFormat::Bzip => Box::new(BzipDecompressor {}),
|
CompressionFormat::Bzip => Box::new(BzipDecompressor {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_decompressor: Option<Box<dyn Decompressor>> = match extension.first_ext {
|
let first_decompressor: Option<Box<dyn Decompressor>> = match extension.first_ext {
|
||||||
Some(ext) => match ext {
|
Some(ext) => match ext {
|
||||||
CompressionFormat::Tar => Some(Box::new(TarDecompressor {})),
|
CompressionFormat::Tar => Some(Box::new(TarDecompressor {})),
|
||||||
|
|
||||||
CompressionFormat::Zip => Some(Box::new(ZipDecompressor {})),
|
CompressionFormat::Zip => Some(Box::new(ZipDecompressor {})),
|
||||||
|
|
||||||
_other => None,
|
_other => None,
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
@ -116,18 +104,18 @@ impl Evaluator {
|
|||||||
decompressor: Option<Box<dyn Decompressor>>,
|
decompressor: Option<Box<dyn Decompressor>>,
|
||||||
output_file: &Option<File>,
|
output_file: &Option<File>,
|
||||||
extension: Option<Extension>,
|
extension: Option<Extension>,
|
||||||
) -> OuchResult<()> {
|
) -> crate::Result<()> {
|
||||||
let output_file_path = utils::get_destination_path(output_file);
|
let output_file_path = utils::get_destination_path(output_file);
|
||||||
|
|
||||||
let mut filename = file_path
|
let mut filename = file_path
|
||||||
.file_stem()
|
.file_stem()
|
||||||
.unwrap_or_else(|| output_file_path.as_os_str());
|
.unwrap_or_else(|| output_file_path.as_os_str());
|
||||||
|
|
||||||
if filename == "." {
|
if filename == "." {
|
||||||
// I believe this is only possible when the supplied inout has a name
|
// I believe this is only possible when the supplied inout has a name
|
||||||
// of the sort `.tar` or `.zip' and no output has been supplied.
|
// of the sort `.tar` or `.zip' and no output has been supplied.
|
||||||
filename = OsStr::new("ouch-output");
|
filename = OsStr::new("ouch-output");
|
||||||
}
|
}
|
||||||
|
|
||||||
let filename = PathBuf::from(filename);
|
let filename = PathBuf::from(filename);
|
||||||
|
|
||||||
// If there is a decompressor to use, we'll create a file in-memory and decompress it
|
// If there is a decompressor to use, we'll create a file in-memory and decompress it
|
||||||
@ -136,7 +124,6 @@ impl Evaluator {
|
|||||||
None => {
|
None => {
|
||||||
// There is no more processing to be done on the input file (or there is but currently unsupported)
|
// 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.
|
// Therefore, we'll save what we have in memory into a file.
|
||||||
|
|
||||||
println!("{}: saving to {:?}.", "info".yellow(), filename);
|
println!("{}: saving to {:?}.", "info".yellow(), filename);
|
||||||
|
|
||||||
let mut f = fs::File::create(output_file_path.join(filename))?;
|
let mut f = fs::File::create(output_file_path.join(filename))?;
|
||||||
@ -160,7 +147,7 @@ impl Evaluator {
|
|||||||
Ok(())
|
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 (first_compressor, second_compressor) = Self::get_compressor(&output)?;
|
||||||
|
|
||||||
let output_path = output.path.clone();
|
let output_path = output.path.clone();
|
||||||
@ -171,9 +158,7 @@ impl Evaluator {
|
|||||||
let bytes = first_compressor.compress(entry)?;
|
let bytes = first_compressor.compress(entry)?;
|
||||||
|
|
||||||
output.contents_in_memory = Some(bytes);
|
output.contents_in_memory = Some(bytes);
|
||||||
|
|
||||||
entry = Entry::InMemory(output);
|
entry = Entry::InMemory(output);
|
||||||
|
|
||||||
second_compressor.compress(entry)?
|
second_compressor.compress(entry)?
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -193,7 +178,7 @@ impl Evaluator {
|
|||||||
Ok(())
|
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 output_file = &command.output;
|
||||||
let (first_decompressor, second_decompressor) = Self::get_decompressor(&file)?;
|
let (first_decompressor, second_decompressor) = Self::get_decompressor(&file)?;
|
||||||
|
|
||||||
@ -228,7 +213,7 @@ impl Evaluator {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evaluate(command: Command) -> error::OuchResult<()> {
|
pub fn evaluate(command: Command) -> crate::Result<()> {
|
||||||
let output = command.output.clone();
|
let output = command.output.clone();
|
||||||
|
|
||||||
match command.kind {
|
match command.kind {
|
||||||
|
@ -5,7 +5,6 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::error;
|
|
||||||
use CompressionFormat::*;
|
use CompressionFormat::*;
|
||||||
|
|
||||||
/// Represents the extension of a file, but only really caring about
|
/// Represents the extension of a file, but only really caring about
|
||||||
@ -44,14 +43,14 @@ impl From<CompressionFormat> for Extension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
let ext_from_str = |ext| match ext {
|
||||||
"zip" => Ok(Zip),
|
"zip" => Ok(Zip),
|
||||||
"tar" => Ok(Tar),
|
"tar" => Ok(Tar),
|
||||||
"gz" => Ok(Gzip),
|
"gz" => Ok(Gzip),
|
||||||
"bz" | "bz2" => Ok(Bzip),
|
"bz" | "bz2" => Ok(Bzip),
|
||||||
"xz" | "lz" | "lzma" => Ok(Lzma),
|
"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) {
|
let (first_ext, second_ext) = match get_extension_from_filename(filename) {
|
||||||
@ -59,7 +58,7 @@ impl Extension {
|
|||||||
("", snd) => (None, snd),
|
("", snd) => (None, snd),
|
||||||
(fst, snd) => (Some(fst), 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) {
|
let (first_ext, second_ext) = match (first_ext, second_ext) {
|
||||||
@ -96,12 +95,12 @@ pub enum CompressionFormat {
|
|||||||
Zip,
|
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 = Path::new(ext);
|
||||||
|
|
||||||
let ext = match ext.to_str() {
|
let ext = match ext.to_str() {
|
||||||
Some(str) => str,
|
Some(str) => str,
|
||||||
None => return Err(error::Error::InvalidUnicode),
|
None => return Err(crate::Error::InvalidUnicode),
|
||||||
};
|
};
|
||||||
|
|
||||||
match ext {
|
match ext {
|
||||||
@ -110,18 +109,18 @@ fn extension_from_os_str(ext: &OsStr) -> Result<CompressionFormat, error::Error>
|
|||||||
"gz" => Ok(Gzip),
|
"gz" => Ok(Gzip),
|
||||||
"bz" | "bz2" => Ok(Bzip),
|
"bz" | "bz2" => Ok(Bzip),
|
||||||
"xz" | "lzma" | "lz" => Ok(Lzma),
|
"xz" | "lzma" | "lz" => Ok(Lzma),
|
||||||
other => Err(error::Error::UnknownExtensionError(other.into())),
|
other => Err(crate::Error::UnknownExtensionError(other.into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&PathBuf> for CompressionFormat {
|
impl TryFrom<&PathBuf> for CompressionFormat {
|
||||||
type Error = error::Error;
|
type Error = crate::Error;
|
||||||
|
|
||||||
fn try_from(ext: &PathBuf) -> Result<Self, Self::Error> {
|
fn try_from(ext: &PathBuf) -> Result<Self, Self::Error> {
|
||||||
let ext = match ext.extension() {
|
let ext = match ext.extension() {
|
||||||
Some(ext) => ext,
|
Some(ext) => ext,
|
||||||
None => {
|
None => {
|
||||||
return Err(error::Error::MissingExtensionError(String::new()));
|
return Err(crate::Error::MissingExtensionError(String::new()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
extension_from_os_str(ext)
|
extension_from_os_str(ext)
|
||||||
@ -129,13 +128,13 @@ impl TryFrom<&PathBuf> for CompressionFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&str> for CompressionFormat {
|
impl TryFrom<&str> for CompressionFormat {
|
||||||
type Error = error::Error;
|
type Error = crate::Error;
|
||||||
|
|
||||||
fn try_from(filename: &str) -> Result<Self, Self::Error> {
|
fn try_from(filename: &str) -> Result<Self, Self::Error> {
|
||||||
let filename = Path::new(filename);
|
let filename = Path::new(filename);
|
||||||
let ext = match filename.extension() {
|
let ext = match filename.extension() {
|
||||||
Some(ext) => ext,
|
Some(ext) => ext,
|
||||||
None => return Err(error::Error::MissingExtensionError(String::new())),
|
None => return Err(crate::Error::MissingExtensionError(String::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
extension_from_os_str(ext)
|
extension_from_os_str(ext)
|
||||||
|
@ -2,7 +2,6 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use crate::extension::Extension;
|
use crate::extension::Extension;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
/// File's (relative) path
|
/// 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
|
/// 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
|
/// 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 {
|
impl From<(PathBuf, Extension)> for File {
|
||||||
|
26
src/main.rs
26
src/main.rs
@ -1,6 +1,6 @@
|
|||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
mod compressors;
|
||||||
|
mod decompressors;
|
||||||
mod error;
|
mod error;
|
||||||
mod evaluator;
|
mod evaluator;
|
||||||
mod extension;
|
mod extension;
|
||||||
@ -8,25 +8,13 @@ mod file;
|
|||||||
mod test;
|
mod test;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
mod compressors;
|
use std::convert::TryFrom;
|
||||||
mod decompressors;
|
|
||||||
|
|
||||||
|
pub use error::{Error, Result};
|
||||||
use evaluator::Evaluator;
|
use evaluator::Evaluator;
|
||||||
|
|
||||||
fn main() -> error::OuchResult<()> {
|
fn main() -> crate::Result<()> {
|
||||||
let print_error = |err| {
|
|
||||||
println!("{}", err);
|
|
||||||
err
|
|
||||||
};
|
|
||||||
|
|
||||||
let matches = cli::get_matches();
|
let matches = cli::get_matches();
|
||||||
let command = match cli::Command::try_from(matches) {
|
let command = cli::Command::try_from(matches)?;
|
||||||
Ok(command) => command,
|
Evaluator::evaluate(command)
|
||||||
Err(err) => return Err(print_error(err))
|
|
||||||
};
|
|
||||||
|
|
||||||
match Evaluator::evaluate(command) {
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(err) => Err(print_error(err))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
112
src/test.rs
112
src/test.rs
@ -2,27 +2,27 @@
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod cli {
|
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 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
|
// ouch's command-line logic uses fs::canonicalize on its inputs so we cannot
|
||||||
// use made-up files for testing.
|
// use made-up files for testing.
|
||||||
// make_dummy_file therefores creates a small temporary file to bypass fs::canonicalize errors
|
// make_dummy_file therefores creates a small temporary file to bypass fs::canonicalize errors
|
||||||
fn make_dummy_file<'a, P>(path: P) -> OuchResult<()>
|
fn make_dummy_file<'a, P>(path: P) -> crate::Result<()>
|
||||||
where P: AsRef<Path> + 'a {
|
where
|
||||||
|
P: AsRef<Path> + 'a,
|
||||||
|
{
|
||||||
fs::write(path.as_ref(), &[2, 3, 4, 5, 6, 7, 8, 9, 10])?;
|
fs::write(path.as_ref(), &[2, 3, 4, 5, 6, 7, 8, 9, 10])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decompress_files_into_folder() -> OuchResult<()> {
|
fn decompress_files_into_folder() -> crate::Result<()> {
|
||||||
make_dummy_file("file.zip")?;
|
make_dummy_file("file.zip")?;
|
||||||
let matches = clap_app().get_matches_from(vec!["ouch", "-i", "file.zip", "-o", "folder/"]);
|
let matches = clap_app().get_matches_from(vec!["ouch", "-i", "file.zip", "-o", "folder/"]);
|
||||||
let command_from_matches = Command::try_from(matches)?;
|
let command_from_matches = Command::try_from(matches)?;
|
||||||
@ -30,13 +30,11 @@ mod cli {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
command_from_matches,
|
command_from_matches,
|
||||||
Command {
|
Command {
|
||||||
kind: Decompression(vec![
|
kind: Decompression(vec![File {
|
||||||
File {
|
path: fs::canonicalize("file.zip")?,
|
||||||
path: fs::canonicalize("file.zip")?,
|
contents_in_memory: None,
|
||||||
contents_in_memory: None,
|
extension: Some(Extension::from(Zip))
|
||||||
extension: Some(Extension::from(Zip))
|
}]),
|
||||||
}
|
|
||||||
]),
|
|
||||||
output: Some(File {
|
output: Some(File {
|
||||||
path: "folder".into(),
|
path: "folder".into(),
|
||||||
contents_in_memory: None,
|
contents_in_memory: None,
|
||||||
@ -51,10 +49,11 @@ mod cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decompress_files() -> OuchResult<()> {
|
fn decompress_files() -> crate::Result<()> {
|
||||||
make_dummy_file("my-cool-file.zip")?;
|
make_dummy_file("my-cool-file.zip")?;
|
||||||
make_dummy_file("file.tar")?;
|
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)?;
|
let command_from_matches = Command::try_from(matches)?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -83,8 +82,7 @@ mod cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compress_files() -> OuchResult<()> {
|
fn compress_files() -> crate::Result<()> {
|
||||||
|
|
||||||
make_dummy_file("file")?;
|
make_dummy_file("file")?;
|
||||||
make_dummy_file("file2.jpeg")?;
|
make_dummy_file("file2.jpeg")?;
|
||||||
make_dummy_file("file3.ok")?;
|
make_dummy_file("file3.ok")?;
|
||||||
@ -108,13 +106,11 @@ mod cli {
|
|||||||
fs::canonicalize("file2.jpeg")?,
|
fs::canonicalize("file2.jpeg")?,
|
||||||
fs::canonicalize("file3.ok")?
|
fs::canonicalize("file3.ok")?
|
||||||
]),
|
]),
|
||||||
output: Some(
|
output: Some(File {
|
||||||
File {
|
path: "file.tar".into(),
|
||||||
path: "file.tar".into(),
|
contents_in_memory: None,
|
||||||
contents_in_memory: None,
|
extension: Some(Extension::from(Tar))
|
||||||
extension: Some(Extension::from(Tar))
|
}),
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -131,20 +127,22 @@ mod cli_errors {
|
|||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use crate::cli::clap_app;
|
use crate::{
|
||||||
use crate::cli::Command;
|
cli::{clap_app, Command},
|
||||||
use crate::error::Error;
|
error::crate::{Error, Result},
|
||||||
use crate::error::OuchResult;
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compress_files() -> OuchResult<()> {
|
fn compress_files() -> crate::Result<()> {
|
||||||
let matches =
|
let matches =
|
||||||
clap_app().get_matches_from(vec!["ouch", "-i", "a_file", "file2.jpeg", "file3.ok"]);
|
clap_app().get_matches_from(vec!["ouch", "-i", "a_file", "file2.jpeg", "file3.ok"]);
|
||||||
let res = Command::try_from(matches);
|
let res = Command::try_from(matches);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
Err(Error::InputsMustHaveBeenDecompressible("a_file".into()))
|
Err(crate::Error::InputsMustHaveBeenDecompressible(
|
||||||
|
"a_file".into()
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -153,23 +151,23 @@ mod cli_errors {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod extension_extraction {
|
mod extension_extraction {
|
||||||
use crate::{error::OuchResult, extension::Extension} ;
|
|
||||||
use crate::extension::CompressionFormat;
|
|
||||||
use std::{convert::TryFrom, path::PathBuf, str::FromStr};
|
use std::{convert::TryFrom, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
error::crate::Result,
|
||||||
|
extension::{CompressionFormat, Extension},
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zip() -> OuchResult<()> {
|
fn zip() -> crate::Result<()> {
|
||||||
let path = PathBuf::from_str("filename.tar.zip").unwrap();
|
let path = PathBuf::from_str("filename.tar.zip").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Zip);
|
||||||
CompressionFormat::try_from(&path)?,
|
|
||||||
CompressionFormat::Zip
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tar_gz() -> OuchResult<()> {
|
fn tar_gz() -> crate::Result<()> {
|
||||||
let extension = Extension::new("folder.tar.gz")?;
|
let extension = Extension::new("folder.tar.gz")?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -184,45 +182,33 @@ mod extension_extraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tar() -> OuchResult<()> {
|
fn tar() -> crate::Result<()> {
|
||||||
let path = PathBuf::from_str("pictures.tar").unwrap();
|
let path = PathBuf::from_str("pictures.tar").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Tar);
|
||||||
CompressionFormat::try_from(&path)?,
|
|
||||||
CompressionFormat::Tar
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gz() -> OuchResult<()> {
|
fn gz() -> crate::Result<()> {
|
||||||
let path = PathBuf::from_str("passwords.tar.gz").unwrap();
|
let path = PathBuf::from_str("passwords.tar.gz").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Gzip);
|
||||||
CompressionFormat::try_from(&path)?,
|
|
||||||
CompressionFormat::Gzip
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lzma() -> OuchResult<()> {
|
fn lzma() -> crate::Result<()> {
|
||||||
let path = PathBuf::from_str("mygame.tar.lzma").unwrap();
|
let path = PathBuf::from_str("mygame.tar.lzma").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Lzma);
|
||||||
CompressionFormat::try_from(&path)?,
|
|
||||||
CompressionFormat::Lzma
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bz() -> OuchResult<()> {
|
fn bz() -> crate::Result<()> {
|
||||||
let path = PathBuf::from_str("songs.tar.bz").unwrap();
|
let path = PathBuf::from_str("songs.tar.bz").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(CompressionFormat::try_from(&path)?, CompressionFormat::Bzip);
|
||||||
CompressionFormat::try_from(&path)?,
|
|
||||||
CompressionFormat::Bzip
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
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 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
|
where
|
||||||
P: AsRef<Path> + 'a {
|
P: AsRef<Path> + 'a,
|
||||||
let exists = path.as_ref().exists();
|
{
|
||||||
if !exists {
|
let exists = path.as_ref().exists();
|
||||||
eprintln!("{}: could not find file {:?}", "[ERROR]".red(), path.as_ref());
|
if !exists {
|
||||||
return Err(Error::FileNotFound(PathBuf::from(path.as_ref())));
|
eprintln!(
|
||||||
}
|
"{}: could not find file {:?}",
|
||||||
Ok(())
|
"[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 {
|
if files.len() != 1 {
|
||||||
eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "[ERROR]".red(), format, format);
|
eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "[ERROR]".red(), format, format);
|
||||||
return Err(Error::InvalidInput);
|
return Err(crate::Error::InvalidInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
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() {
|
if !path.exists() {
|
||||||
println!(
|
println!(
|
||||||
"{}: attempting to create folder {:?}.",
|
"{}: attempting to create folder {:?}.",
|
||||||
@ -40,7 +52,7 @@ pub (crate) fn create_path_if_non_existent(path: &Path) -> OuchResult<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub (crate) fn get_destination_path(dest: &Option<File>) -> &Path {
|
pub(crate) fn get_destination_path(dest: &Option<File>) -> &Path {
|
||||||
match dest {
|
match dest {
|
||||||
Some(output) => {
|
Some(output) => {
|
||||||
// Must be None according to the way command-line arg. parsing in Ouch works
|
// Must be None according to the way command-line arg. parsing in Ouch works
|
||||||
|
Loading…
x
Reference in New Issue
Block a user