2019-06-04 18:08:26 +00:00
|
|
|
use super::*;
|
|
|
|
use std::io::Write;
|
|
|
|
use std::process::Command;
|
|
|
|
use std::process::Stdio;
|
2019-06-05 19:28:35 +00:00
|
|
|
use failure::*;
|
2019-06-04 18:08:26 +00:00
|
|
|
|
|
|
|
pub trait SpawningFileAdapter: GetMetadata {
|
2019-06-05 19:28:35 +00:00
|
|
|
fn get_exe(&self) -> &str;
|
|
|
|
fn command(&self, inp_fname: &Path, command: Command) -> Command;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn map_exe_error(err: std::io::Error, exe_name: &str, help: &str) -> Error {
|
|
|
|
use std::io::ErrorKind::*;
|
|
|
|
match err.kind() {
|
|
|
|
NotFound => format_err!("Could not find executable \"{}\". {}", exe_name, help),
|
|
|
|
_ => Error::from(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pipe_output(mut cmd: Command, oup: &mut dyn Write, exe_name: &str, help: &str) -> Fallible<()> {
|
|
|
|
let mut cmd = cmd.stdout(Stdio::piped()).spawn().map_err(|e| map_exe_error(e, exe_name, help))?;
|
|
|
|
let stdo = cmd.stdout.as_mut().expect("is piped");
|
|
|
|
std::io::copy(stdo, oup)?;
|
|
|
|
let status = cmd.wait()?;
|
|
|
|
if status.success() {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(format_err!("subprocess failed: {:?}", status))
|
|
|
|
}
|
2019-06-04 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> FileAdapter for T
|
2019-06-05 19:28:35 +00:00
|
|
|
where
|
|
|
|
T: SpawningFileAdapter,
|
2019-06-04 18:08:26 +00:00
|
|
|
{
|
2019-06-05 19:28:35 +00:00
|
|
|
fn adapt(&self, inp_fname: &Path, oup: &mut dyn Write) -> Fallible<()> {
|
|
|
|
let cmd = Command::new(self.get_exe());
|
|
|
|
pipe_output(self.command(inp_fname, cmd), oup, self.get_exe(), "")
|
2019-06-04 18:08:26 +00:00
|
|
|
}
|
|
|
|
}
|