chug_cli/
target.rs

1use std::{fmt, process::Command};
2
3#[derive(Debug)]
4pub struct Target {
5    arch: String,
6    os: String,
7}
8
9impl Target {
10    pub fn current() -> anyhow::Result<Self> {
11        let arch = command_output("uname", &["-m"])?;
12        let mut os = command_output("uname", &["-s"])?.to_lowercase();
13
14        if os == "darwin" {
15            let version = command_output("sw_vers", &["--productVersion"])?;
16            let major_version = version.split('.').next().unwrap();
17            match major_version {
18                "13" => os = "ventura".to_owned(),
19                "14" => os = "sonoma".to_owned(),
20                "15" => os = "sequoia".to_owned(),
21                "16" => os = "cheer".to_owned(),
22                _ => anyhow::bail!("Unsupported macOS version: {version}"),
23            }
24        }
25
26        Ok(Target { arch, os })
27    }
28
29    pub fn current_str() -> anyhow::Result<&'static str> {
30        let target = cache!(String).get_or_init(|| {
31            let target = Target::current()?;
32            Ok(target.to_string())
33        })?;
34        Ok(target)
35    }
36}
37
38impl fmt::Display for Target {
39    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40        write!(f, "{}_{}", self.arch, self.os)
41    }
42}
43
44fn command_output(command: &str, args: &[&str]) -> anyhow::Result<String> {
45    let bytes = Command::new(command).args(args).output()?.stdout;
46    let mut output = String::from_utf8(bytes)?;
47
48    while output.chars().last().unwrap().is_whitespace() {
49        output.pop();
50    }
51
52    Ok(output)
53}