use std::io::{BufRead, BufReader}; use std::process::Command; use log::{info, trace}; pub struct Process { pub command: Vec, pub cwd: Option, pub env: Vec, } impl Process { pub fn new(command: Vec, cwd: Option, env: Vec) -> Process { Process { command, cwd, env } } pub fn command>(cmd: Vec) -> Process { Process::new(cmd.into_iter().map(|v| v.into()).collect(), None, vec![]) } pub fn spawn(&self) -> std::io::Result { trace!("Spawning process: {:?}", self.command); let mut child = Command::new(&self.command[0]) .args(&self.command[1..]) .current_dir(self.cwd.clone().unwrap_or(".".to_string())) .envs(self.env.iter().map(|v| { let mut split = v.split('='); ( split.next().unwrap().to_string(), split.next().unwrap().to_string(), ) })) .stdout(std::process::Stdio::piped()) .stderr(std::process::Stdio::piped()) .spawn()?; let stdout = child.stdout.take().unwrap(); let stderr = child.stderr.take().unwrap(); trace!("Processing lines from stdout and stderr"); for line in BufReader::new(stdout).lines() { info!(target: "command:stdout", "{}", line.unwrap()); } for line in BufReader::new(stderr).lines() { info!(target: "command:stderr", "{}", line.unwrap()); } trace!("End of process"); trace!("Returning child"); Ok(child) } } impl Default for Process { fn default() -> Process { Process::new(vec![], None, vec![]) } }