use crate::functions::output_and_write_streams;
use crate::{CmdError, NamedOutput, OutputWithName};
use std::io::Write;
use std::process::Command;
pub trait CommandWithName {
fn name(&mut self) -> String;
fn mut_cmd(&mut self) -> &mut Command;
fn named(&mut self, s: impl AsRef<str>) -> NamedCommand<'_> {
let name = s.as_ref().to_string();
let command = self.mut_cmd();
NamedCommand { name, command }
}
#[allow(clippy::needless_lifetimes)]
fn named_fn<'a>(&'a mut self, f: impl FnOnce(&mut Command) -> String) -> NamedCommand<'a> {
let cmd = self.mut_cmd();
let name = f(cmd);
self.named(name)
}
#[cfg(command_resolved_envs)]
#[allow(clippy::needless_lifetimes)]
#[must_use]
fn named_env_vars<'a, T, K>(&'a mut self, keys: T) -> NamedCommand<'a>
where
T: IntoIterator<Item = K>,
K: Into<std::ffi::OsString>,
{
use crate::functions::display_name_with_env_keys;
use std::collections::HashMap;
use std::ffi::OsString;
let old = self.name();
let cmd = self.mut_cmd();
let name = display_name_with_env_keys(
old,
cmd.get_resolved_envs()
.collect::<HashMap<OsString, OsString>>(),
keys,
);
self.named(name)
}
fn named_output(&mut self) -> Result<NamedOutput, CmdError> {
let name = self.name();
self.mut_cmd()
.output()
.map_err(|io_error| CmdError::SystemError(name.clone(), io_error))
.map(|output| output.named(name.clone()))
.and_then(NamedOutput::nonzero_captured)
}
fn stream_output<OW, EW>(
&mut self,
stdout_write: OW,
stderr_write: EW,
) -> Result<NamedOutput, CmdError>
where
OW: Write + Send,
EW: Write + Send,
{
let name = &self.name();
let cmd = self.mut_cmd();
output_and_write_streams(cmd, stdout_write, stderr_write)
.map_err(|io_error| CmdError::SystemError(name.clone(), io_error))
.map(|output| output.named(name.clone()))
.and_then(NamedOutput::nonzero_streamed)
}
}
impl CommandWithName for Command {
fn name(&mut self) -> String {
crate::display(self)
}
fn mut_cmd(&mut self) -> &mut Command {
self
}
}
impl CommandWithName for &mut Command {
fn name(&mut self) -> String {
crate::display(self)
}
fn mut_cmd(&mut self) -> &mut Command {
self
}
}
pub struct NamedCommand<'a> {
name: String,
command: &'a mut Command,
}
impl<'a> From<&'a mut Command> for NamedCommand<'a> {
fn from(command: &'a mut Command) -> Self {
NamedCommand {
name: command.name(),
command,
}
}
}
impl CommandWithName for NamedCommand<'_> {
fn name(&mut self) -> String {
self.name.to_string()
}
fn mut_cmd(&mut self) -> &mut Command {
self.command
}
}
impl CommandWithName for &mut NamedCommand<'_> {
fn name(&mut self) -> String {
self.name.to_string()
}
fn mut_cmd(&mut self) -> &mut Command {
self.command
}
}