1use crate::Verbosity;
5use colored::Colorize;
6use std::io::Write;
7use std::process::{Command, Output, Stdio};
8use std::{io, process};
9
10pub fn cmd_call_to_string(bin: &str, args: &[&str]) -> String {
15 format!(
16 "{} {}",
17 bin,
18 args.iter()
19 .map(|s| {
20 if s.contains(' ') {
21 format!("\"{s}\"")
23 } else {
24 s.to_string()
25 }
26 })
27 .collect::<Vec<_>>()
28 .join(" ")
29 )
30}
31
32pub fn cmd_call(
33 bin: &str,
34 args: &[&str],
35 output_stdout: bool,
36 output_stderr: bool,
37 verbosity: &Verbosity,
38) -> io::Result<Output> {
39 if matches!(verbosity, Verbosity::Verbose) {
40 eprintln!("{}: {}", "DEBUG".green(), cmd_call_to_string(bin, args));
41 }
42 let mut binding = Command::new(bin);
43 let mut command = binding.args(args);
44 command = command.stdout(Stdio::piped()).stderr(Stdio::piped());
45 let output = command.output()?; if output_stdout {
47 cmd_write_stdout(bin, &output.stdout);
48 }
49 if output_stderr {
50 cmd_write_stderr(bin, &output.stderr);
51 }
52 Ok(output)
53}
54
55pub fn cmd_write_stderr(bin: &str, stderr: &[u8]) {
56 io::stderr().write_all(stderr).unwrap_or_else(|e| {
57 eprintln!("{}: writing {} stderr: {}", "ERROR".red(), bin, e);
58 process::exit(151);
59 });
60}
61
62pub fn cmd_write_stdout(bin: &str, stdout: &[u8]) {
63 io::stdout().write_all(stdout).unwrap_or_else(|e| {
64 eprintln!("{}: writing {} stdout: {}", "ERROR".red(), bin, e);
65 process::exit(151);
66 });
67}
68
69pub fn cmd_exit_code(bin: &str, output: &Output) -> i32 {
70 output.status.code().unwrap_or_else(|| {
71 eprintln!("{}: {} process terminated by signal", "ERROR".red(), bin);
72 process::exit(10)
73 })
74}
75
76pub fn cmd_get_success_output_or_fail(
81 bin: &str,
82 bin_cmd: &str,
83 output: Output,
84 quiet: bool,
85) -> String {
86 match output.status.success() {
87 true => {
88 if !quiet && !output.stderr.is_empty() {
90 eprintln!(
92 "{}: the following are warnings from {}:",
93 "WARN".yellow(),
94 bin_cmd
95 );
96 cmd_write_stderr(bin, &output.stderr);
97 }
98 String::from_utf8(output.stdout).unwrap_or_else(|e| {
99 eprintln!(
100 "{}: deserializing {} {} output: {}",
101 "ERROR".red(),
102 bin,
103 bin_cmd,
104 e,
105 );
106 process::exit(17);
107 })
108 }
109 false => {
110 eprintln!("{}: calling {}", "ERROR".red(), bin_cmd);
111 cmd_write_stderr(bin, &output.stderr);
112 process::exit(cmd_exit_code(bin, &output));
113 }
114 }
115}