mirror of
https://github.com/sharkdp/fd.git
synced 2024-11-19 02:10:34 +01:00
Group outputs from exec
This commit is contained in:
parent
718f723d31
commit
1bc58b2fbb
4 changed files with 35 additions and 10 deletions
|
@ -11,6 +11,7 @@ pub fn job(
|
|||
rx: Arc<Mutex<Receiver<PathBuf>>>,
|
||||
base: Arc<Option<PathBuf>>,
|
||||
cmd: Arc<TokenizedCommand>,
|
||||
out_perm: Arc<Mutex<()>>,
|
||||
) {
|
||||
// A string buffer that will be re-used in each iteration.
|
||||
let buffer = &mut String::with_capacity(256);
|
||||
|
@ -35,6 +36,7 @@ pub fn job(
|
|||
drop(lock);
|
||||
// Generate a command to store within the buffer, and execute the command.
|
||||
// Note that the `then_execute()` method will clear the buffer for us.
|
||||
cmd.generate(buffer, &value).then_execute();
|
||||
cmd.generate(buffer, &value, out_perm.clone())
|
||||
.then_execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ mod job;
|
|||
mod paths;
|
||||
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use self::paths::{basename, dirname, remove_extension};
|
||||
use self::ticket::CommandTicket;
|
||||
|
@ -102,7 +103,12 @@ impl TokenizedCommand {
|
|||
/// written into the `command` buffer. Once all tokens have been processed, the mutable
|
||||
/// reference of the `command` will be wrapped within a `CommandTicket`, which will be
|
||||
/// responsible for executing the command and clearing the buffer.
|
||||
pub fn generate<'a>(&self, command: &'a mut String, input: &Path) -> CommandTicket<'a> {
|
||||
pub fn generate<'a>(
|
||||
&self,
|
||||
command: &'a mut String,
|
||||
input: &Path,
|
||||
out_perm: Arc<Mutex<()>>,
|
||||
) -> CommandTicket<'a> {
|
||||
for token in &self.tokens {
|
||||
match *token {
|
||||
Token::Basename => *command += basename(&input.to_string_lossy()),
|
||||
|
@ -116,7 +122,7 @@ impl TokenizedCommand {
|
|||
}
|
||||
}
|
||||
|
||||
CommandTicket::new(command)
|
||||
CommandTicket::new(command, out_perm)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::io::{self, Write};
|
||||
|
||||
lazy_static! {
|
||||
/// On non-Windows systems, the `SHELL` environment variable will be used to determine the
|
||||
|
@ -18,11 +20,12 @@ lazy_static! {
|
|||
/// cleared so that a new command can be written to the string in the future.
|
||||
pub struct CommandTicket<'a> {
|
||||
command: &'a mut String,
|
||||
out_perm: Arc<Mutex<()>>,
|
||||
}
|
||||
|
||||
impl<'a> CommandTicket<'a> {
|
||||
pub fn new(command: &'a mut String) -> CommandTicket<'a> {
|
||||
CommandTicket { command }
|
||||
pub fn new(command: &'a mut String, out_perm: Arc<Mutex<()>>) -> CommandTicket<'a> {
|
||||
CommandTicket { command, out_perm }
|
||||
}
|
||||
|
||||
/// Executes the command stored within the ticket, and
|
||||
|
@ -32,12 +35,22 @@ impl<'a> CommandTicket<'a> {
|
|||
let cmd = Command::new(COMMAND.0.as_str())
|
||||
.arg(COMMAND.1)
|
||||
.arg(&self.command)
|
||||
.spawn();
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.output();
|
||||
|
||||
// Then wait for the command to exit, if it was spawned.
|
||||
match cmd {
|
||||
Ok(mut child) => {
|
||||
let _ = child.wait();
|
||||
Ok(output) => {
|
||||
// While this lock is active, this thread will be the only thread allowed
|
||||
// to write it's outputs.
|
||||
let _lock = self.out_perm.lock().unwrap();
|
||||
|
||||
let stdout = io::stdout();
|
||||
let stderr = io::stderr();
|
||||
|
||||
let _ = stdout.lock().write_all(&output.stdout);
|
||||
let _ = stderr.lock().write_all(&output.stderr);
|
||||
}
|
||||
Err(why) => eprintln!("fd: exec error: {}", why),
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ pub fn scan(root: &Path, pattern: Arc<Regex>, base: &Path, config: Arc<FdOptions
|
|||
// This will be set to `Some` if the `--exec` argument was supplied.
|
||||
if let Some(ref cmd) = rx_config.command {
|
||||
let shared_rx = Arc::new(Mutex::new(rx));
|
||||
|
||||
let out_perm = Arc::new(Mutex::new(()));
|
||||
|
||||
let base = Arc::new(if is_absolute { Some(rx_base) } else { None });
|
||||
|
||||
// This is safe because `cmd` will exist beyond the end of this scope.
|
||||
|
@ -72,9 +75,10 @@ pub fn scan(root: &Path, pattern: Arc<Regex>, base: &Path, config: Arc<FdOptions
|
|||
let rx = shared_rx.clone();
|
||||
let cmd = cmd.clone();
|
||||
let base = base.clone();
|
||||
let out_perm = out_perm.clone();
|
||||
|
||||
// Spawn a job thread that will listen for and execute inputs.
|
||||
let handle = thread::spawn(move || exec::job(rx, base, cmd));
|
||||
let handle = thread::spawn(move || exec::job(rx, base, cmd, out_perm));
|
||||
|
||||
// Push the handle of the spawned thread into the vector for later joining.
|
||||
handles.push(handle);
|
||||
|
|
Loading…
Reference in a new issue