2017-10-14 18:04:11 +02:00
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::sync::mpsc::Receiver;
|
2018-04-13 22:46:17 +02:00
|
|
|
use std::sync::{Arc, Mutex};
|
2017-10-14 18:04:11 +02:00
|
|
|
|
2020-04-03 21:18:54 +02:00
|
|
|
use crate::error::print_error;
|
|
|
|
use crate::exit_codes::{merge_exitcodes, ExitCode};
|
|
|
|
use crate::walk::WorkerResult;
|
|
|
|
|
|
|
|
use super::CommandTemplate;
|
|
|
|
|
2017-10-14 18:04:11 +02:00
|
|
|
/// 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
|
|
|
|
/// be executed, and this process will continue until the receiver's sender has closed.
|
2018-09-30 22:56:32 +02:00
|
|
|
pub fn job(
|
|
|
|
rx: Arc<Mutex<Receiver<WorkerResult>>>,
|
|
|
|
cmd: Arc<CommandTemplate>,
|
|
|
|
out_perm: Arc<Mutex<()>>,
|
2018-10-22 14:20:08 +02:00
|
|
|
show_filesystem_errors: bool,
|
2021-08-09 09:02:30 +02:00
|
|
|
buffer_output: bool,
|
2020-01-25 17:13:47 +01:00
|
|
|
) -> ExitCode {
|
|
|
|
let mut results: Vec<ExitCode> = Vec::new();
|
2017-10-14 18:04:11 +02:00
|
|
|
loop {
|
|
|
|
// Create a lock on the shared receiver for this thread.
|
|
|
|
let lock = rx.lock().unwrap();
|
|
|
|
|
2018-10-01 21:29:54 +02:00
|
|
|
// Obtain the next result from the receiver, else if the channel
|
2017-10-14 18:04:11 +02:00
|
|
|
// has closed, exit from the loop
|
2017-10-14 22:42:47 +02:00
|
|
|
let value: PathBuf = match lock.recv() {
|
2018-10-01 21:29:54 +02:00
|
|
|
Ok(WorkerResult::Entry(val)) => val,
|
|
|
|
Ok(WorkerResult::Error(err)) => {
|
2018-10-22 14:20:08 +02:00
|
|
|
if show_filesystem_errors {
|
2020-04-03 21:18:54 +02:00
|
|
|
print_error(err.to_string());
|
2018-10-22 14:20:08 +02:00
|
|
|
}
|
2018-10-01 21:29:54 +02:00
|
|
|
continue;
|
|
|
|
}
|
2017-10-14 20:04:04 +02:00
|
|
|
Err(_) => break,
|
2017-10-14 18:04:11 +02:00
|
|
|
};
|
2021-08-09 09:02:30 +02:00
|
|
|
|
2020-01-25 17:13:47 +01:00
|
|
|
// Drop the lock so that other threads can read from the receiver.
|
2017-10-14 18:04:11 +02:00
|
|
|
drop(lock);
|
2020-01-26 14:06:18 +01:00
|
|
|
// Generate a command, execute it and store its exit code.
|
2021-08-09 09:02:30 +02:00
|
|
|
results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm), buffer_output))
|
2017-10-14 18:04:11 +02:00
|
|
|
}
|
2020-01-25 17:13:47 +01:00
|
|
|
// Returns error in case of any error.
|
2021-08-21 22:43:17 +02:00
|
|
|
merge_exitcodes(results)
|
2017-10-14 20:04:04 +02:00
|
|
|
}
|
2018-11-11 18:00:01 +01:00
|
|
|
|
2019-09-13 22:26:27 +02:00
|
|
|
pub fn batch(
|
|
|
|
rx: Receiver<WorkerResult>,
|
|
|
|
cmd: &CommandTemplate,
|
|
|
|
show_filesystem_errors: bool,
|
2021-08-09 09:02:30 +02:00
|
|
|
buffer_output: bool,
|
2021-10-22 08:05:13 +02:00
|
|
|
limit: usize,
|
2019-09-13 22:26:27 +02:00
|
|
|
) -> ExitCode {
|
2018-11-11 18:00:01 +01:00
|
|
|
let paths = rx.iter().filter_map(|value| match value {
|
|
|
|
WorkerResult::Entry(val) => Some(val),
|
|
|
|
WorkerResult::Error(err) => {
|
|
|
|
if show_filesystem_errors {
|
2020-04-03 21:18:54 +02:00
|
|
|
print_error(err.to_string());
|
2018-11-11 18:00:01 +01:00
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
2021-10-22 08:05:13 +02:00
|
|
|
if limit == 0 {
|
|
|
|
// no limit
|
|
|
|
return cmd.generate_and_execute_batch(paths, buffer_output);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut exit_codes = Vec::new();
|
|
|
|
let mut peekable = paths.peekable();
|
|
|
|
while peekable.peek().is_some() {
|
|
|
|
let limited = peekable.by_ref().take(limit);
|
|
|
|
let exit_code = cmd.generate_and_execute_batch(limited, buffer_output);
|
|
|
|
exit_codes.push(exit_code);
|
|
|
|
}
|
|
|
|
merge_exitcodes(exit_codes)
|
2018-11-11 18:00:01 +01:00
|
|
|
}
|