Merge pull request #16 from vrmiguel/nightly

Update master from nightly
This commit is contained in:
Vinícius Miguel 2021-04-06 00:39:23 -03:00 committed by GitHub
commit d3de94dfca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 186 additions and 277 deletions

View File

@ -17,37 +17,33 @@ jobs:
- name: Install toolchain - name: Install toolchain
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: ${{ matrix.rust }} toolchain: stable
target: x86_64-unknown-linux-musl
override: true override: true
- name: Install dependencies for musl libc
run: |
sudo apt-get update
sudo apt-get install musl-tools
- name: Run cargo build - name: Run cargo build
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: build command: build
args: --release args: --release --target x86_64-unknown-linux-musl
- name: Run cargo test - name: Run cargo test
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: test command: test
- name: Install dependencies for Python test script
run: |
sudo apt-get update
sudo apt-get install libmagic1
python3 -m pip install python-magic
- name: Run test script
run: python3 makeshift_testing.py
- name: Strip binary - name: Strip binary
run: strip target/release/ouch run: strip target/x86_64-unknown-linux-musl/release/ouch
- name: Upload binary - name: Upload binary
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: 'ouch-ubuntu-18.04-glibc' name: 'ouch-linux-musl'
path: target/release/ouch path: target/x86_64-unknown-linux-musl/release/ouch
macos: macos:
name: macOS name: macOS
@ -77,11 +73,6 @@ jobs:
with: with:
command: test command: test
- name: Install dependencies for Python test script
run: |
brew install libmagic
python3 -m pip install python-magic
- name: Strip binary - name: Strip binary
run: strip target/release/ouch run: strip target/release/ouch
@ -91,9 +82,6 @@ jobs:
name: 'ouch-macOS' name: 'ouch-macOS'
path: target/release/ouch path: target/release/ouch
- name: Run test script
run: python3 makeshift_testing.py
windows: windows:
name: Windows Server name: Windows Server
runs-on: windows-2019 runs-on: windows-2019

View File

@ -12,10 +12,6 @@
- [Installation](#Installation) - [Installation](#Installation)
- [Supported operating systems](#Supported-operating-systems) - [Supported operating systems](#Supported-operating-systems)
**Note**
* This README represents the new, but not yet implemented, interface that `ouch` will use.
* For current usage instructions, check [the old README](https://github.com/vrmiguel/ouch/blob/0f453e9dfc70066056b9cc40e8032dcc6ee703bc/README.md).
## Usage ## Usage
### Decompressing files ### Decompressing files

View File

@ -1,89 +0,0 @@
#!/usr/bin/python3
"""
Little integration testing script while proper integration tests in Rust aren't implemented.
"""
import magic, os, hashlib
def make_random_file():
with open('test-file', 'wb') as fout:
fout.write(os.urandom(2048))
def sanity_check_format(format: str):
make_random_file()
md5sum = hashlib.md5(open('test-file', 'rb').read()).hexdigest()
os.system(f"cargo run -- -i test-file -o test-file.{format}")
os.remove('test-file')
os.system(f"cargo run -- -i test-file.{format}")
if md5sum != hashlib.md5(open('test-file', 'rb').read()).hexdigest():
print("Something went wrong with tar (de)compression.")
os._exit(2)
os.remove('test-file')
os.remove(f'test-file.{format}')
if __name__ == "__main__":
# We'll use MIME sniffing through magic numbers to
# verify if ouch is actually outputting the file formats
# that it should
m = magic.open(magic.MAGIC_MIME)
try:
os.mkdir("testbuilds")
except OSError:
print ("Could not make testbuilds folder. Exiting.")
os._exit(2)
os.chdir("testbuilds")
m.load()
files = [
"src.tar",
"src.zip",
"src.tar.gz",
"src.tar.bz",
"src.tar.bz2",
"src.tar.lz",
"src.tar.lzma",
]
expected_mime_types = [
"application/x-tar",
"application/zip",
"application/gzip",
"application/x-bzip2",
"application/x-bzip2",
"application/x-xz",
"application/x-xz"
]
for file in files:
rv = os.system(f"cargo run -- -i ../src/ -o {file}")
if rv != 0:
print(f"Failed while compressing {file}")
for (file, expected_mime) in zip(files, expected_mime_types):
if m.file(file) != expected_mime:
print(f"Test failed at file {file}")
os._exit(2)
for (idx, file) in enumerate(files):
rv = os.system(f"cargo run -- -i {file} -o out{idx}/")
if rv != 0:
print(f"Failed while decompressing {file}")
os._exit(2)
os.chdir("..")
os.system("rm -rf testbuilds")
# We'll now verify if ouch is not altering the data it is compressing
# and decompressing
sanity_check_format("tar")
sanity_check_format("tar.gz")
sanity_check_format("tar.bz")
sanity_check_format("tar.bz2")
sanity_check_format("tar.lz")
sanity_check_format("tar.lzma")

View File

@ -91,7 +91,7 @@ impl FlagType {
#[cfg(target_family = "windows")] #[cfg(target_family = "windows")]
{ {
use std::os::windows::ffi::OsStrExt; use std::os::windows::ffi::OsStrExt;
iter = text.encode_wide iter = text.encode_wide();
} }
// 45 is the code for a hyphen // 45 is the code for a hyphen

View File

@ -126,7 +126,7 @@ pub fn filter_flags(
// For each letter in the short arg, except the last one // For each letter in the short arg, except the last one
for (i, letter) in letters.iter().copied().enumerate() { for (i, letter) in letters.iter().copied().enumerate() {
// Safety: this loop only runs when len >= 1 // Safety: this loop only runs when len >= 1, so this subtraction is safe
let is_last_letter = i == letters.len() - 1; let is_last_letter = i == letters.len() - 1;
let flag_info = short_flags_info.get(&letter).unwrap_or_else(|| { let flag_info = short_flags_info.get(&letter).unwrap_or_else(|| {
@ -149,16 +149,15 @@ pub fn filter_flags(
} }
// pop the next one // pop the next one
let flag_argument = iter.next(); let flag_argument = iter.next().unwrap_or_else(|| {
flag_argument.unwrap_or_else(|| {
panic!( panic!(
"USer errror: argument flag `argument_flag` came at last, but it \ "USer errror: argument flag `argument_flag` came at last, but it \
requires an argument" requires an argument"
) )
}); });
// Otherwise, insert it (TODO: grab next one and add it) // Otherwise, insert it.
// result_flags.argument_flags.insert(flag_info.long); result_flags.argument_flags.insert(flag_name, flag_argument);
} else { } else {
// If it was already inserted // If it was already inserted
if result_flags.boolean_flags.contains(flag_name) { if result_flags.boolean_flags.contains(flag_name) {

View File

@ -5,6 +5,7 @@ pub fn trim_double_hyphen(flag_text: &str) -> &str {
chars.as_str() chars.as_str()
} }
// Currently unused
/// Util function to skip the single leading short flag hyphen. /// Util function to skip the single leading short flag hyphen.
pub fn trim_single_hyphen(flag_text: &str) -> &str { pub fn trim_single_hyphen(flag_text: &str) -> &str {
let mut chars = flag_text.chars(); let mut chars = flag_text.chars();

View File

@ -2,6 +2,10 @@ use std::{env, ffi::OsString, io, path::PathBuf, vec::Vec};
use oof::{arg_flag, flag}; use oof::{arg_flag, flag};
use crate::debug;
pub const VERSION: &str = "0.1.5";
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
pub enum Command { pub enum Command {
/// Files to be compressed /// Files to be compressed
@ -66,8 +70,9 @@ pub fn parse_args_from(mut args: Vec<OsString>) -> crate::Result<ParsedArgs> {
let mut files: Vec<PathBuf> = args.into_iter().map(PathBuf::from).collect(); let mut files: Vec<PathBuf> = args.into_iter().map(PathBuf::from).collect();
if files.len() < 2 { if files.len() < 2 {
panic!("The compress subcommands demands at least 2 arguments, see usage:......."); return Err(crate::Error::MissingArgumentsForCompression);
} }
// Safety: we checked that args.len() >= 2 // Safety: we checked that args.len() >= 2
let compressed_output_path = files.pop().unwrap(); let compressed_output_path = files.pop().unwrap();
@ -82,16 +87,18 @@ pub fn parse_args_from(mut args: Vec<OsString>) -> crate::Result<ParsedArgs> {
// Defaults to decompression when there is no subcommand // Defaults to decompression when there is no subcommand
None => { None => {
flags_info.push(arg_flag!('o', "output")); flags_info.push(arg_flag!('o', "output"));
debug!(&flags_info);
// Parse flags // Parse flags
let (args, mut flags) = oof::filter_flags(args, &flags_info)?; let (args, mut flags) = oof::filter_flags(args, &flags_info)?;
debug!((&args, &flags));
let files: Vec<_> = args.into_iter().map(PathBuf::from).collect(); let files: Vec<_> = args.into_iter().map(PathBuf::from).collect();
// TODO: This line doesn't seem to be working correctly
let output_folder = flags.take_arg("output").map(PathBuf::from); let output_folder = flags.take_arg("output").map(PathBuf::from);
// Is the output here fully correct? // Is the output here fully correct?
// With the paths not canonicalized? // With the paths not canonicalized?
let command = Command::Decompress { let command = Command::Decompress {
files, files,
output_folder, output_folder,
@ -103,97 +110,3 @@ pub fn parse_args_from(mut args: Vec<OsString>) -> crate::Result<ParsedArgs> {
Ok(parsed_args) Ok(parsed_args)
} }
#[cfg(test)]
mod tests {
use super::*;
fn gen_args(text: &str) -> Vec<OsString> {
let args = text.split_whitespace();
args.map(OsString::from).collect()
}
// // util for test the argument parsing
// macro_rules! test {
// ($expected_command:expr, $input_text:expr) => {{
// assert_eq!(
// $expected_command,
// oof::try_arg_parsing($input_text.split_whitespace())
// )
// }};
// }
macro_rules! parse {
($input_text:expr) => {{
let args = gen_args($input_text);
parse_args_from(args).unwrap()
}};
}
#[test]
// The absolute flags that ignore all the other argparsing rules are --help and --version
fn test_absolute_flags() {
let expected = Command::ShowHelp;
assert_eq!(expected, parse!("").command);
assert_eq!(expected, parse!("-h").command);
assert_eq!(expected, parse!("--help").command);
assert_eq!(expected, parse!("aaaaaaaa --help -o -e aaa").command);
assert_eq!(expected, parse!("aaaaaaaa -h").command);
assert_eq!(expected, parse!("--help compress aaaaaaaa").command);
assert_eq!(expected, parse!("compress --help").command);
assert_eq!(expected, parse!("--version --help").command);
assert_eq!(expected, parse!("aaaaaaaa -v aaaa -h").command);
let expected = Command::ShowVersion;
assert_eq!(expected, parse!("ouch --version").command);
assert_eq!(expected, parse!("ouch a --version b").command);
}
#[test]
fn test_arg_parsing_compress_subcommand() {
let files = ["a", "b", "c"].iter().map(PathBuf::from).collect();
let expected = Command::Compress {
files,
compressed_output_path: "d".into(),
};
assert_eq!(expected, parse!("compress a b c d").command);
}
#[test]
fn test_arg_parsing_decompress_subcommand() {
let files: Vec<_> = ["a", "b", "c"].iter().map(PathBuf::from).collect();
let expected = Command::Decompress {
files: files.clone(),
output_folder: None,
};
assert_eq!(expected, parse!("a b c").command);
let expected = Command::Decompress {
files,
output_folder: Some("folder".into()),
};
assert_eq!(expected, parse!("a b c --output folder").command);
assert_eq!(expected, parse!("a b --output folder c").command);
assert_eq!(expected, parse!("a --output folder b c").command);
assert_eq!(expected, parse!("--output folder a b c").command);
}
// #[test]
// fn test_arg_parsing_decompress_subcommand() {
// let files: Vec<PathBuf> = ["a", "b", "c"].iter().map(PathBuf::from).collect();
// let expected = Ok(Command::Decompress {
// files: files.clone(),
// });
// test!(expected, "ouch a b c");
// let files: Vec<PathBuf> = ["a", "b", "c", "d"].iter().map(PathBuf::from).collect();
// let expected = Ok(Command::Decompress {
// files: files.clone(),
// });
// test!(expected, "ouch a b c d");
// }
}

View File

@ -29,6 +29,7 @@ impl TarCompressor {
for entry in WalkDir::new(&filename) { for entry in WalkDir::new(&filename) {
let entry = entry?; let entry = entry?;
let path = entry.path(); let path = entry.path();
println!("Compressing {:?}", path);
if path.is_dir() { if path.is_dir() {
continue; continue;
} }

View File

@ -68,7 +68,9 @@ impl ZipCompressor {
if entry_path.is_dir() { if entry_path.is_dir() {
continue; continue;
} }
writer.start_file(entry_path.to_string_lossy(), options)?; writer.start_file(entry_path.to_string_lossy(), options)?;
println!("Compressing {:?}", entry_path);
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)?;
} }

View File

@ -15,22 +15,14 @@ pub enum Error {
InvalidZipArchive(&'static str), InvalidZipArchive(&'static str),
PermissionDenied, PermissionDenied,
UnsupportedZipArchive(&'static str), UnsupportedZipArchive(&'static str),
// InputsMustBeDecompressible(PathBuf),
InternalError, InternalError,
CompressingRootFolder, CompressingRootFolder,
MissingArgumentsForCompression,
WalkdirError, WalkdirError,
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
// impl std::error::Error for Error {
// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
// // TODO: get rid of PartialEq and Eq in self::Error in order to
// // correctly use `source`.
// None
// }
// }
impl fmt::Debug for Error { impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self) write!(f, "{}", self)
@ -42,19 +34,18 @@ impl fmt::Display for Error {
match self { match self {
Error::MissingExtensionError(filename) => { Error::MissingExtensionError(filename) => {
write!(f, "{} ", "[ERROR]".red())?; write!(f, "{} ", "[ERROR]".red())?;
// 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::InputsMustBeDecompressible(file) => {
// write!(f, "{} ", "[ERROR]".red())?;
// write!(f, "file '{:?}' is not decompressible", file)
// }
Error::WalkdirError => { Error::WalkdirError => {
// Already printed in the From block // Already printed in the From block
write!(f, "") write!(f, "")
} }
Error::FileNotFound(file) => { Error::FileNotFound(file) => {
write!(f, "{} ", "[ERROR]".red())?; write!(f, "{} ", "[ERROR]".red())?;
// TODO: check if file == "" if file == &PathBuf::from("") {
return write!(f, "file not found!");
}
write!(f, "file {:?} not found!", file) write!(f, "file {:?} not found!", file)
} }
Error::CompressingRootFolder => { Error::CompressingRootFolder => {
@ -73,6 +64,10 @@ impl fmt::Display for Error {
"rsync".green() "rsync".green()
) )
} }
Error::MissingArgumentsForCompression => {
write!(f, "{} ", "[ERROR]".red())?;
write!(f,"The compress subcommands demands at least 2 arguments, see usage: <TODO-USAGE>")
}
Error::InternalError => { Error::InternalError => {
write!(f, "{} ", "[ERROR]".red())?; write!(f, "{} ", "[ERROR]".red())?;
write!(f, "You've reached an internal error! This really should not have happened.\nPlease file an issue at {}", "https://github.com/vrmiguel/ouch".green()) write!(f, "You've reached an internal error! This really should not have happened.\nPlease file an issue at {}", "https://github.com/vrmiguel/ouch".green())

View File

@ -7,9 +7,9 @@ use std::{
use colored::Colorize; use colored::Colorize;
use crate::{ use crate::{
cli::Command, cli::{VERSION, Command},
compressors::{ compressors::{
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor, Entry, Compressor, BzipCompressor, GzipCompressor, LzmaCompressor, TarCompressor,
ZipCompressor, ZipCompressor,
}, },
decompressors::{ decompressors::{
@ -20,6 +20,7 @@ use crate::{
extension::{CompressionFormat, Extension}, extension::{CompressionFormat, Extension},
file::File, file::File,
utils, utils,
debug
}; };
pub struct Evaluator {} pub struct Evaluator {}
@ -31,6 +32,7 @@ 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 => {
@ -212,7 +214,7 @@ impl Evaluator {
output: Option<&Path>, output: Option<&Path>,
flags: &oof::Flags, flags: &oof::Flags,
) -> crate::Result<()> { ) -> crate::Result<()> {
let file = File::from(file_path)?; let file = debug!(File::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,
@ -266,9 +268,25 @@ impl Evaluator {
Self::decompress_file(file, output_folder, flags)?; Self::decompress_file(file, output_folder, flags)?;
} }
} }
Command::ShowHelp => todo!("call help function"), Command::ShowHelp => help_message(),
Command::ShowVersion => todo!("call version function"), Command::ShowVersion => version_message(),
} }
Ok(()) Ok(())
} }
} }
#[inline]
fn version_message() {
println!("ouch {}", VERSION);
}
fn help_message() {
version_message();
println!("Vinícius R. M. & João M. Bezerra");
println!("ouch is a unified compression & decompression utility");
println!();
println!(" COMPRESSION USAGE:");
println!(" ouch compress <input...> output-file");
println!("DECOMPRESSION USAGE:");
println!(" ouch <input> [-o/--output output-folder]");
}

View File

@ -7,7 +7,7 @@ use std::{
use CompressionFormat::*; use CompressionFormat::*;
use crate::utils::to_utf; use crate::{debug, utils::to_utf};
/// Represents the extension of a file, but only really caring about /// Represents the extension of a file, but only really caring about
/// compression formats (and .tar). /// compression formats (and .tar).

View File

@ -19,13 +19,12 @@ pub struct File<'a> {
impl<'a> File<'a> { impl<'a> File<'a> {
pub fn from(path: &'a Path) -> crate::Result<Self> { pub fn from(path: &'a Path) -> crate::Result<Self> {
let extension = Extension::from(path.as_ref())?; let extension = Extension::from(path.as_ref()).ok();
eprintln!("dev warning: Should we really ignore the errors from the convertion above?");
Ok(File { Ok(File {
path, path,
contents_in_memory: None, contents_in_memory: None,
extension: Some(extension), extension
}) })
} }
} }

View File

@ -23,6 +23,6 @@ fn main() {
fn run() -> crate::Result<()> { fn run() -> crate::Result<()> {
let ParsedArgs { command, flags } = cli::parse_args()?; let ParsedArgs { command, flags } = cli::parse_args()?;
dbg!(&command); debug!(&command);
Evaluator::evaluate(command, &flags) Evaluator::evaluate(command, &flags)
} }

View File

@ -1,39 +1,112 @@
// TODO: remove tests of CompressionFormat::try_from since that's no longer used anywhere use std::{fs, path::Path};
// use std::{ #[allow(dead_code)]
// convert::TryFrom, // ouch's command-line logic uses fs::canonicalize on its inputs so we cannot
// ffi::{OsStr, OsString}, // use made-up files for testing.
// fs, // make_dummy_file therefores creates a small temporary file to bypass fs::canonicalize errors
// path::Path, 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(())
}
// use crate::{ #[allow(dead_code)]
// cli::Command, fn make_dummy_files<'a, P>(paths: &[P]) -> crate::Result<()>
// extension::{CompressionFormat, CompressionFormat::*, Extension}, where
// file::File, P: AsRef<Path> + 'a,
// }; {
let _ = paths
.iter()
.map(make_dummy_file)
.map(Result::unwrap)
.collect::<Vec<_>>();
Ok(())
}
// // Helper #[cfg(test)]
// fn gen_args(text: &str) -> Vec<OsString> { mod tests {
// let args = text.split_whitespace(); use super::{make_dummy_files};
// args.map(OsString::from).collect() use crate::cli;
// } use crate::cli::Command;
use std::{ffi::OsString, fs, path::PathBuf};
fn gen_args(text: &str) -> Vec<OsString> {
let args = text.split_whitespace();
args.map(OsString::from).collect()
}
macro_rules! parse {
($input_text:expr) => {{
let args = gen_args($input_text);
cli::parse_args_from(args).unwrap()
}};
}
#[test]
// The absolute flags that ignore all the other argparsing rules are --help and --version
fn test_absolute_flags() {
let expected = Command::ShowHelp;
assert_eq!(expected, parse!("").command);
assert_eq!(expected, parse!("-h").command);
assert_eq!(expected, parse!("--help").command);
assert_eq!(expected, parse!("aaaaaaaa --help -o -e aaa").command);
assert_eq!(expected, parse!("aaaaaaaa -h").command);
assert_eq!(expected, parse!("--help compress aaaaaaaa").command);
assert_eq!(expected, parse!("compress --help").command);
assert_eq!(expected, parse!("--version --help").command);
assert_eq!(expected, parse!("aaaaaaaa -v aaaa -h").command);
let expected = Command::ShowVersion;
assert_eq!(expected, parse!("ouch --version").command);
assert_eq!(expected, parse!("ouch a --version b").command);
}
#[test]
fn test_arg_parsing_compress_subcommand() -> crate::Result<()> {
let files = vec!["a", "b", "c"];
make_dummy_files(&*files)?;
let files= files.iter().map(fs::canonicalize).map(Result::unwrap).collect();
let expected = Command::Compress {
files,
compressed_output_path: "d".into(),
};
assert_eq!(expected, parse!("compress a b c d").command);
fs::remove_file("a")?;
fs::remove_file("b")?;
fs::remove_file("c")?;
Ok(())
}
#[test]
fn test_arg_parsing_decompress_subcommand() {
let files: Vec<_> = ["a", "b", "c"].iter().map(PathBuf::from).collect();
let expected = Command::Decompress {
files: files.clone(),
output_folder: None,
};
assert_eq!(expected, parse!("a b c").command);
let expected = Command::Decompress {
files,
output_folder: Some("folder".into()),
};
assert_eq!(expected, parse!("a b c --output folder").command);
assert_eq!(expected, parse!("a b --output folder c").command);
assert_eq!(expected, parse!("a --output folder b c").command);
assert_eq!(expected, parse!("--output folder a b c").command);
}
}
// #[cfg(test)] // #[cfg(test)]
// mod cli { // mod cli {
// use super::*; // use super::*;
// // 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) -> crate::Result<()>
// where
// P: AsRef<Path> + 'a,
// {
// fs::write(path.as_ref(), &[2, 3, 4, 5, 6, 7, 8, 9, 10])?;
// Ok(())
// }
// #[test] // #[test]
// fn decompress_files_into_folder() -> crate::Result<()> { // fn decompress_files_into_folder() -> crate::Result<()> {
// make_dummy_file("file.zip")?; // make_dummy_file("file.zip")?;

View File

@ -9,6 +9,19 @@ use colored::Colorize;
use crate::{dialogs::Confirmation, extension::CompressionFormat, file::File}; use crate::{dialogs::Confirmation, extension::CompressionFormat, file::File};
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! debug {
($x:expr) => { dbg!($x) }
}
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! debug {
($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,
@ -69,7 +82,7 @@ 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).unwrap(); env::set_current_dir(parent).ok().ok_or(crate::Error::CompressingRootFolder)?;
Ok(previous_location) Ok(previous_location)
} }