Skip to content

Commit 29aec6b

Browse files
committed
feat(system): detect ubuntu/debian derivative distros via id_like fallback
Add `from_id_like()` to fall back to the `ID_LIKE` parent chain when the primary distro ID is unrecognized. Fixes valgrind setup failing on Pop!_OS (`ID=pop`, `ID_LIKE="ubuntu debian"`). Tests also cover Ubuntu and CentOS.
1 parent ba33073 commit 29aec6b

1 file changed

Lines changed: 59 additions & 1 deletion

File tree

src/system/os.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ impl SupportedOs {
2626
match os {
2727
"linux" => {
2828
let os_id = System::distribution_id();
29-
Ok(Self::Linux(LinuxDistribution::from_id(&os_id, &os_version)))
29+
let os_id_like = System::distribution_id_like();
30+
Ok(Self::Linux(LinuxDistribution::from_id_like(
31+
&os_id,
32+
&os_id_like,
33+
&os_version,
34+
)))
3035
}
3136
"macos" => Ok(Self::Macos {
3237
version: os_version,
@@ -99,6 +104,21 @@ impl LinuxDistribution {
99104
}
100105
}
101106

107+
/// Build a [`LinuxDistribution`] from the `sysinfo`-reported `os_id` and `os_id_like` fields.
108+
/// This is needed to handle cases like PopOS (`os_id` = "pop" and `os_id_like` = ["ubuntu"]).
109+
fn from_id_like(os_id: &str, os_id_like: &[String], version: &str) -> Self {
110+
let by_id = Self::from_id(os_id, version);
111+
if matches!(by_id, Self::Other { .. }) {
112+
for like_id in os_id_like {
113+
let by_like_id = Self::from_id(like_id, version);
114+
if !matches!(by_like_id, Self::Other { .. }) {
115+
return by_like_id;
116+
}
117+
}
118+
}
119+
by_id
120+
}
121+
102122
/// The distro id as it appears on the wire (matches `sysinfo::System::distribution_id()`).
103123
pub fn id(&self) -> &str {
104124
match self {
@@ -137,4 +157,42 @@ mod tests {
137157
let err = SupportedOs::from_os("windows").unwrap_err();
138158
assert_eq!(err.to_string(), "Unsupported operating system: windows");
139159
}
160+
161+
#[test]
162+
fn pop_os_resolves_to_ubuntu_via_id_like() {
163+
// Pop!_OS: ID=pop, ID_LIKE="ubuntu debian"
164+
let distro = LinuxDistribution::from_id_like(
165+
"pop",
166+
&[String::from("ubuntu"), String::from("debian")],
167+
"24.04",
168+
);
169+
assert!(
170+
matches!(distro, LinuxDistribution::Ubuntu { .. }),
171+
"got {distro}"
172+
);
173+
}
174+
175+
#[test]
176+
fn ubuntu_resolves_directly_without_id_like() {
177+
// Ubuntu laptop: ID=ubuntu, ID_LIKE="debian" — primary id wins, no fallback needed
178+
let distro = LinuxDistribution::from_id_like("ubuntu", &[String::from("debian")], "24.04");
179+
assert!(
180+
matches!(distro, LinuxDistribution::Ubuntu { .. }),
181+
"got {distro}"
182+
);
183+
}
184+
185+
#[test]
186+
fn centos_with_unrecognized_parents_is_other() {
187+
// CentOS server: ID=centos, ID_LIKE="rhel fedora" — neither parent is known
188+
let distro = LinuxDistribution::from_id_like(
189+
"centos",
190+
&[String::from("rhel"), String::from("fedora")],
191+
"9",
192+
);
193+
assert!(
194+
matches!(&distro, LinuxDistribution::Other { name, .. } if name == "centos"),
195+
"got {distro}"
196+
);
197+
}
140198
}

0 commit comments

Comments
 (0)