use std::io::Write;
use std::io;
use std::process;
use assert::Assert;
use assert::OutputAssertExt;
use errors::OutputError;
use errors::OutputResult;
use cmd::OutputOkExt;
use cmd::dump_buffer;
pub trait CommandStdInExt {
fn with_stdin<S>(self, buffer: S) -> StdInCommand
where
S: Into<Vec<u8>>;
}
impl CommandStdInExt for process::Command {
fn with_stdin<S>(self, buffer: S) -> StdInCommand
where
S: Into<Vec<u8>>,
{
StdInCommand {
cmd: self,
stdin: buffer.into(),
}
}
}
#[derive(Debug)]
pub struct StdInCommand {
cmd: process::Command,
stdin: Vec<u8>,
}
impl StdInCommand {
pub fn output(&mut self) -> io::Result<process::Output> {
self.spawn()?.wait_with_output()
}
fn spawn(&mut self) -> io::Result<process::Child> {
self.cmd.stdin(process::Stdio::piped());
self.cmd.stdout(process::Stdio::piped());
self.cmd.stderr(process::Stdio::piped());
let mut spawned = self.cmd.spawn()?;
spawned
.stdin
.as_mut()
.expect("Couldn't get mut ref to command stdin")
.write_all(&self.stdin)?;
Ok(spawned)
}
}
impl<'c> OutputOkExt for &'c mut StdInCommand {
fn ok(self) -> OutputResult {
let output = self.output().map_err(OutputError::with_cause)?;
if output.status.success() {
Ok(output)
} else {
let error = OutputError::new(output)
.set_cmd(format!("{:?}", self.cmd))
.set_stdin(self.stdin.clone());
Err(error)
}
}
fn unwrap_err(self) -> OutputError {
match self.ok() {
Ok(output) => panic!(
"Completed successfully:\ncommand=`{:?}`\nstdin=```{}```\nstdout=```{}```",
self.cmd,
dump_buffer(&self.stdin),
dump_buffer(&output.stdout)
),
Err(err) => err,
}
}
}
impl<'c> OutputAssertExt for &'c mut StdInCommand {
fn assert(self) -> Assert {
let output = self.output().unwrap();
Assert::new(output)
.set_cmd(format!("{:?}", self.cmd))
.set_stdin(self.stdin.clone())
}
}