vdev/utils/
command.rs

1//! Command execution utilities
2
3use std::{
4    ffi::{OsStr, OsString},
5    process::{self, Command},
6};
7
8/// Trait for chaining command arguments
9pub trait ChainArgs {
10    fn chain_args<I: Into<OsString>>(&self, args: impl IntoIterator<Item = I>) -> Vec<OsString>;
11}
12
13impl<T: AsRef<OsStr>> ChainArgs for Vec<T> {
14    fn chain_args<I: Into<OsString>>(&self, args: impl IntoIterator<Item = I>) -> Vec<OsString> {
15        self.iter()
16            .map(Into::into)
17            .chain(args.into_iter().map(Into::into))
18            .collect()
19    }
20}
21
22impl<T: AsRef<OsStr>> ChainArgs for [T] {
23    fn chain_args<I: Into<OsString>>(&self, args: impl IntoIterator<Item = I>) -> Vec<OsString> {
24        self.iter()
25            .map(Into::into)
26            .chain(args.into_iter().map(Into::into))
27            .collect()
28    }
29}
30
31/// Run a shell command and return its output or exit on failure
32pub fn run_command(cmd: &str) -> String {
33    let output = Command::new("sh")
34        .arg("-c")
35        .arg(cmd)
36        .output()
37        .expect("Failed to execute command");
38
39    if !output.status.success() {
40        eprintln!(
41            "Command failed: {cmd} - Error: {}",
42            String::from_utf8_lossy(&output.stderr)
43        );
44        process::exit(1);
45    }
46
47    String::from_utf8_lossy(&output.stdout).to_string()
48}