Refactor FinalError::display_and_crash into Error::Custom

This commit is contained in:
Vinícius Rodrigues Miguel 2021-10-06 16:23:19 -03:00
parent 40410840c9
commit b093277a85
2 changed files with 30 additions and 25 deletions

View File

@ -20,6 +20,7 @@ use crate::{
}, },
info, oof, utils, info, oof, utils,
utils::to_utf, utils::to_utf,
Error,
}; };
// Used in BufReader and BufWriter to perform less syscalls // Used in BufReader and BufWriter to perform less syscalls
@ -32,14 +33,16 @@ pub fn run(command: Command, flags: &oof::Flags) -> crate::Result<()> {
let formats = extension::extensions_from_path(&output_path); let formats = extension::extensions_from_path(&output_path);
if formats.is_empty() { if formats.is_empty() {
FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path))) let reason = FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path)))
.detail("You shall supply the compression format via the extension.") .detail("You shall supply the compression format via the extension.")
.hint("Try adding something like .tar.gz or .zip to the output file.") .hint("Try adding something like .tar.gz or .zip to the output file.")
.hint("") .hint("")
.hint("Examples:") .hint("Examples:")
.hint(format!(" ouch compress ... {}.tar.gz", to_utf(&output_path))) .hint(format!(" ouch compress ... {}.tar.gz", to_utf(&output_path)))
.hint(format!(" ouch compress ... {}.zip", to_utf(&output_path))) .hint(format!(" ouch compress ... {}.zip", to_utf(&output_path)))
.display_and_crash(); .into_owned();
return Err(Error::with_reason(reason));
} }
if matches!(&formats[0], Bzip | Gzip | Lzma) && files.len() > 1 { if matches!(&formats[0], Bzip | Gzip | Lzma) && files.len() > 1 {
@ -59,35 +62,35 @@ pub fn run(command: Command, flags: &oof::Flags) -> crate::Result<()> {
let mut suggested_output_path = output_path.clone(); let mut suggested_output_path = output_path.clone();
suggested_output_path.replace_range(empty_range, ".tar"); suggested_output_path.replace_range(empty_range, ".tar");
FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path))) let reason = FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path)))
.detail("You are trying to compress multiple files.") .detail("You are trying to compress multiple files.")
.detail(format!("The compression format '{}' cannot receive multiple files.", &formats[0])) .detail(format!("The compression format '{}' cannot receive multiple files.", &formats[0]))
.detail("The only supported formats that bundle files into an archive are .tar and .zip.") .detail("The only supported formats that bundle files into an archive are .tar and .zip.")
.hint(format!("Try inserting '.tar' or '.zip' before '{}'.", &formats[0])) .hint(format!("Try inserting '.tar' or '.zip' before '{}'.", &formats[0]))
.hint(format!("From: {}", output_path)) .hint(format!("From: {}", output_path))
.hint(format!(" To : {}", suggested_output_path)) .hint(format!(" To : {}", suggested_output_path))
.display_and_crash(); .into_owned();
return Err(Error::with_reason(reason));
} }
if let Some(format) = formats.iter().skip(1).position(|format| matches!(format, Tar | Zip)) { if let Some(format) = formats.iter().skip(1).position(|format| matches!(format, Tar | Zip)) {
FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path))) let reason = FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path)))
.detail(format!("Found the format '{}' in an incorrect position.", format)) .detail(format!("Found the format '{}' in an incorrect position.", format))
.detail(format!("{} can only be used at the start of the file extension.", format)) .detail(format!("{} can only be used at the start of the file extension.", format))
.hint(format!("If you wish to compress multiple files, start the extension with {}.", format)) .hint(format!("If you wish to compress multiple files, start the extension with {}.", format))
.hint(format!("Otherwise, remove {} from '{}'.", format, to_utf(&output_path))) .hint(format!("Otherwise, remove {} from '{}'.", format, to_utf(&output_path)))
.display_and_crash(); .into_owned();
return Err(Error::with_reason(reason));
} }
if output_path.exists() && !utils::user_wants_to_overwrite(&output_path, flags)? { if output_path.exists() && !utils::user_wants_to_overwrite(&output_path, flags)? {
// User does not want to overwrite this file
return Ok(()); return Ok(());
} }
let output_file = fs::File::create(&output_path).unwrap_or_else(|err| { let output_file = fs::File::create(&output_path)?;
FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path)))
.detail(format!("Could not open file '{}' for writing.", to_utf(&output_path)))
.detail(format!("Error: {}.", err))
.display_and_crash()
});
let compress_result = compress_files(files, formats, output_file, flags); let compress_result = compress_files(files, formats, output_file, flags);
// If any error occurred, delete incomplete file // If any error occurred, delete incomplete file

View File

@ -30,11 +30,12 @@ pub enum Error {
MissingArgumentsForDecompression, MissingArgumentsForDecompression,
CompressionTypo, CompressionTypo,
WalkdirError { reason: String }, WalkdirError { reason: String },
Custom { reason: FinalError },
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
#[derive(Default)] #[derive(Debug, Default, PartialEq)]
pub struct FinalError { pub struct FinalError {
title: String, title: String,
details: Vec<String>, details: Vec<String>,
@ -79,14 +80,9 @@ impl FinalError {
self self
} }
pub fn to_owned(&mut self) -> Self { pub fn into_owned(&mut self) -> Self {
std::mem::take(self) std::mem::take(self)
} }
pub fn display_and_crash(&self) -> ! {
eprintln!("{}", self);
std::process::exit(crate::EXIT_FAILURE)
}
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@ -97,7 +93,7 @@ impl fmt::Display for Error {
.detail("Ouch could not detect the compression format") .detail("Ouch could not detect the compression format")
.hint("Use a supported format extension, like '.zip' or '.tar.gz'") .hint("Use a supported format extension, like '.zip' or '.tar.gz'")
.hint("Check https://github.com/vrmiguel/ouch for a full list of supported formats") .hint("Check https://github.com/vrmiguel/ouch for a full list of supported formats")
.to_owned(); .into_owned();
error error
} }
@ -115,7 +111,7 @@ impl fmt::Display for Error {
let error = FinalError::with_title("It seems you're trying to compress the root folder.") let error = FinalError::with_title("It seems you're trying to compress the root folder.")
.detail("This is unadvisable since ouch does compressions in-memory.") .detail("This is unadvisable since ouch does compressions in-memory.")
.hint("Use a more appropriate tool for this, such as rsync.") .hint("Use a more appropriate tool for this, such as rsync.")
.to_owned(); .into_owned();
error error
} }
@ -127,7 +123,7 @@ impl fmt::Display for Error {
.hint(" - The output argument.") .hint(" - The output argument.")
.hint("") .hint("")
.hint("Example: `ouch compress image.png img.zip`") .hint("Example: `ouch compress image.png img.zip`")
.to_owned(); .into_owned();
error error
} }
@ -138,7 +134,7 @@ impl fmt::Display for Error {
.hint(" - At least one input argument.") .hint(" - At least one input argument.")
.hint("") .hint("")
.hint("Example: `ouch decompress imgs.tar.gz`") .hint("Example: `ouch decompress imgs.tar.gz`")
.to_owned(); .into_owned();
error error
} }
@ -148,7 +144,7 @@ impl fmt::Display for Error {
.detail("It's probably our fault") .detail("It's probably our fault")
.detail("Please help us improve by reporting the issue at:") .detail("Please help us improve by reporting the issue at:")
.detail(format!(" {}https://github.com/vrmiguel/ouch/issues ", cyan())) .detail(format!(" {}https://github.com/vrmiguel/ouch/issues ", cyan()))
.to_owned(); .into_owned();
error error
} }
@ -156,7 +152,7 @@ impl fmt::Display for Error {
Error::IoError { reason } => FinalError::with_title(reason), Error::IoError { reason } => FinalError::with_title(reason),
Error::CompressionTypo => FinalError::with_title("Possible typo detected") Error::CompressionTypo => FinalError::with_title("Possible typo detected")
.hint(format!("Did you mean '{}ouch compress{}'?", magenta(), reset())) .hint(format!("Did you mean '{}ouch compress{}'?", magenta(), reset()))
.to_owned(), .into_owned(),
_err => { _err => {
todo!(); todo!();
} }
@ -166,6 +162,12 @@ impl fmt::Display for Error {
} }
} }
impl Error {
pub fn with_reason(reason: FinalError) -> Self {
Self::Custom { reason }
}
}
impl From<std::io::Error> for Error { impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self { fn from(err: std::io::Error) -> Self {
match err.kind() { match err.kind() {