use std::process::{Child, Command, Stdio};
use super::output::sanitize;
use super::{ProcessError, ProcessSpec};
pub(crate) fn spawn(spec: &ProcessSpec) -> Result<Child, ProcessError> {
let mut command = Command::new(spec.program());
command
.args(spec.arguments())
.current_dir(spec.directory())
.envs(spec.environment().iter().cloned())
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit());
#[cfg(windows)]
if spec.new_process_group_enabled() {
use std::os::windows::process::CommandExt;
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
command.creation_flags(CREATE_NEW_PROCESS_GROUP);
}
command.spawn().map_err(|source| ProcessError::Spawn {
program: spec.program().to_string_lossy().into_owned(),
directory: spec.directory().to_path_buf(),
source,
})
}
pub(crate) fn run(spec: &ProcessSpec) -> Result<(), ProcessError> {
let mut child = spawn(spec)?;
let status = child.wait().map_err(|source| ProcessError::Wait {
program: spec.program().to_string_lossy().into_owned(),
source,
})?;
if status.success() {
Ok(())
} else {
Err(ProcessError::Failed {
program: spec.program().to_string_lossy().into_owned(),
directory: spec.directory().to_path_buf(),
status,
})
}
}
pub(crate) fn run_quiet(spec: &ProcessSpec) -> Result<(), ProcessError> {
let output = Command::new(spec.program())
.args(spec.arguments())
.current_dir(spec.directory())
.envs(spec.environment().iter().cloned())
.stdin(Stdio::null())
.output()
.map_err(|source| ProcessError::Spawn {
program: spec.program().to_string_lossy().into_owned(),
directory: spec.directory().to_path_buf(),
source,
})?;
if output.status.success() {
Ok(())
} else {
let bytes = if output.stderr.is_empty() {
&output.stdout
} else {
&output.stderr
};
Err(ProcessError::FailedOutput {
program: spec.program().to_string_lossy().into_owned(),
directory: spec.directory().to_path_buf(),
status: output.status,
output: sanitize(bytes),
})
}
}
pub(crate) fn run_capture(spec: &ProcessSpec) -> Result<Vec<u8>, ProcessError> {
let output = Command::new(spec.program())
.args(spec.arguments())
.current_dir(spec.directory())
.envs(spec.environment().iter().cloned())
.stdin(Stdio::null())
.output()
.map_err(|source| ProcessError::Spawn {
program: spec.program().to_string_lossy().into_owned(),
directory: spec.directory().to_path_buf(),
source,
})?;
if output.status.success() {
Ok(output.stdout)
} else {
let bytes = if output.stderr.is_empty() {
&output.stdout
} else {
&output.stderr
};
Err(ProcessError::FailedOutput {
program: spec.program().to_string_lossy().into_owned(),
directory: spec.directory().to_path_buf(),
status: output.status,
output: sanitize(bytes),
})
}
}