mirror of https://github.com/sharkdp/fd.git
Proper error handling within walk.rs
This commit is contained in:
parent
bce95274e3
commit
4590ae8535
11
src/error.rs
11
src/error.rs
|
@ -1,10 +1,3 @@
|
||||||
macro_rules! print_error {
|
pub fn print_error(msg: impl Into<String>) {
|
||||||
($($arg:tt)*) => (eprintln!("[fd error]: {}", format!($($arg)*)))
|
eprintln!("[fd error]: {}", msg.into());
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! print_error_and_exit {
|
|
||||||
($($arg:tt)*) => {
|
|
||||||
print_error!($($arg)*);
|
|
||||||
::std::process::exit(1);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::io::Write;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use crate::error::print_error;
|
||||||
use crate::exit_codes::ExitCode;
|
use crate::exit_codes::ExitCode;
|
||||||
|
|
||||||
/// Executes a command.
|
/// 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 => {
|
Err(ref why) if why.kind() == io::ErrorKind::NotFound => {
|
||||||
print_error!("Command not found: {:?}", cmd);
|
print_error(format!("Command not found: {:?}", cmd));
|
||||||
ExitCode::GeneralError
|
ExitCode::GeneralError
|
||||||
}
|
}
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
print_error!("Problem while executing command: {}", why);
|
print_error(format!("Problem while executing command: {}", why));
|
||||||
ExitCode::GeneralError
|
ExitCode::GeneralError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
use super::CommandTemplate;
|
|
||||||
use crate::exit_codes::{merge_exitcodes, ExitCode};
|
|
||||||
use crate::walk::WorkerResult;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
use std::sync::{Arc, Mutex};
|
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
|
/// 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
|
/// 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.
|
/// 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::Entry(val)) => val,
|
||||||
Ok(WorkerResult::Error(err)) => {
|
Ok(WorkerResult::Error(err)) => {
|
||||||
if show_filesystem_errors {
|
if show_filesystem_errors {
|
||||||
print_error!("{}", err);
|
print_error(err.to_string());
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +53,7 @@ pub fn batch(
|
||||||
WorkerResult::Entry(val) => Some(val),
|
WorkerResult::Entry(val) => Some(val),
|
||||||
WorkerResult::Error(err) => {
|
WorkerResult::Error(err) => {
|
||||||
if show_filesystem_errors {
|
if show_filesystem_errors {
|
||||||
print_error!("{}", err);
|
print_error(err.to_string());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,9 +303,7 @@ fn run() -> Result<ExitCode> {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let exit_code = walk::scan(&dir_vec, Arc::new(re), Arc::new(config));
|
walk::scan(&dir_vec, Arc::new(re), Arc::new(config))
|
||||||
|
|
||||||
Ok(exit_code)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
53
src/walk.rs
53
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::borrow::Cow;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs::{FileType, Metadata};
|
use std::fs::{FileType, Metadata};
|
||||||
|
@ -16,10 +10,18 @@ use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
use ignore::overrides::OverrideBuilder;
|
use ignore::overrides::OverrideBuilder;
|
||||||
use ignore::{self, WalkBuilder};
|
use ignore::{self, WalkBuilder};
|
||||||
use regex::bytes::Regex;
|
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.
|
/// The receiver thread can either be buffering results or directly streaming to the console.
|
||||||
enum ReceiverMode {
|
enum ReceiverMode {
|
||||||
/// Receiver is still buffering in order to sort the results, if the search finishes fast
|
/// 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
|
/// 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
|
/// jobs in parallel from a given command line and the discovered paths. Otherwise, each
|
||||||
/// path will simply be written to standard output.
|
/// path will simply be written to standard output.
|
||||||
pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<Options>) -> ExitCode {
|
pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<Options>) -> Result<ExitCode> {
|
||||||
let mut path_iter = path_vec.iter();
|
let mut path_iter = path_vec.iter();
|
||||||
let first_path_buf = path_iter
|
let first_path_buf = path_iter
|
||||||
.next()
|
.next()
|
||||||
|
@ -54,14 +56,13 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<Options>) ->
|
||||||
let mut override_builder = OverrideBuilder::new(first_path_buf.as_path());
|
let mut override_builder = OverrideBuilder::new(first_path_buf.as_path());
|
||||||
|
|
||||||
for pattern in &config.exclude_patterns {
|
for pattern in &config.exclude_patterns {
|
||||||
let res = override_builder.add(pattern);
|
override_builder
|
||||||
if res.is_err() {
|
.add(pattern)
|
||||||
print_error_and_exit!("Malformed exclude pattern '{}'", pattern);
|
.map_err(|e| anyhow!("Malformed exclude pattern: {}", e))?;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let overrides = override_builder.build().unwrap_or_else(|_| {
|
let overrides = override_builder
|
||||||
print_error_and_exit!("Mismatch in exclude patterns");
|
.build()
|
||||||
});
|
.map_err(|_| anyhow!("Mismatch in exclude patterns"))?;
|
||||||
|
|
||||||
let mut walker = WalkBuilder::new(first_path_buf.as_path());
|
let mut walker = WalkBuilder::new(first_path_buf.as_path());
|
||||||
walker
|
walker
|
||||||
|
@ -86,13 +87,10 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<Options>) ->
|
||||||
match result {
|
match result {
|
||||||
Some(ignore::Error::Partial(_)) => (),
|
Some(ignore::Error::Partial(_)) => (),
|
||||||
Some(err) => {
|
Some(err) => {
|
||||||
print_error!(
|
print_error(format!(
|
||||||
"{}",
|
"Malformed pattern in custom ignore file. {}.",
|
||||||
format!(
|
err.to_string()
|
||||||
"Malformed pattern in custom ignore file. {}.",
|
));
|
||||||
err.to_string()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
|
@ -131,7 +129,7 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<Options>) ->
|
||||||
process::exit(ExitCode::KilledBySigint.into());
|
process::exit(ExitCode::KilledBySigint.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_code
|
Ok(exit_code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_receiver(
|
fn spawn_receiver(
|
||||||
|
@ -231,7 +229,7 @@ fn spawn_receiver(
|
||||||
}
|
}
|
||||||
WorkerResult::Error(err) => {
|
WorkerResult::Error(err) => {
|
||||||
if show_filesystem_errors {
|
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 entry_path = entry.path();
|
||||||
|
|
||||||
let search_str: Cow<OsStr> = if config.search_full_path {
|
let search_str: Cow<OsStr> = if config.search_full_path {
|
||||||
match filesystem::path_absolute_form(entry_path) {
|
let path_abs_buf = filesystem::path_absolute_form(entry_path)
|
||||||
Ok(path_abs_buf) => Cow::Owned(path_abs_buf.as_os_str().to_os_string()),
|
.expect("Retrieving absolute path succeeds");
|
||||||
Err(_) => {
|
Cow::Owned(path_abs_buf.as_os_str().to_os_string())
|
||||||
print_error_and_exit!("Unable to retrieve absolute path.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
match entry_path.file_name() {
|
match entry_path.file_name() {
|
||||||
Some(filename) => Cow::Borrowed(filename),
|
Some(filename) => Cow::Borrowed(filename),
|
||||||
|
|
Loading…
Reference in New Issue