use std::{
ffi::OsStr,
io,
path::Path,
process::{Command as StdCommand, ExitStatus, Output, Stdio},
};
use crate::process::child::Child;
pub type StdioConfig = std::process::Stdio;
pub struct Command {
inner: StdCommand,
stdin_set: bool,
stdout_set: bool,
stderr_set: bool,
kill_on_drop: bool,
}
impl Command {
pub fn new(program: impl AsRef<OsStr>) -> Command {
Command {
inner: StdCommand::new(program),
stdin_set: false,
stdout_set: false,
stderr_set: false,
kill_on_drop: false,
}
}
pub fn arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
self.inner.arg(arg);
self
}
pub fn args<I, S>(&mut self, args: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
self.inner.args(args);
self
}
pub fn env(&mut self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut Self {
self.inner.env(key, value);
self
}
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
self.inner.envs(vars);
self
}
pub fn env_remove(&mut self, key: impl AsRef<OsStr>) -> &mut Self {
self.inner.env_remove(key);
self
}
pub fn env_clear(&mut self) -> &mut Self {
self.inner.env_clear();
self
}
pub fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self {
self.inner.current_dir(dir);
self
}
pub fn stdin(&mut self, cfg: StdioConfig) -> &mut Self {
self.stdin_set = true;
self.inner.stdin(cfg);
self
}
pub fn stdout(&mut self, cfg: StdioConfig) -> &mut Self {
self.stdout_set = true;
self.inner.stdout(cfg);
self
}
pub fn stderr(&mut self, cfg: StdioConfig) -> &mut Self {
self.stderr_set = true;
self.inner.stderr(cfg);
self
}
pub fn kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Self {
self.kill_on_drop = kill_on_drop;
self
}
pub fn spawn(&mut self) -> io::Result<Child> {
Child::spawn(&mut self.inner, self.kill_on_drop)
}
pub async fn status(&mut self) -> io::Result<ExitStatus> {
self.spawn()?.wait().await
}
pub async fn output(&mut self) -> io::Result<Output> {
if !self.stdout_set {
self.inner.stdout(Stdio::piped());
self.stdout_set = true;
}
if !self.stderr_set {
self.inner.stderr(Stdio::piped());
self.stderr_set = true;
}
if !self.stdin_set {
self.inner.stdin(Stdio::null());
}
self.spawn()?.wait_with_output().await
}
}