From 4590ae8535c70632e2f5e77eb95ef9ff18e63088 Mon Sep 17 00:00:00 2001 From: sharkdp Date: Fri, 3 Apr 2020 21:18:54 +0200 Subject: [PATCH] Proper error handling within walk.rs --- src/error.rs | 11 ++-------- src/exec/command.rs | 5 +++-- src/exec/job.rs | 13 ++++++----- src/main.rs | 4 +--- src/walk.rs | 53 ++++++++++++++++++++------------------------- 5 files changed, 38 insertions(+), 48 deletions(-) diff --git a/src/error.rs b/src/error.rs index aad963b..3501fee 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,10 +1,3 @@ -macro_rules! print_error { - ($($arg:tt)*) => (eprintln!("[fd error]: {}", format!($($arg)*))) -} - -macro_rules! print_error_and_exit { - ($($arg:tt)*) => { - print_error!($($arg)*); - ::std::process::exit(1); - }; +pub fn print_error(msg: impl Into) { + eprintln!("[fd error]: {}", msg.into()); } diff --git a/src/exec/command.rs b/src/exec/command.rs index 29dd219..ecdfe62 100644 --- a/src/exec/command.rs +++ b/src/exec/command.rs @@ -3,6 +3,7 @@ use std::io::Write; use std::process::Command; use std::sync::Mutex; +use crate::error::print_error; use crate::exit_codes::ExitCode; /// Executes a command. @@ -30,11 +31,11 @@ pub fn execute_command(mut cmd: Command, out_perm: &Mutex<()>) -> ExitCode { } } Err(ref why) if why.kind() == io::ErrorKind::NotFound => { - print_error!("Command not found: {:?}", cmd); + print_error(format!("Command not found: {:?}", cmd)); ExitCode::GeneralError } Err(why) => { - print_error!("Problem while executing command: {}", why); + print_error(format!("Problem while executing command: {}", why)); ExitCode::GeneralError } } diff --git a/src/exec/job.rs b/src/exec/job.rs index eafb0cd..eef042a 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -1,10 +1,13 @@ -use super::CommandTemplate; -use crate::exit_codes::{merge_exitcodes, ExitCode}; -use crate::walk::WorkerResult; use std::path::PathBuf; use std::sync::mpsc::Receiver; use std::sync::{Arc, Mutex}; +use crate::error::print_error; +use crate::exit_codes::{merge_exitcodes, ExitCode}; +use crate::walk::WorkerResult; + +use super::CommandTemplate; + /// An event loop that listens for inputs from the `rx` receiver. Each received input will /// generate a command with the supplied command template. The generated command will then /// be executed, and this process will continue until the receiver's sender has closed. @@ -25,7 +28,7 @@ pub fn job( Ok(WorkerResult::Entry(val)) => val, Ok(WorkerResult::Error(err)) => { if show_filesystem_errors { - print_error!("{}", err); + print_error(err.to_string()); } continue; } @@ -50,7 +53,7 @@ pub fn batch( WorkerResult::Entry(val) => Some(val), WorkerResult::Error(err) => { if show_filesystem_errors { - print_error!("{}", err); + print_error(err.to_string()); } None } diff --git a/src/main.rs b/src/main.rs index b48b660..e0e585f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -303,9 +303,7 @@ fn run() -> Result { ) })?; - let exit_code = walk::scan(&dir_vec, Arc::new(re), Arc::new(config)); - - Ok(exit_code) + walk::scan(&dir_vec, Arc::new(re), Arc::new(config)) } fn main() { diff --git a/src/walk.rs b/src/walk.rs index e70c2be..3385869 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,9 +1,3 @@ -use crate::exec; -use crate::exit_codes::{merge_exitcodes, ExitCode}; -use crate::filesystem; -use crate::options::Options; -use crate::output; - use std::borrow::Cow; use std::ffi::OsStr; use std::fs::{FileType, Metadata}; @@ -16,10 +10,18 @@ use std::sync::{Arc, Mutex}; use std::thread; use std::time; +use anyhow::{anyhow, Result}; use ignore::overrides::OverrideBuilder; use ignore::{self, WalkBuilder}; use regex::bytes::Regex; +use crate::error::print_error; +use crate::exec; +use crate::exit_codes::{merge_exitcodes, ExitCode}; +use crate::filesystem; +use crate::options::Options; +use crate::output; + /// The receiver thread can either be buffering results or directly streaming to the console. enum ReceiverMode { /// Receiver is still buffering in order to sort the results, if the search finishes fast @@ -44,7 +46,7 @@ pub const MAX_BUFFER_LENGTH: usize = 1000; /// If the `--exec` argument was supplied, this will create a thread pool for executing /// jobs in parallel from a given command line and the discovered paths. Otherwise, each /// path will simply be written to standard output. -pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> ExitCode { +pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> Result { let mut path_iter = path_vec.iter(); let first_path_buf = path_iter .next() @@ -54,14 +56,13 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> let mut override_builder = OverrideBuilder::new(first_path_buf.as_path()); for pattern in &config.exclude_patterns { - let res = override_builder.add(pattern); - if res.is_err() { - print_error_and_exit!("Malformed exclude pattern '{}'", pattern); - } + override_builder + .add(pattern) + .map_err(|e| anyhow!("Malformed exclude pattern: {}", e))?; } - let overrides = override_builder.build().unwrap_or_else(|_| { - print_error_and_exit!("Mismatch in exclude patterns"); - }); + let overrides = override_builder + .build() + .map_err(|_| anyhow!("Mismatch in exclude patterns"))?; let mut walker = WalkBuilder::new(first_path_buf.as_path()); walker @@ -86,13 +87,10 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> match result { Some(ignore::Error::Partial(_)) => (), Some(err) => { - print_error!( - "{}", - format!( - "Malformed pattern in custom ignore file. {}.", - err.to_string() - ) - ); + print_error(format!( + "Malformed pattern in custom ignore file. {}.", + err.to_string() + )); } None => (), } @@ -131,7 +129,7 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> process::exit(ExitCode::KilledBySigint.into()); } - exit_code + Ok(exit_code) } fn spawn_receiver( @@ -231,7 +229,7 @@ fn spawn_receiver( } WorkerResult::Error(err) => { if show_filesystem_errors { - print_error!("{}", err); + print_error(err.to_string()); } } } @@ -344,12 +342,9 @@ fn spawn_senders( let entry_path = entry.path(); let search_str: Cow = if config.search_full_path { - match filesystem::path_absolute_form(entry_path) { - Ok(path_abs_buf) => Cow::Owned(path_abs_buf.as_os_str().to_os_string()), - Err(_) => { - print_error_and_exit!("Unable to retrieve absolute path."); - } - } + let path_abs_buf = filesystem::path_absolute_form(entry_path) + .expect("Retrieving absolute path succeeds"); + Cow::Owned(path_abs_buf.as_os_str().to_os_string()) } else { match entry_path.file_name() { Some(filename) => Cow::Borrowed(filename),