use crate::detect::{Row, Rows};
pub fn detect() -> Rows {
let mut id = String::new();
let mut name = String::new();
let mut version_id = String::new();
let mut codename = String::new();
let mut pretty = String::new();
if let Ok(s) = std::fs::read_to_string("/etc/os-release") {
for line in s.lines() {
let Some((k, v)) = line.split_once('=') else {
continue;
};
let v = v.trim().trim_matches('"');
match k {
"ID" => id = v.to_string(),
"NAME" => name = v.to_string(),
"VERSION_ID" => version_id = v.to_string(),
"VERSION_CODENAME" => codename = v.to_string(),
"PRETTY_NAME" => pretty = v.to_string(),
_ => {}
}
}
}
let debian_version = std::fs::read_to_string("/etc/debian_version")
.ok()
.map(|s| s.trim().to_string());
let version = effective_version(&id, version_id, debian_version);
let arch = std::env::consts::ARCH;
let base = if !name.is_empty() {
let mut b = name;
if !version.is_empty() {
b.push(' ');
b.push_str(&version);
}
if !codename.is_empty() {
b.push_str(&format!(" ({codename})"));
}
b
} else if !pretty.is_empty() {
pretty
} else {
"Linux".to_string()
};
vec![Row::val(format!("{base} {arch}"))]
}
fn effective_version(id: &str, version_id: String, debian_version: Option<String>) -> String {
if id == "debian" {
if let Some(v) = debian_version.filter(|s| !s.is_empty()) {
return v;
}
}
version_id
}
#[cfg(test)]
mod tests {
use super::effective_version;
#[test]
fn debian_version_only_refines_debian_itself() {
let s = |x: &str| x.to_string();
assert_eq!(
effective_version("debian", s("13"), Some(s("13.5"))),
"13.5"
);
assert_eq!(
effective_version("ubuntu", s("24.04"), Some(s("trixie/sid"))),
"24.04"
);
assert_eq!(effective_version("debian", s("13"), None), "13");
assert_eq!(effective_version("debian", s("13"), Some(s(""))), "13");
}
}