From a4e81a4e5aa47c360e9f5f0d78021163bcfe84b1 Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sat, 25 Jan 2020 15:54:56 +0100 Subject: [PATCH 1/8] Restun exit code for generate_and_execute? --- src/exec/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 8554f28c4..091e989b5 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -146,7 +146,7 @@ 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>) { + pub fn generate_and_execute(&self, input: &Path, out_perm: Arc>) -> ExitCode { let input = Self::prepare_path(input); let mut cmd = Command::new(self.args[0].generate(&input).as_ref()); @@ -154,7 +154,7 @@ 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 { From 3b660288943eb9f7e06f5aa0cd3675a5334a7741 Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sat, 25 Jan 2020 17:13:47 +0100 Subject: [PATCH 2/8] Add collection of job & thread exit codes + default to ExitCode::Error if any ExitCode::Error --- src/exec/job.rs | 11 +++++++---- src/exit_codes.rs | 18 +++++++++++++++--- src/walk.rs | 5 +++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/exec/job.rs b/src/exec/job.rs index 270723844..017b8efdb 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -21,7 +21,8 @@ pub fn job( cmd: Arc, out_perm: Arc>, show_filesystem_errors: bool, -) { +) -> ExitCode { + let mut results: Vec = Vec::new(); loop { // Create a lock on the shared receiver for this thread. let lock = rx.lock().unwrap(); @@ -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, executes it and store its exit code. + results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm))) } + // Returns error in case of any error. + ExitCode::error_if_any_error(results) } pub fn batch( diff --git a/src/exit_codes.rs b/src/exit_codes.rs index 026562707..6905f478e 100644 --- a/src/exit_codes.rs +++ b/src/exit_codes.rs @@ -7,9 +7,21 @@ pub enum ExitCode { impl Into for ExitCode { fn into(self) -> i32 { match self { - ExitCode::Success => 0, - ExitCode::GeneralError => 1, - ExitCode::KilledBySigint => 130, + Self::Success => 0, + Self::GeneralError => 1, + Self::KilledBySigint => 130, } } } + +impl ExitCode { + pub fn error_if_any_error(results: Vec) -> Self { + if results.iter().any(|s| match s { + Self::GeneralError => true, + _ => false, + }) { + return Self::GeneralError; + } + Self::Success + } +} diff --git a/src/walk.rs b/src/walk.rs index 77ec7c979..e0716be21 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -177,11 +177,12 @@ fn spawn_receiver( } // Wait for all threads to exit before exiting the program. + let mut results: Vec = Vec::new(); for h in handles { - h.join().unwrap(); + results.push(h.join().unwrap()); } - ExitCode::Success + ExitCode::error_if_any_error(results) } } else { let start = time::Instant::now(); From 4ec16a4c706762dec9d5273c88fe9e00046d9f47 Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sun, 26 Jan 2020 14:06:18 +0100 Subject: [PATCH 3/8] Fix typo in a job.rs comment --- src/exec/job.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exec/job.rs b/src/exec/job.rs index 017b8efdb..67d301c3f 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -42,7 +42,7 @@ pub fn job( // Drop the lock so that other threads can read from the receiver. drop(lock); - // Generate a command, executes it and store its exit code. + // 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. From 0ef6eccb96abf6a183c693699a36232fe4688998 Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sat, 22 Feb 2020 08:55:32 +0100 Subject: [PATCH 4/8] Switch back from Self to ExitCode --- src/exit_codes.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/exit_codes.rs b/src/exit_codes.rs index 6905f478e..ec238d8d4 100644 --- a/src/exit_codes.rs +++ b/src/exit_codes.rs @@ -7,9 +7,9 @@ pub enum ExitCode { impl Into for ExitCode { fn into(self) -> i32 { match self { - Self::Success => 0, - Self::GeneralError => 1, - Self::KilledBySigint => 130, + ExitCode::Success => 0, + ExitCode::GeneralError => 1, + ExitCode::KilledBySigint => 130, } } } @@ -17,11 +17,11 @@ impl Into for ExitCode { impl ExitCode { pub fn error_if_any_error(results: Vec) -> Self { if results.iter().any(|s| match s { - Self::GeneralError => true, + ExitCode::GeneralError => true, _ => false, }) { - return Self::GeneralError; + return ExitCode::GeneralError; } - Self::Success + ExitCode::Success } } From ad6bce8d27611419a161abd6add0656ac7bb08a2 Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sat, 22 Feb 2020 09:01:52 +0100 Subject: [PATCH 5/8] Extract ExitCode::is_error helper --- src/exit_codes.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/exit_codes.rs b/src/exit_codes.rs index ec238d8d4..19a252e64 100644 --- a/src/exit_codes.rs +++ b/src/exit_codes.rs @@ -16,12 +16,16 @@ impl Into for ExitCode { impl ExitCode { pub fn error_if_any_error(results: Vec) -> Self { - if results.iter().any(|s| match s { - ExitCode::GeneralError => true, - _ => false, - }) { + if results.iter().any(ExitCode::is_error) { return ExitCode::GeneralError; } ExitCode::Success } + + fn is_error(&self) -> bool { + match self { + ExitCode::GeneralError | ExitCode::KilledBySigint => true, + _ => false, + } + } } From 138e95648836b7d962cb633a205045373cf3a651 Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sat, 22 Feb 2020 09:08:07 +0100 Subject: [PATCH 6/8] Extract error_if_any_error as free function --- src/exec/job.rs | 4 ++-- src/exit_codes.rs | 14 +++++++------- src/walk.rs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/exec/job.rs b/src/exec/job.rs index 67d301c3f..7e6ce8e76 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -7,7 +7,7 @@ // according to those terms. use super::CommandTemplate; -use crate::exit_codes::ExitCode; +use crate::exit_codes::{ExitCode, error_if_any_error}; use crate::walk::WorkerResult; use std::path::PathBuf; use std::sync::mpsc::Receiver; @@ -46,7 +46,7 @@ pub fn job( results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm))) } // Returns error in case of any error. - ExitCode::error_if_any_error(results) + error_if_any_error(results) } pub fn batch( diff --git a/src/exit_codes.rs b/src/exit_codes.rs index 19a252e64..731de1de3 100644 --- a/src/exit_codes.rs +++ b/src/exit_codes.rs @@ -15,13 +15,6 @@ impl Into for ExitCode { } impl ExitCode { - pub fn error_if_any_error(results: Vec) -> Self { - if results.iter().any(ExitCode::is_error) { - return ExitCode::GeneralError; - } - ExitCode::Success - } - fn is_error(&self) -> bool { match self { ExitCode::GeneralError | ExitCode::KilledBySigint => true, @@ -29,3 +22,10 @@ impl ExitCode { } } } + +pub fn error_if_any_error(results: Vec) -> ExitCode { + if results.iter().any(ExitCode::is_error) { + return ExitCode::GeneralError; + } + ExitCode::Success +} diff --git a/src/walk.rs b/src/walk.rs index e0716be21..12c22907b 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -7,7 +7,7 @@ // according to those terms. use crate::exec; -use crate::exit_codes::ExitCode; +use crate::exit_codes::{ExitCode, error_if_any_error}; use crate::fshelper; use crate::internal::{opts::FdOptions, osstr_to_bytes, MAX_BUFFER_LENGTH}; use crate::output; @@ -182,7 +182,7 @@ fn spawn_receiver( results.push(h.join().unwrap()); } - ExitCode::error_if_any_error(results) + error_if_any_error(results) } } else { let start = time::Instant::now(); From 3133a4e37b0b87f3205a0cdc9b0e4af71f1e56f6 Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sat, 22 Feb 2020 09:08:56 +0100 Subject: [PATCH 7/8] Rename error_if_any_error to merge_exitcodes --- src/exec/job.rs | 4 ++-- src/exit_codes.rs | 2 +- src/walk.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/exec/job.rs b/src/exec/job.rs index 7e6ce8e76..d37899b67 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -7,7 +7,7 @@ // according to those terms. use super::CommandTemplate; -use crate::exit_codes::{ExitCode, error_if_any_error}; +use crate::exit_codes::{ExitCode, merge_exitcodes}; use crate::walk::WorkerResult; use std::path::PathBuf; use std::sync::mpsc::Receiver; @@ -46,7 +46,7 @@ pub fn job( results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm))) } // Returns error in case of any error. - error_if_any_error(results) + merge_exitcodes(results) } pub fn batch( diff --git a/src/exit_codes.rs b/src/exit_codes.rs index 731de1de3..c2aaacff8 100644 --- a/src/exit_codes.rs +++ b/src/exit_codes.rs @@ -23,7 +23,7 @@ impl ExitCode { } } -pub fn error_if_any_error(results: Vec) -> ExitCode { +pub fn merge_exitcodes(results: Vec) -> ExitCode { if results.iter().any(ExitCode::is_error) { return ExitCode::GeneralError; } diff --git a/src/walk.rs b/src/walk.rs index 12c22907b..ea9e76d70 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -7,7 +7,7 @@ // according to those terms. use crate::exec; -use crate::exit_codes::{ExitCode, error_if_any_error}; +use crate::exit_codes::{ExitCode, merge_exitcodes}; use crate::fshelper; use crate::internal::{opts::FdOptions, osstr_to_bytes, MAX_BUFFER_LENGTH}; use crate::output; @@ -182,7 +182,7 @@ fn spawn_receiver( results.push(h.join().unwrap()); } - error_if_any_error(results) + merge_exitcodes(results) } } else { let start = time::Instant::now(); From 85ce9d98ede2b82b6c7e44fdcd46aa44fbd3e9fd Mon Sep 17 00:00:00 2001 From: fusillicode Date: Sat, 22 Feb 2020 10:39:03 +0100 Subject: [PATCH 8/8] Add unit tests for merge_exitcodes --- src/exec/job.rs | 2 +- src/exit_codes.rs | 28 ++++++++++++++++++++++++++++ src/walk.rs | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/exec/job.rs b/src/exec/job.rs index d37899b67..c3c8254fe 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -7,7 +7,7 @@ // according to those terms. use super::CommandTemplate; -use crate::exit_codes::{ExitCode, merge_exitcodes}; +use crate::exit_codes::{merge_exitcodes, ExitCode}; use crate::walk::WorkerResult; use std::path::PathBuf; use std::sync::mpsc::Receiver; diff --git a/src/exit_codes.rs b/src/exit_codes.rs index c2aaacff8..c0be96bec 100644 --- a/src/exit_codes.rs +++ b/src/exit_codes.rs @@ -1,3 +1,4 @@ +#[derive(PartialEq, Debug)] pub enum ExitCode { Success, GeneralError, @@ -29,3 +30,30 @@ pub fn merge_exitcodes(results: Vec) -> ExitCode { } 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); + } +} diff --git a/src/walk.rs b/src/walk.rs index ea9e76d70..b3190e0d4 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -7,7 +7,7 @@ // according to those terms. use crate::exec; -use crate::exit_codes::{ExitCode, merge_exitcodes}; +use crate::exit_codes::{merge_exitcodes, ExitCode}; use crate::fshelper; use crate::internal::{opts::FdOptions, osstr_to_bytes, MAX_BUFFER_LENGTH}; use crate::output;