Expose exit status from `--exec-batch <cmd>`

closes #333
This commit is contained in:
sharkdp 2019-09-13 22:26:27 +02:00 committed by David Peter
parent 630749f706
commit a0505bd4df
7 changed files with 44 additions and 11 deletions

2
Cargo.lock generated
View File

@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.6.9" version = "0.6.9"

View File

@ -11,8 +11,10 @@ use std::io::Write;
use std::process::Command; use std::process::Command;
use std::sync::Mutex; use std::sync::Mutex;
use crate::exit_codes::ExitCode;
/// Executes a command. /// Executes a command.
pub fn execute_command(mut cmd: Command, out_perm: &Mutex<()>) { pub fn execute_command(mut cmd: Command, out_perm: &Mutex<()>) -> ExitCode {
// Spawn the supplied command. // Spawn the supplied command.
let output = cmd.output(); let output = cmd.output();
@ -28,12 +30,20 @@ pub fn execute_command(mut cmd: Command, out_perm: &Mutex<()>) {
let _ = stdout.lock().write_all(&output.stdout); let _ = stdout.lock().write_all(&output.stdout);
let _ = stderr.lock().write_all(&output.stderr); let _ = stderr.lock().write_all(&output.stderr);
if output.status.code() == Some(0) {
ExitCode::Success
} else {
ExitCode::GeneralError
}
} }
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!("Command not found: {:?}", cmd);
ExitCode::GeneralError
} }
Err(why) => { Err(why) => {
print_error!("Problem while executing command: {}", why); print_error!("Problem while executing command: {}", why);
ExitCode::GeneralError
} }
} }
} }

View File

@ -7,6 +7,7 @@
// according to those terms. // according to those terms.
use super::CommandTemplate; use super::CommandTemplate;
use crate::exit_codes::ExitCode;
use crate::walk::WorkerResult; use crate::walk::WorkerResult;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
@ -45,7 +46,11 @@ pub fn job(
} }
} }
pub fn batch(rx: Receiver<WorkerResult>, cmd: &CommandTemplate, show_filesystem_errors: bool) { pub fn batch(
rx: Receiver<WorkerResult>,
cmd: &CommandTemplate,
show_filesystem_errors: bool,
) -> ExitCode {
let paths = rx.iter().filter_map(|value| match value { let paths = rx.iter().filter_map(|value| match value {
WorkerResult::Entry(val) => Some(val), WorkerResult::Entry(val) => Some(val),
WorkerResult::Error(err) => { WorkerResult::Error(err) => {
@ -55,5 +60,5 @@ pub fn batch(rx: Receiver<WorkerResult>, cmd: &CommandTemplate, show_filesystem_
None None
} }
}); });
cmd.generate_and_execute_batch(paths); cmd.generate_and_execute_batch(paths)
} }

View File

@ -20,6 +20,8 @@ use std::sync::{Arc, Mutex};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use crate::exit_codes::ExitCode;
use self::command::execute_command; use self::command::execute_command;
use self::input::{basename, dirname, remove_extension}; use self::input::{basename, dirname, remove_extension};
pub use self::job::{batch, job}; pub use self::job::{batch, job};
@ -152,14 +154,14 @@ impl CommandTemplate {
cmd.arg(arg.generate(&input).as_ref()); cmd.arg(arg.generate(&input).as_ref());
} }
execute_command(cmd, &out_perm) execute_command(cmd, &out_perm);
} }
pub fn in_batch_mode(&self) -> bool { pub fn in_batch_mode(&self) -> bool {
self.mode == ExecutionMode::Batch self.mode == ExecutionMode::Batch
} }
pub fn generate_and_execute_batch<I>(&self, paths: I) pub fn generate_and_execute_batch<I>(&self, paths: I) -> ExitCode
where where
I: Iterator<Item = PathBuf>, I: Iterator<Item = PathBuf>,
{ {
@ -185,7 +187,9 @@ impl CommandTemplate {
} }
if has_path { if has_path {
execute_command(cmd, &Mutex::new(())); execute_command(cmd, &Mutex::new(()))
} else {
ExitCode::Success
} }
} }
} }

View File

@ -1,4 +1,5 @@
pub enum ExitCode { pub enum ExitCode {
Success,
GeneralError, GeneralError,
KilledBySigint, KilledBySigint,
} }
@ -6,6 +7,7 @@ pub enum ExitCode {
impl Into<i32> for ExitCode { impl Into<i32> for ExitCode {
fn into(self) -> i32 { fn into(self) -> i32 {
match self { match self {
ExitCode::Success => 0,
ExitCode::GeneralError => 1, ExitCode::GeneralError => 1,
ExitCode::KilledBySigint => 130, ExitCode::KilledBySigint => 130,
} }

View File

@ -19,6 +19,7 @@ mod walk;
use std::env; use std::env;
use std::error::Error; use std::error::Error;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process;
use std::sync::Arc; use std::sync::Arc;
use std::time; use std::time;
@ -250,7 +251,10 @@ fn main() {
.dot_matches_new_line(true) .dot_matches_new_line(true)
.build() .build()
{ {
Ok(re) => walk::scan(&dir_vec, Arc::new(re), Arc::new(config)), Ok(re) => {
let exit_code = walk::scan(&dir_vec, Arc::new(re), Arc::new(config));
process::exit(exit_code.into());
}
Err(err) => { Err(err) => {
print_error_and_exit!( print_error_and_exit!(
"{}\nHint: You can use the '--fixed-strings' option to search for a \ "{}\nHint: You can use the '--fixed-strings' option to search for a \

View File

@ -47,7 +47,7 @@ pub enum WorkerResult {
/// 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<FdOptions>) { pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) -> 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()
@ -122,18 +122,20 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) {
spawn_senders(&config, &wants_to_quit, pattern, parallel_walker, tx); spawn_senders(&config, &wants_to_quit, pattern, parallel_walker, tx);
// Wait for the receiver thread to print out all results. // Wait for the receiver thread to print out all results.
receiver_thread.join().unwrap(); let exit_code = receiver_thread.join().unwrap();
if wants_to_quit.load(Ordering::Relaxed) { if wants_to_quit.load(Ordering::Relaxed) {
process::exit(ExitCode::KilledBySigint.into()); process::exit(ExitCode::KilledBySigint.into());
} }
exit_code
} }
fn spawn_receiver( fn spawn_receiver(
config: &Arc<FdOptions>, config: &Arc<FdOptions>,
wants_to_quit: &Arc<AtomicBool>, wants_to_quit: &Arc<AtomicBool>,
rx: Receiver<WorkerResult>, rx: Receiver<WorkerResult>,
) -> thread::JoinHandle<()> { ) -> thread::JoinHandle<ExitCode> {
let config = Arc::clone(config); let config = Arc::clone(config);
let wants_to_quit = Arc::clone(wants_to_quit); let wants_to_quit = Arc::clone(wants_to_quit);
@ -144,7 +146,7 @@ fn spawn_receiver(
// This will be set to `Some` if the `--exec` argument was supplied. // This will be set to `Some` if the `--exec` argument was supplied.
if let Some(ref cmd) = config.command { if let Some(ref cmd) = config.command {
if cmd.in_batch_mode() { if cmd.in_batch_mode() {
exec::batch(rx, cmd, show_filesystem_errors); exec::batch(rx, cmd, show_filesystem_errors)
} else { } else {
let shared_rx = Arc::new(Mutex::new(rx)); let shared_rx = Arc::new(Mutex::new(rx));
@ -169,6 +171,8 @@ fn spawn_receiver(
for h in handles { for h in handles {
h.join().unwrap(); h.join().unwrap();
} }
ExitCode::Success
} }
} else { } else {
let start = time::Instant::now(); let start = time::Instant::now();
@ -233,6 +237,8 @@ fn spawn_receiver(
output::print_entry(&mut stdout, &value, &config, &wants_to_quit); output::print_entry(&mut stdout, &value, &config, &wants_to_quit);
} }
} }
ExitCode::Success
} }
}) })
} }