Exit status now depends on Result
This commit is contained in:
parent
b8d2be4abe
commit
53041af73c
5 changed files with 59 additions and 7 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::path::PathBuf;
|
||||
use std::{fmt, iter, path::PathBuf};
|
||||
|
||||
/// Result convenience type for the Error type
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
@ -10,6 +10,9 @@ pub enum Error {
|
|||
#[error("IO error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error("Path doesn't exist: {0}")]
|
||||
FileDoesntExist(PathBuf),
|
||||
|
||||
#[error("Could not open file {0:?}: {1}")]
|
||||
OpenFile(PathBuf, std::io::Error),
|
||||
|
||||
|
@ -36,6 +39,44 @@ pub enum Error {
|
|||
|
||||
#[error("Put error: {0}")]
|
||||
Put(#[from] crate::ops::put::PutError),
|
||||
|
||||
#[error("{0} and {1}")]
|
||||
And(Box<Error>, Box<Error>),
|
||||
|
||||
#[error("{0}")]
|
||||
Multiple(MultipleErrors),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Construct an error consisting of multiple errors
|
||||
pub fn multiple(errors: impl Iterator<Item = Error>) -> Self {
|
||||
Error::Multiple(MultipleErrors(
|
||||
errors
|
||||
.map(|err| -> Box<dyn Iterator<Item = Error>> {
|
||||
match err {
|
||||
Error::Multiple(MultipleErrors(errors)) => {
|
||||
Box::new(errors.into_iter())
|
||||
}
|
||||
_ => Box::new(iter::once(err)),
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MultipleErrors(Vec<Error>);
|
||||
|
||||
impl fmt::Display for MultipleErrors {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "")?;
|
||||
for err in self.0.iter() {
|
||||
writeln!(f, "- {}", err)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors related to .trashinfo files
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::process::exit;
|
||||
|
||||
use garbage::{
|
||||
ops::{self, EmptyOptions, ListOptions, PutOptions, RestoreOptions},
|
||||
Result,
|
||||
|
@ -61,7 +66,8 @@ fn main() {
|
|||
match run(opt.command) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
eprintln!("Error: {}", err);
|
||||
error!("{}", err);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ use std::fs::File;
|
|||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use libmount::mountinfo::Parser;
|
||||
use libc::c_ulong;
|
||||
use libmount::mountinfo::Parser;
|
||||
|
||||
use crate::errors::Error;
|
||||
use crate::utils;
|
||||
|
|
|
@ -65,11 +65,13 @@ pub struct PutOptions {
|
|||
|
||||
/// Throw some files into the trash.
|
||||
pub fn put(options: PutOptions) -> Result<()> {
|
||||
let mut errors = vec![];
|
||||
|
||||
for path in options.paths.iter() {
|
||||
let abs_path = utils::into_absolute(&path)?;
|
||||
|
||||
if !abs_path.exists() {
|
||||
error!("Skipping non-existent path {:?}", path);
|
||||
errors.push(Error::FileDoesntExist(path.clone()));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -102,7 +104,11 @@ pub fn put(options: PutOptions) -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::multiple(errors.into_iter()))
|
||||
}
|
||||
}
|
||||
|
||||
/// DeletionStrategy describes a strategy by which a file is deleted
|
||||
|
|
|
@ -24,8 +24,7 @@ pub fn into_absolute(path: impl AsRef<Path>) -> Result<PathBuf> {
|
|||
for component in path.components() {
|
||||
match component {
|
||||
Component::Prefix(_) => unimplemented!("windows lol"),
|
||||
Component::RootDir => {
|
||||
}
|
||||
Component::RootDir => {}
|
||||
Component::CurDir => {}
|
||||
Component::ParentDir => {
|
||||
new_path.pop();
|
||||
|
|
Loading…
Reference in a new issue