use anyhow::{Result, bail};
pub async fn detect_os_id() -> Result<String> {
let os_release = tokio::fs::read_to_string("/etc/os-release").await.ok();
detect_os_id_from(std::env::consts::OS, os_release.as_deref())
}
fn detect_os_id_from(os: &str, os_release: Option<&str>) -> Result<String> {
match os {
"macos" => Ok("macos".to_string()),
"windows" => Ok("windows".to_string()),
"linux" => {
if let Some(content) = os_release {
for line in content.lines() {
if let Some(id) = line.strip_prefix("ID=") {
return Ok(id.trim_matches('"').to_lowercase());
}
}
}
bail!(
"Could not detect Linux distribution. \
Expected ID= in /etc/os-release. Supported: ubuntu"
)
}
other => bail!(
"Unsupported platform '{}'. Supported targets: ubuntu (Linux), macos, windows",
other
),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn detects_macos() {
let result = detect_os_id_from("macos", None).unwrap();
assert_eq!(result, "macos");
}
#[test]
fn detects_windows() {
let result = detect_os_id_from("windows", None).unwrap();
assert_eq!(result, "windows");
}
#[test]
fn detects_ubuntu_from_os_release() {
let os_release = "PRETTY_NAME=\"Ubuntu 22.04\"\nID=ubuntu\nVERSION_ID=\"22.04\"\n";
let result = detect_os_id_from("linux", Some(os_release)).unwrap();
assert_eq!(result, "ubuntu");
}
#[test]
fn detects_quoted_id() {
let os_release = "ID=\"ubuntu\"\n";
let result = detect_os_id_from("linux", Some(os_release)).unwrap();
assert_eq!(result, "ubuntu");
}
#[test]
fn lowercases_id() {
let os_release = "ID=Debian\n";
let result = detect_os_id_from("linux", Some(os_release)).unwrap();
assert_eq!(result, "debian");
}
#[test]
fn errors_on_linux_without_os_release() {
let err = detect_os_id_from("linux", None).unwrap_err();
assert!(err.to_string().contains("os-release"));
}
#[test]
fn errors_on_unsupported_platform() {
let err = detect_os_id_from("freebsd", None).unwrap_err();
assert!(err.to_string().contains("freebsd"));
}
}