justrs/execute_shell_command.rs
1// use std::process::{Command, Output};
2
3// pub type Result<T> = core::result::Result<T, Error>;
4// pub type Error = Box<dyn std::error::Error>; // For early dev.
5
6// pub fn execute_shell_command<T>(command: &str) -> Result<T>
7// where
8// T: std::convert::From<std::string::String> + std::str::FromStr,
9// {
10// let output: Output = Command::new("sh")
11// .arg("-c")
12// .arg(command)
13// .output()
14// .map_err(|e| format!("Failed to execute command: {}", e))?;
15
16// if output.status.success() {
17// let stdout = String::from_utf8_lossy(&output.stdout).to_string();
18// Ok(format!("Success : {}", stdout).into())
19// } else {
20// let stderr = String::from_utf8_lossy(&output.stderr).to_string();
21// Err(format!("Command failed: {}", stderr).into())
22// }
23// }
24
25use std::{process::Command, str::FromStr};
26
27pub type Result<T> = core::result::Result<T, Error>;
28pub type Error = Box<dyn std::error::Error + Send + Sync>;
29
30/// Execute `command` via `sh -c` and parse stdout into `T`.
31/// `T` must implement `FromStr` and its error must implement `Display`.
32pub fn execute_shell_command<T>(command: &str) -> Result<T>
33where
34 T: FromStr,
35 <T as FromStr>::Err: std::fmt::Display,
36{
37 let output = Command::new("sh")
38 .arg("-c")
39 .arg(command)
40 .output()
41 .map_err(|e| format!("Failed to execute command: {}", e))?;
42
43 if output.status.success() {
44 // parse the stdout (trim trailing newline/whitespace)
45 let stdout = String::from_utf8_lossy(&output.stdout).to_string();
46 let trimmed = stdout.trim();
47 let parsed = trimmed.parse::<T>().map_err(|e| {
48 format!(
49 "Failed to parse stdout (`{}`) into target type: {}",
50 trimmed, e
51 )
52 })?;
53 Ok(parsed)
54 } else {
55 let stderr = String::from_utf8_lossy(&output.stderr).to_string();
56 Err(format!("Command failed: {}", stderr).into())
57 }
58}