sweet_fs/process/
command.rs1use anyhow::Result;
2use std::process::Child;
3use std::process::Command;
4use std::process::Output;
5use std::process::Stdio;
6
7
8pub struct CommandExt;
9
10impl CommandExt {
11 pub fn from_vec<T: AsRef<str>>(cmd: &Vec<T>) -> Command {
13 let mut command = Command::new(cmd[0].as_ref());
14 for arg in cmd.iter().skip(1) {
15 command.arg(arg.as_ref());
16 }
17 command
18 }
19
20
21 pub fn from_whitespace(cmd: &str) -> Command {
23 let cmd = cmd.split_whitespace();
24 let mut command = Command::new(cmd.clone().next().unwrap());
25 for arg in cmd.skip(1) {
26 command.arg(arg);
27 }
28 command
29 }
30
31 pub fn unwrap_status(mut cmd: Command) -> Result<()> {
33 let status = cmd.status()?;
34 if !status.success() {
35 Err(anyhow::anyhow!("Command failed: {:?}", status))?;
36 }
37 Ok(())
38 }
39 pub fn unwrap_output_empty(mut cmd: Command) -> Result<()> {
41 let output = cmd.output()?;
42 if output.stdout.is_empty() && output.stderr.is_empty() {
43 Ok(())
44 } else {
45 anyhow::bail!(
46 "Expected empty output, received: \nStdout: {}\nStderr: {}",
47 String::from_utf8_lossy(&output.stdout),
48 String::from_utf8_lossy(&output.stderr)
49 )
50 }
51 }
52
53
54 pub fn spawn_command(args: &Vec<&str>) -> Result<Child> {
56 println!("{}", args.join(" "));
57 let child = Self::get_command(args)
58 .spawn()?;
60 Ok(child)
61 }
62
63 pub fn spawn_command_blocking(args: &Vec<&str>) -> Result<()> {
64 let _ = Self::get_command(args)
65 .stdout(Stdio::inherit())
66 .stderr(Stdio::inherit())
67 .output()?;
68 Ok(())
69 }
70
71 pub fn spawn_command_hold_stdio(args: &Vec<&str>) -> Result<CommandOutput> {
72 let out = Self::get_command(args).output()?;
73 Ok(out.into())
74 }
75
76 fn get_command(args: &Vec<&str>) -> Command {
77 let mut cmd = Command::new(args[0]);
78 cmd.args(args[1..].iter());
79 cmd
80 }
81
82 pub fn spawn_command_with_shell_blocking(args: &Vec<&str>) -> Result<()> {
83 let _ = Self::get_command_with_shell(args)
84 .stdout(Stdio::inherit())
85 .stderr(Stdio::inherit())
86 .output()?;
87 Ok(())
88 }
89
90 fn get_command_with_shell(args: &Vec<&str>) -> Command {
91 let is_windows = cfg!(target_os = "windows");
92 let (cmd, arg) = if is_windows {
93 ("powershell", "-Command")
95 } else {
96 ("sh", "-c")
97 };
98 let mut cmd = Command::new(cmd);
99 cmd.arg(arg);
100 cmd.args(args);
101 cmd
102 }
103}
104
105pub struct CommandOutput {
106 pub success: bool,
107 pub stdout: String,
108 pub stderr: String,
109}
110
111impl From<Output> for CommandOutput {
112 fn from(output: Output) -> Self {
113 let stdout = String::from_utf8_lossy(&output.stdout).to_string();
114 let stderr = String::from_utf8_lossy(&output.stderr).to_string();
115 CommandOutput {
116 success: output.status.success(),
117 stdout,
118 stderr,
119 }
120 }
121}