Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fd --exec should fail if one of --exec fails #526 #531

Merged
merged 8 commits into from
Feb 22, 2020
13 changes: 8 additions & 5 deletions src/exec/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// according to those terms.

use super::CommandTemplate;
use crate::exit_codes::ExitCode;
use crate::exit_codes::{merge_exitcodes, ExitCode};
use crate::walk::WorkerResult;
use std::path::PathBuf;
use std::sync::mpsc::Receiver;
Expand All @@ -21,7 +21,8 @@ pub fn job(
cmd: Arc<CommandTemplate>,
out_perm: Arc<Mutex<()>>,
show_filesystem_errors: bool,
) {
) -> ExitCode {
let mut results: Vec<ExitCode> = Vec::new();
loop {
// Create a lock on the shared receiver for this thread.
let lock = rx.lock().unwrap();
Expand All @@ -39,11 +40,13 @@ pub fn job(
Err(_) => break,
};

// Drop the lock so that other threads can read from the the receiver.
// Drop the lock so that other threads can read from the receiver.
drop(lock);
// Generate a command and execute it.
cmd.generate_and_execute(&value, Arc::clone(&out_perm));
// Generate a command, execute it and store its exit code.
results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm)))
}
// Returns error in case of any error.
merge_exitcodes(results)
}

pub fn batch(
Expand Down
4 changes: 2 additions & 2 deletions src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,15 @@ impl CommandTemplate {
///
/// Using the internal `args` field, and a supplied `input` variable, a `Command` will be
/// build. Once all arguments have been processed, the command is executed.
pub fn generate_and_execute(&self, input: &Path, out_perm: Arc<Mutex<()>>) {
pub fn generate_and_execute(&self, input: &Path, out_perm: Arc<Mutex<()>>) -> ExitCode {
let input = Self::prepare_path(input);

let mut cmd = Command::new(self.args[0].generate(&input).as_ref());
for arg in &self.args[1..] {
cmd.arg(arg.generate(&input).as_ref());
}

execute_command(cmd, &out_perm);
execute_command(cmd, &out_perm)
}

pub fn in_batch_mode(&self) -> bool {
Expand Down
44 changes: 44 additions & 0 deletions src/exit_codes.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[derive(PartialEq, Debug)]
pub enum ExitCode {
Success,
GeneralError,
Expand All @@ -13,3 +14,46 @@ impl Into<i32> for ExitCode {
}
}
}

impl ExitCode {
fn is_error(&self) -> bool {
match self {
ExitCode::GeneralError | ExitCode::KilledBySigint => true,
_ => false,
sharkdp marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

pub fn merge_exitcodes(results: Vec<ExitCode>) -> ExitCode {
if results.iter().any(ExitCode::is_error) {
return ExitCode::GeneralError;
}
ExitCode::Success
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn success_with_empty_vec() {
assert_eq!(merge_exitcodes(vec![]), ExitCode::Success);
}

#[test]
fn general_error_with_at_least_a_matching_error() {
assert_eq!(
merge_exitcodes(vec![ExitCode::KilledBySigint, ExitCode::Success]),
ExitCode::GeneralError
);
assert_eq!(
merge_exitcodes(vec![ExitCode::GeneralError, ExitCode::Success]),
ExitCode::GeneralError
);
}

#[test]
fn success_with_no_error() {
assert_eq!(merge_exitcodes(vec![ExitCode::Success]), ExitCode::Success);
}
}
7 changes: 4 additions & 3 deletions src/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// according to those terms.

use crate::exec;
use crate::exit_codes::ExitCode;
use crate::exit_codes::{merge_exitcodes, ExitCode};
use crate::fshelper;
use crate::internal::{opts::FdOptions, osstr_to_bytes, MAX_BUFFER_LENGTH};
use crate::output;
Expand Down Expand Up @@ -177,11 +177,12 @@ fn spawn_receiver(
}

// Wait for all threads to exit before exiting the program.
let mut results: Vec<ExitCode> = Vec::new();
for h in handles {
h.join().unwrap();
results.push(h.join().unwrap());
}

ExitCode::Success
merge_exitcodes(results)
}
} else {
let start = time::Instant::now();
Expand Down