mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-07 12:05:46 +00:00
evaluator: Verify if input files are decompressible
This commit is contained in:
parent
9b8dcb40fa
commit
f9272b5ce5
10
src/cli.rs
10
src/cli.rs
@ -1,4 +1,9 @@
|
|||||||
use std::{env, ffi::OsString, path::{Path, PathBuf}, vec::Vec};
|
use std::{
|
||||||
|
env,
|
||||||
|
ffi::OsString,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
use oof::{arg_flag, flag};
|
use oof::{arg_flag, flag};
|
||||||
|
|
||||||
@ -41,7 +46,7 @@ pub struct ParsedArgs {
|
|||||||
|
|
||||||
fn canonicalize<'a, P>(path: P) -> crate::Result<PathBuf>
|
fn canonicalize<'a, P>(path: P) -> crate::Result<PathBuf>
|
||||||
where
|
where
|
||||||
P: AsRef<Path> + 'a
|
P: AsRef<Path> + 'a,
|
||||||
{
|
{
|
||||||
match std::fs::canonicalize(&path.as_ref()) {
|
match std::fs::canonicalize(&path.as_ref()) {
|
||||||
Ok(abs_path) => Ok(abs_path),
|
Ok(abs_path) => Ok(abs_path),
|
||||||
@ -118,6 +123,7 @@ pub fn parse_args_from(mut args: Vec<OsString>) -> crate::Result<ParsedArgs> {
|
|||||||
let files = files.map(Result::unwrap).collect();
|
let files = files.map(Result::unwrap).collect();
|
||||||
|
|
||||||
let output_folder = flags.take_arg("output").map(PathBuf::from);
|
let output_folder = flags.take_arg("output").map(PathBuf::from);
|
||||||
|
|
||||||
// TODO: ensure all files are decompressible
|
// TODO: ensure all files are decompressible
|
||||||
|
|
||||||
let command = Command::Decompress {
|
let command = Command::Decompress {
|
||||||
|
@ -4,8 +4,8 @@ use colored::Colorize;
|
|||||||
|
|
||||||
use super::{Compressor, Entry};
|
use super::{Compressor, Entry};
|
||||||
use crate::{
|
use crate::{
|
||||||
extension::CompressionFormat,
|
|
||||||
bytes::Bytes,
|
bytes::Bytes,
|
||||||
|
extension::CompressionFormat,
|
||||||
file::File,
|
file::File,
|
||||||
utils::{check_for_multiple_files, ensure_exists},
|
utils::{check_for_multiple_files, ensure_exists},
|
||||||
};
|
};
|
||||||
|
@ -4,9 +4,9 @@ use colored::Colorize;
|
|||||||
|
|
||||||
use super::{Compressor, Entry};
|
use super::{Compressor, Entry};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
bytes::Bytes,
|
||||||
extension::CompressionFormat,
|
extension::CompressionFormat,
|
||||||
file::File,
|
file::File,
|
||||||
bytes::Bytes,
|
|
||||||
utils::{check_for_multiple_files, ensure_exists},
|
utils::{check_for_multiple_files, ensure_exists},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@ use colored::Colorize;
|
|||||||
|
|
||||||
use super::{Compressor, Entry};
|
use super::{Compressor, Entry};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
bytes::Bytes,
|
||||||
extension::CompressionFormat,
|
extension::CompressionFormat,
|
||||||
file::File,
|
file::File,
|
||||||
bytes::Bytes,
|
|
||||||
utils::{check_for_multiple_files, ensure_exists},
|
utils::{check_for_multiple_files, ensure_exists},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use colored::Colorize;
|
|||||||
use tar::{self, Archive};
|
use tar::{self, Archive};
|
||||||
|
|
||||||
use super::decompressor::{DecompressionResult, Decompressor};
|
use super::decompressor::{DecompressionResult, Decompressor};
|
||||||
use crate::{dialogs::Confirmation, file::File, bytes::Bytes, utils};
|
use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TarDecompressor {}
|
pub struct TarDecompressor {}
|
||||||
|
@ -6,8 +6,8 @@ use std::{
|
|||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
|
||||||
use super::decompressor::{DecompressionResult, Decompressor};
|
use super::decompressor::{DecompressionResult, Decompressor};
|
||||||
use crate::utils;
|
|
||||||
use crate::bytes::Bytes;
|
use crate::bytes::Bytes;
|
||||||
|
use crate::utils;
|
||||||
use crate::{extension::CompressionFormat, file::File};
|
use crate::{extension::CompressionFormat, file::File};
|
||||||
|
|
||||||
struct DecompressorToMemory {}
|
struct DecompressorToMemory {}
|
||||||
|
@ -8,7 +8,7 @@ use colored::Colorize;
|
|||||||
use zip::{self, read::ZipFile, ZipArchive};
|
use zip::{self, read::ZipFile, ZipArchive};
|
||||||
|
|
||||||
use super::decompressor::{DecompressionResult, Decompressor};
|
use super::decompressor::{DecompressionResult, Decompressor};
|
||||||
use crate::{dialogs::Confirmation, file::File, bytes::Bytes, utils};
|
use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils};
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn __unix_set_permissions(file_path: &Path, file: &ZipFile) {
|
fn __unix_set_permissions(file_path: &Path, file: &ZipFile) {
|
||||||
|
@ -5,7 +5,7 @@ use colored::Colorize;
|
|||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
UnknownExtensionError(String),
|
UnknownExtensionError(String),
|
||||||
MissingExtensionError(String),
|
MissingExtensionError(PathBuf),
|
||||||
// TODO: get rid of this error variant
|
// TODO: get rid of this error variant
|
||||||
InvalidUnicode,
|
InvalidUnicode,
|
||||||
InvalidInput,
|
InvalidInput,
|
||||||
@ -35,7 +35,7 @@ impl fmt::Display for Error {
|
|||||||
Error::MissingExtensionError(filename) => {
|
Error::MissingExtensionError(filename) => {
|
||||||
write!(f, "{} ", "[ERROR]".red())?;
|
write!(f, "{} ", "[ERROR]".red())?;
|
||||||
// TODO: show MIME type of the unsupported file
|
// TODO: show MIME type of the unsupported file
|
||||||
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::WalkdirError => {
|
Error::WalkdirError => {
|
||||||
// Already printed in the From block
|
// Already printed in the From block
|
||||||
|
@ -8,9 +8,9 @@ use colored::Colorize;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bytes::Bytes,
|
bytes::Bytes,
|
||||||
cli::{VERSION, Command},
|
cli::{Command, VERSION},
|
||||||
compressors::{
|
compressors::{
|
||||||
Entry, Compressor, BzipCompressor, GzipCompressor, LzmaCompressor, TarCompressor,
|
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor,
|
||||||
ZipCompressor,
|
ZipCompressor,
|
||||||
},
|
},
|
||||||
decompressors::{
|
decompressors::{
|
||||||
@ -21,7 +21,6 @@ use crate::{
|
|||||||
extension::{CompressionFormat, Extension},
|
extension::{CompressionFormat, Extension},
|
||||||
file::File,
|
file::File,
|
||||||
utils,
|
utils,
|
||||||
debug
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Evaluator {}
|
pub struct Evaluator {}
|
||||||
@ -33,7 +32,6 @@ impl Evaluator {
|
|||||||
pub fn get_compressor(
|
pub fn get_compressor(
|
||||||
file: &File,
|
file: &File,
|
||||||
) -> crate::Result<(Option<BoxedCompressor>, BoxedCompressor)> {
|
) -> crate::Result<(Option<BoxedCompressor>, BoxedCompressor)> {
|
||||||
|
|
||||||
let extension = match &file.extension {
|
let extension = match &file.extension {
|
||||||
Some(extension) => extension.clone(),
|
Some(extension) => extension.clone(),
|
||||||
None => {
|
None => {
|
||||||
@ -214,7 +212,15 @@ impl Evaluator {
|
|||||||
output: Option<&Path>,
|
output: Option<&Path>,
|
||||||
flags: &oof::Flags,
|
flags: &oof::Flags,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let file = debug!(File::from(file_path)?);
|
// The file to be decompressed
|
||||||
|
let file = File::from(file_path)?;
|
||||||
|
// The file must have a supported decompressible format
|
||||||
|
if file.extension == None {
|
||||||
|
return Err(crate::Error::MissingExtensionError(PathBuf::from(
|
||||||
|
file_path,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
let output = match output {
|
let output = match output {
|
||||||
Some(inner) => Some(File::from(inner)?),
|
Some(inner) => Some(File::from(inner)?),
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -57,7 +57,11 @@ impl Extension {
|
|||||||
(os_str, snd) if os_str.is_empty() => (None, snd),
|
(os_str, snd) if os_str.is_empty() => (None, snd),
|
||||||
(fst, snd) => (Some(fst), snd),
|
(fst, snd) => (Some(fst), snd),
|
||||||
},
|
},
|
||||||
None => return Err(crate::Error::MissingExtensionError(to_utf(file_name))),
|
None => {
|
||||||
|
return Err(crate::Error::MissingExtensionError(PathBuf::from(
|
||||||
|
file_name,
|
||||||
|
)))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (first_ext, second_ext) = match (first_ext, second_ext) {
|
let (first_ext, second_ext) = match (first_ext, second_ext) {
|
||||||
@ -119,7 +123,7 @@ impl TryFrom<&PathBuf> for CompressionFormat {
|
|||||||
let ext = match ext.extension() {
|
let ext = match ext.extension() {
|
||||||
Some(ext) => ext,
|
Some(ext) => ext,
|
||||||
None => {
|
None => {
|
||||||
return Err(crate::Error::MissingExtensionError(String::new()));
|
return Err(crate::Error::MissingExtensionError(PathBuf::new()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
extension_from_os_str(ext)
|
extension_from_os_str(ext)
|
||||||
@ -133,7 +137,7 @@ impl TryFrom<&str> for CompressionFormat {
|
|||||||
let file_name = Path::new(file_name);
|
let file_name = Path::new(file_name);
|
||||||
let ext = match file_name.extension() {
|
let ext = match file_name.extension() {
|
||||||
Some(ext) => ext,
|
Some(ext) => ext,
|
||||||
None => return Err(crate::Error::MissingExtensionError(String::new())),
|
None => return Err(crate::Error::MissingExtensionError(PathBuf::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
extension_from_os_str(ext)
|
extension_from_os_str(ext)
|
||||||
|
@ -24,7 +24,7 @@ impl<'a> File<'a> {
|
|||||||
Ok(File {
|
Ok(File {
|
||||||
path,
|
path,
|
||||||
contents_in_memory: None,
|
contents_in_memory: None,
|
||||||
extension
|
extension,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
src/test.rs
64
src/test.rs
@ -27,7 +27,7 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod argparsing {
|
mod argparsing {
|
||||||
use super::{make_dummy_files};
|
use super::make_dummy_files;
|
||||||
use crate::cli;
|
use crate::cli;
|
||||||
use crate::cli::Command;
|
use crate::cli::Command;
|
||||||
use std::{ffi::OsString, fs, path::PathBuf};
|
use std::{ffi::OsString, fs, path::PathBuf};
|
||||||
@ -65,10 +65,13 @@ mod argparsing {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_arg_parsing_compress_subcommand() -> crate::Result<()> {
|
fn test_arg_parsing_compress_subcommand() -> crate::Result<()> {
|
||||||
|
|
||||||
let files = vec!["a", "b", "c"];
|
let files = vec!["a", "b", "c"];
|
||||||
make_dummy_files(&*files)?;
|
make_dummy_files(&*files)?;
|
||||||
let files= files.iter().map(fs::canonicalize).map(Result::unwrap).collect();
|
let files = files
|
||||||
|
.iter()
|
||||||
|
.map(fs::canonicalize)
|
||||||
|
.map(Result::unwrap)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let expected = Command::Compress {
|
let expected = Command::Compress {
|
||||||
files,
|
files,
|
||||||
@ -108,69 +111,36 @@ mod byte_pretty_printing {
|
|||||||
use crate::bytes::Bytes;
|
use crate::bytes::Bytes;
|
||||||
#[test]
|
#[test]
|
||||||
fn bytes() {
|
fn bytes() {
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(234)), "234.00 B");
|
||||||
&format!("{}", Bytes::new(234)),
|
|
||||||
"234.00 B"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(999)), "999.00 B");
|
||||||
&format!("{}", Bytes::new(999)),
|
|
||||||
"999.00 B"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn kilobytes() {
|
fn kilobytes() {
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(2234)), "2.23 kB");
|
||||||
&format!("{}", Bytes::new(2234)),
|
|
||||||
"2.23 kB"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(62500)), "62.50 kB");
|
||||||
&format!("{}", Bytes::new(62500)),
|
|
||||||
"62.50 kB"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(329990)), "329.99 kB");
|
||||||
&format!("{}", Bytes::new(329990)),
|
|
||||||
"329.99 kB"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn megabytes() {
|
fn megabytes() {
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(2750000)), "2.75 MB");
|
||||||
&format!("{}", Bytes::new(2750000)),
|
|
||||||
"2.75 MB"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(55000000)), "55.00 MB");
|
||||||
&format!("{}", Bytes::new(55000000)),
|
|
||||||
"55.00 MB"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(987654321)), "987.65 MB");
|
||||||
&format!("{}", Bytes::new(987654321)),
|
|
||||||
"987.65 MB"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gigabytes() {
|
fn gigabytes() {
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(5280000000)), "5.28 GB");
|
||||||
&format!("{}", Bytes::new(5280000000)),
|
|
||||||
"5.28 GB"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(95200000000)), "95.20 GB");
|
||||||
&format!("{}", Bytes::new(95200000000)),
|
|
||||||
"95.20 GB"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(&format!("{}", Bytes::new(302000000000)), "302.00 GB");
|
||||||
&format!("{}", Bytes::new(302000000000)),
|
|
||||||
"302.00 GB"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
src/utils.rs
13
src/utils.rs
@ -12,16 +12,19 @@ use crate::{dialogs::Confirmation, extension::CompressionFormat, file::File};
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
macro_rules! debug {
|
macro_rules! debug {
|
||||||
($x:expr) => { dbg!($x) }
|
($x:expr) => {
|
||||||
|
dbg!($x)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
macro_rules! debug {
|
macro_rules! debug {
|
||||||
($x:expr) => { std::convert::identity($x) }
|
($x:expr) => {
|
||||||
|
std::convert::identity($x)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn ensure_exists<'a, P>(path: P) -> crate::Result<()>
|
pub(crate) fn ensure_exists<'a, P>(path: P) -> crate::Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path> + 'a,
|
P: AsRef<Path> + 'a,
|
||||||
@ -82,7 +85,9 @@ pub(crate) fn change_dir_and_return_parent(filename: &Path) -> crate::Result<Pat
|
|||||||
return Err(crate::Error::CompressingRootFolder);
|
return Err(crate::Error::CompressingRootFolder);
|
||||||
};
|
};
|
||||||
|
|
||||||
env::set_current_dir(parent).ok().ok_or(crate::Error::CompressingRootFolder)?;
|
env::set_current_dir(parent)
|
||||||
|
.ok()
|
||||||
|
.ok_or(crate::Error::CompressingRootFolder)?;
|
||||||
|
|
||||||
Ok(previous_location)
|
Ok(previous_location)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user