1use std::{ffi::OsStr, io::{self, BufRead}, process::{Child, Command, Stdio}};
2
3use anyhow::{anyhow, Result};
4
5pub fn output<I, S>(args: I) -> Result<String>
17where
18 I: IntoIterator<Item = S>,
19 S: AsRef<OsStr>,
20{
21 let args: Vec<S> = args.into_iter().collect();
22 let output = Command::new(&args[0])
23 .args(&args[1..])
24 .output()?;
25
26 let outerr = String::from_utf8_lossy(&output.stderr);
27 if !outerr.is_empty() {
28 if let Some(e) = outerr.strip_suffix("\n") {
29 return Err(anyhow!("{e}"));
30 } else {
31 return Err(anyhow!("{outerr}"));
32 }
33 }
34 let out = String::from_utf8_lossy(&output.stdout);
35 if let Some(o) = out.strip_suffix("\n") {
36 return Ok(o.to_string());
37 }
38 Ok(out.to_string())
39}
40
41
42pub fn spawn<I, S>(args: I) -> Result<Vec<String>>
52where
53 I: IntoIterator<Item = S>,
54 S: AsRef<OsStr>,
55{
56 let args: Vec<S> = args.into_iter().collect();
57 let mut child: Child = Command::new(&args[0])
58 .args(&args[1..])
59 .stdout(Stdio::piped()) .spawn()?; let stdout = child.stdout.take().ok_or_else(|| anyhow!("Could not capture standard output"))?;
64
65 let reader = io::BufReader::new(stdout);
67
68 let mut result = Vec::new();
70 for line in reader.lines() {
71 let line = line?;
72 println!("{}", line);
73 result.push(line);
74 }
75
76 let _ = child.wait()?;
78 Ok(result)
79}
80