From a0505bd4df82dc2203195d4f651a5ab7227987d0 Mon Sep 17 00:00:00 2001 From: sharkdp Date: Fri, 13 Sep 2019 22:26:27 +0200 Subject: [PATCH] Expose exit status from `--exec-batch ` closes #333 --- Cargo.lock | 2 ++ src/exec/command.rs | 12 +++++++++++- src/exec/job.rs | 9 +++++++-- src/exec/mod.rs | 10 +++++++--- src/exit_codes.rs | 2 ++ src/main.rs | 6 +++++- src/walk.rs | 14 ++++++++++---- 7 files changed, 44 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 717798c..12eeb07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.9" diff --git a/src/exec/command.rs b/src/exec/command.rs index f02b5f4..f6d79d0 100644 --- a/src/exec/command.rs +++ b/src/exec/command.rs @@ -11,8 +11,10 @@ use std::io::Write; use std::process::Command; use std::sync::Mutex; +use crate::exit_codes::ExitCode; + /// 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. 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 _ = 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 => { print_error!("Command not found: {:?}", cmd); + ExitCode::GeneralError } Err(why) => { print_error!("Problem while executing command: {}", why); + ExitCode::GeneralError } } } diff --git a/src/exec/job.rs b/src/exec/job.rs index 56d6966..2707238 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -7,6 +7,7 @@ // according to those terms. use super::CommandTemplate; +use crate::exit_codes::ExitCode; use crate::walk::WorkerResult; use std::path::PathBuf; use std::sync::mpsc::Receiver; @@ -45,7 +46,11 @@ pub fn job( } } -pub fn batch(rx: Receiver, cmd: &CommandTemplate, show_filesystem_errors: bool) { +pub fn batch( + rx: Receiver, + cmd: &CommandTemplate, + show_filesystem_errors: bool, +) -> ExitCode { let paths = rx.iter().filter_map(|value| match value { WorkerResult::Entry(val) => Some(val), WorkerResult::Error(err) => { @@ -55,5 +60,5 @@ pub fn batch(rx: Receiver, cmd: &CommandTemplate, show_filesystem_ None } }); - cmd.generate_and_execute_batch(paths); + cmd.generate_and_execute_batch(paths) } diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 8f335e4..3690331 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -20,6 +20,8 @@ use std::sync::{Arc, Mutex}; use lazy_static::lazy_static; use regex::Regex; +use crate::exit_codes::ExitCode; + use self::command::execute_command; use self::input::{basename, dirname, remove_extension}; pub use self::job::{batch, job}; @@ -152,14 +154,14 @@ impl CommandTemplate { cmd.arg(arg.generate(&input).as_ref()); } - execute_command(cmd, &out_perm) + execute_command(cmd, &out_perm); } pub fn in_batch_mode(&self) -> bool { self.mode == ExecutionMode::Batch } - pub fn generate_and_execute_batch(&self, paths: I) + pub fn generate_and_execute_batch(&self, paths: I) -> ExitCode where I: Iterator, { @@ -185,7 +187,9 @@ impl CommandTemplate { } if has_path { - execute_command(cmd, &Mutex::new(())); + execute_command(cmd, &Mutex::new(())) + } else { + ExitCode::Success } } } diff --git a/src/exit_codes.rs b/src/exit_codes.rs index 225c5bc..0265627 100644 --- a/src/exit_codes.rs +++ b/src/exit_codes.rs @@ -1,4 +1,5 @@ pub enum ExitCode { + Success, GeneralError, KilledBySigint, } @@ -6,6 +7,7 @@ pub enum ExitCode { impl Into for ExitCode { fn into(self) -> i32 { match self { + ExitCode::Success => 0, ExitCode::GeneralError => 1, ExitCode::KilledBySigint => 130, } diff --git a/src/main.rs b/src/main.rs index d24eb96..eb6b995 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ mod walk; use std::env; use std::error::Error; use std::path::{Path, PathBuf}; +use std::process; use std::sync::Arc; use std::time; @@ -250,7 +251,10 @@ fn main() { .dot_matches_new_line(true) .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) => { print_error_and_exit!( "{}\nHint: You can use the '--fixed-strings' option to search for a \ diff --git a/src/walk.rs b/src/walk.rs index 4870643..f2b4722 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -47,7 +47,7 @@ pub enum WorkerResult { /// 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) { +pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> ExitCode { let mut path_iter = path_vec.iter(); let first_path_buf = path_iter .next() @@ -122,18 +122,20 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) { spawn_senders(&config, &wants_to_quit, pattern, parallel_walker, tx); // 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) { process::exit(ExitCode::KilledBySigint.into()); } + + exit_code } fn spawn_receiver( config: &Arc, wants_to_quit: &Arc, rx: Receiver, -) -> thread::JoinHandle<()> { +) -> thread::JoinHandle { let config = Arc::clone(config); 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. if let Some(ref cmd) = config.command { if cmd.in_batch_mode() { - exec::batch(rx, cmd, show_filesystem_errors); + exec::batch(rx, cmd, show_filesystem_errors) } else { let shared_rx = Arc::new(Mutex::new(rx)); @@ -169,6 +171,8 @@ fn spawn_receiver( for h in handles { h.join().unwrap(); } + + ExitCode::Success } } else { let start = time::Instant::now(); @@ -233,6 +237,8 @@ fn spawn_receiver( output::print_entry(&mut stdout, &value, &config, &wants_to_quit); } } + + ExitCode::Success } }) }