os_info/linux/
file_release.rs

1// spell-checker:ignore sles
2
3use std::{fmt, fs::File, io::Read, path::Path};
4
5use log::{trace, warn};
6
7use crate::{matcher::Matcher, Bitness, Info, Type, Version};
8
9pub fn get() -> Option<Info> {
10    retrieve(&DISTRIBUTIONS, "/")
11}
12
13fn retrieve(distributions: &[ReleaseInfo], root: &str) -> Option<Info> {
14    for release_info in distributions {
15        let path = Path::new(root).join(release_info.path);
16
17        if !path.exists() {
18            trace!("Path '{}' doesn't exist", release_info.path);
19            continue;
20        }
21
22        let mut file = match File::open(&path) {
23            Ok(val) => val,
24            Err(e) => {
25                warn!("Unable to open {:?} file: {:?}", &path, e);
26                continue;
27            }
28        };
29
30        let mut file_content = String::new();
31        if let Err(e) = file.read_to_string(&mut file_content) {
32            warn!("Unable to read {:?} file: {:?}", &path, e);
33            continue;
34        }
35
36        let os_type = (release_info.os_type)(&file_content);
37
38        // If os_type is indeterminate, try the next release_info
39        if os_type.is_none() {
40            continue;
41        }
42
43        let version = (release_info.version)(&file_content);
44
45        return Some(Info {
46            // Unwrap is OK here because of the `os_type.is_none()` check above.
47            os_type: os_type.unwrap(),
48            version: version.unwrap_or(Version::Unknown),
49            bitness: Bitness::Unknown,
50            ..Default::default()
51        });
52    }
53
54    // Failed to determine os info
55    None
56}
57
58/// Struct containing information on how to parse distribution info from a release file.
59#[derive(Clone)]
60struct ReleaseInfo<'a> {
61    /// Relative path to the release file this struct corresponds to from root.
62    path: &'a str,
63
64    /// A closure that determines the os type from the release file contents.
65    os_type: for<'b> fn(&'b str) -> Option<Type>,
66
67    /// A closure that determines the os version from the release file contents.
68    version: for<'b> fn(&'b str) -> Option<Version>,
69}
70
71impl fmt::Debug for ReleaseInfo<'_> {
72    fn fmt<'a>(&'a self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
73        f.debug_struct("ReleaseInfo")
74            .field("path", &self.path)
75            .field("os_type", &(self.os_type as fn(&'a str) -> Option<Type>))
76            .field("version", &(self.version as fn(&'a str) -> Option<Version>))
77            .finish()
78    }
79}
80
81/// List of all supported distributions and the information on how to parse their version from the
82/// release file.
83static DISTRIBUTIONS: [ReleaseInfo; 6] = [
84    // Keep this first; most modern distributions have this file.
85    ReleaseInfo {
86        path: "etc/os-release",
87        os_type: |release| {
88            Matcher::KeyValue { key: "ID" }
89                .find(release)
90                .and_then(|id| match id.as_str() {
91                    // os-release information collected from
92                    // https://github.com/chef/os_release
93                    "almalinux" => Some(Type::AlmaLinux),
94                    "alpaquita" => Some(Type::Alpaquita),
95                    "alpine" => Some(Type::Alpine),
96                    "amzn" => Some(Type::Amazon),
97                    //"antergos" => Antergos
98                    //"aosc" => AOSC
99                    "arch" => Some(Type::Arch),
100                    "archarm" => Some(Type::Arch),
101                    "artix" => Some(Type::Artix),
102                    "bluefin" => Some(Type::Bluefin),
103                    "cachyos" => Some(Type::CachyOS),
104                    "centos" => Some(Type::CentOS),
105                    //"clear-linux-os" => ClearLinuxOS
106                    //"clearos" => ClearOS
107                    //"coreos"
108                    //"cumulus-linux" => Cumulus
109                    "debian" => Some(Type::Debian),
110                    //"devuan" => Devuan
111                    //"elementary" => Elementary
112                    "fedora" => Some(Type::Fedora),
113                    //"gentoo" => Gentoo
114                    //"ios_xr" => ios_xr
115                    "kali" => Some(Type::Kali),
116                    //"mageia" => Mageia
117                    //"manjaro" => Manjaro
118                    "linuxmint" => Some(Type::Mint),
119                    "mariner" => Some(Type::Mariner),
120                    //"nexus" => Nexus
121                    "nixos" => Some(Type::NixOS),
122                    "nobara" => Some(Type::Nobara),
123                    "Uos" => Some(Type::Uos),
124                    "opencloudos" => Some(Type::OpenCloudOS),
125                    "openEuler" => Some(Type::openEuler),
126                    "ol" => Some(Type::OracleLinux),
127                    "opensuse" => Some(Type::openSUSE),
128                    "opensuse-leap" => Some(Type::openSUSE),
129                    "opensuse-microos" => Some(Type::openSUSE),
130                    "opensuse-tumbleweed" => Some(Type::openSUSE),
131                    //"rancheros" => RancherOS
132                    //"raspbian" => Raspbian
133                    // note XBian also uses "raspbian"
134                    "rhel" => Some(Type::RedHatEnterprise),
135                    "rocky" => Some(Type::RockyLinux),
136                    //"sabayon" => Sabayon
137                    //"scientific" => Scientific
138                    //"slackware" => Slackware
139                    "sled" => Some(Type::SUSE), // SUSE desktop
140                    "sles" => Some(Type::SUSE),
141                    "sles_sap" => Some(Type::SUSE), // SUSE SAP
142                    "ubuntu" => Some(Type::Ubuntu),
143                    "ultramarine" => Some(Type::Ultramarine),
144                    //"virtuozzo" => Virtuozzo
145                    "void" => Some(Type::Void),
146                    //"XCP-ng" => xcp-ng
147                    //"xenenterprise" => xcp-ng
148                    //"xenserver" => xcp-ng
149                    _ => None,
150                })
151        },
152        version: |release| {
153            Matcher::KeyValue { key: "VERSION_ID" }
154                .find(release)
155                .map(Version::from_string)
156        },
157    },
158    // Older distributions must have their specific release file parsed.
159    ReleaseInfo {
160        path: "etc/mariner-release",
161        os_type: |_| Some(Type::Mariner),
162        version: |release| {
163            Matcher::PrefixedVersion {
164                prefix: "CBL-Mariner",
165            }
166            .find(release)
167            .map(Version::from_string)
168        },
169    },
170    ReleaseInfo {
171        path: "etc/centos-release",
172        os_type: |_| Some(Type::CentOS),
173        version: |release| {
174            Matcher::PrefixedVersion { prefix: "release" }
175                .find(release)
176                .map(Version::from_string)
177        },
178    },
179    ReleaseInfo {
180        path: "etc/fedora-release",
181        os_type: |_| Some(Type::Fedora),
182        version: |release| {
183            Matcher::PrefixedVersion { prefix: "release" }
184                .find(release)
185                .map(Version::from_string)
186        },
187    },
188    ReleaseInfo {
189        path: "etc/alpine-release",
190        os_type: |_| Some(Type::Alpine),
191        version: |release| Matcher::AllTrimmed.find(release).map(Version::from_string),
192    },
193    ReleaseInfo {
194        path: "etc/redhat-release",
195        os_type: |_| Some(Type::RedHatEnterprise),
196        version: |release| {
197            Matcher::PrefixedVersion { prefix: "release" }
198                .find(release)
199                .map(Version::from_string)
200        },
201    },
202];
203
204#[cfg(test)]
205mod tests {
206    use super::*;
207    use pretty_assertions::assert_eq;
208
209    #[test]
210    fn almalinux_9_0_release() {
211        let root = "src/linux/tests/AlmaLinux-9.0";
212
213        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
214        assert_eq!(info.os_type(), Type::AlmaLinux);
215        assert_eq!(info.version, Version::Semantic(9, 0, 0));
216        assert_eq!(info.edition, None);
217        assert_eq!(info.codename, None);
218    }
219
220    #[test]
221    fn alpaquita_os_release() {
222        let root = "src/linux/tests/Alpaquita";
223
224        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
225        assert_eq!(info.os_type(), Type::Alpaquita);
226        assert_eq!(info.version, Version::Semantic(23, 0, 0));
227        assert_eq!(info.edition, None);
228        assert_eq!(info.codename, None);
229    }
230
231    #[test]
232    fn alpine_3_12_os_release() {
233        let root = "src/linux/tests/Alpine_3_12";
234
235        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
236        assert_eq!(info.os_type(), Type::Alpine);
237        assert_eq!(info.version, Version::Semantic(3, 12, 0));
238        assert_eq!(info.edition, None);
239        assert_eq!(info.codename, None);
240    }
241
242    #[test]
243    fn alpine_release() {
244        let root = "src/linux/tests/Alpine";
245
246        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
247        assert_eq!(info.os_type(), Type::Alpine);
248        assert_eq!(info.version, Version::Custom("A.B.C".to_owned()));
249        assert_eq!(info.edition, None);
250        assert_eq!(info.codename, None);
251    }
252
253    #[test]
254    fn amazon_1_os_release() {
255        let root = "src/linux/tests/Amazon_1";
256
257        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
258        assert_eq!(info.os_type(), Type::Amazon);
259        assert_eq!(info.version, Version::Semantic(2018, 3, 0));
260        assert_eq!(info.edition, None);
261        assert_eq!(info.codename, None);
262    }
263
264    #[test]
265    fn amazon_2_os_release() {
266        let root = "src/linux/tests/Amazon_2";
267
268        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
269        assert_eq!(info.os_type(), Type::Amazon);
270        assert_eq!(info.version, Version::Semantic(2, 0, 0));
271        assert_eq!(info.edition, None);
272        assert_eq!(info.codename, None);
273    }
274
275    #[test]
276    fn arch_os_release() {
277        let root = "src/linux/tests/Arch";
278
279        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
280        assert_eq!(info.os_type(), Type::Arch);
281        assert_eq!(info.version, Version::Unknown);
282        assert_eq!(info.edition, None);
283        assert_eq!(info.codename, None);
284    }
285
286    #[test]
287    fn archarm_os_release() {
288        let root = "src/linux/tests/ArchARM";
289
290        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
291        assert_eq!(info.os_type(), Type::Arch);
292        assert_eq!(info.version, Version::Unknown);
293        assert_eq!(info.edition, None);
294        assert_eq!(info.codename, None);
295    }
296
297    #[test]
298    fn artix_os_release() {
299        let root = "src/linux/tests/Artix";
300
301        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
302        assert_eq!(info.os_type(), Type::Artix);
303        assert_eq!(info.version, Version::Unknown);
304        assert_eq!(info.edition, None);
305        assert_eq!(info.codename, None);
306    }
307
308    #[test]
309    fn bluefin_os_release() {
310        let root = "src/linux/tests/Bluefin";
311
312        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
313        assert_eq!(info.os_type(), Type::Bluefin);
314        assert_eq!(info.version, Version::Semantic(41, 0, 0));
315        assert_eq!(info.edition, None);
316        assert_eq!(info.codename, None);
317    }
318
319    #[test]
320    fn centos_7_os_release() {
321        let root = "src/linux/tests/CentOS_7";
322
323        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
324        assert_eq!(info.os_type(), Type::CentOS);
325        assert_eq!(info.version, Version::Semantic(7, 0, 0));
326        assert_eq!(info.edition, None);
327        assert_eq!(info.codename, None);
328    }
329
330    #[test]
331    fn centos_stream_os_release() {
332        let root = "src/linux/tests/CentOS_Stream";
333
334        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
335        assert_eq!(info.os_type(), Type::CentOS);
336        assert_eq!(info.version, Version::Semantic(8, 0, 0));
337        assert_eq!(info.edition, None);
338        assert_eq!(info.codename, None);
339    }
340
341    #[test]
342    fn centos_release() {
343        let root = "src/linux/tests/CentOS";
344
345        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
346        assert_eq!(info.os_type(), Type::CentOS);
347        assert_eq!(info.version, Version::Custom("XX".to_owned()));
348        assert_eq!(info.edition, None);
349        assert_eq!(info.codename, None);
350    }
351
352    #[test]
353    fn centos_release_unknown() {
354        let root = "src/linux/tests/CentOS_Unknown";
355
356        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
357        assert_eq!(info.os_type(), Type::CentOS);
358        assert_eq!(info.version, Version::Unknown);
359        assert_eq!(info.edition, None);
360        assert_eq!(info.codename, None);
361    }
362
363    #[test]
364    fn debian_11_os_release() {
365        let root = "src/linux/tests/Debian_11";
366
367        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
368        assert_eq!(info.os_type(), Type::Debian);
369        assert_eq!(info.version, Version::Semantic(11, 0, 0));
370        assert_eq!(info.edition, None);
371        assert_eq!(info.codename, None);
372    }
373
374    #[test]
375    fn fedora_32_os_release() {
376        let root = "src/linux/tests/Fedora_32";
377
378        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
379        assert_eq!(info.os_type(), Type::Fedora);
380        assert_eq!(info.version, Version::Semantic(32, 0, 0));
381        assert_eq!(info.edition, None);
382        assert_eq!(info.codename, None);
383    }
384
385    #[test]
386    fn fedora_35_os_release() {
387        let root = "src/linux/tests/Fedora_35";
388
389        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
390        assert_eq!(info.os_type(), Type::Fedora);
391        assert_eq!(info.version, Version::Semantic(35, 0, 0));
392        assert_eq!(info.edition, None);
393        assert_eq!(info.codename, None);
394    }
395
396    #[test]
397    fn fedora_release() {
398        let root = "src/linux/tests/Fedora";
399
400        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
401        assert_eq!(info.os_type(), Type::Fedora);
402        assert_eq!(info.version, Version::Semantic(26, 0, 0));
403        assert_eq!(info.edition, None);
404        assert_eq!(info.codename, None);
405    }
406
407    #[test]
408    fn fedora_release_unknown() {
409        let root = "src/linux/tests/Fedora_Unknown";
410
411        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
412        assert_eq!(info.os_type(), Type::Fedora);
413        assert_eq!(info.version, Version::Unknown);
414        assert_eq!(info.edition, None);
415        assert_eq!(info.codename, None);
416    }
417
418    #[test]
419    fn kali_2023_2_os_release() {
420        let root = "src/linux/tests/Kali_2023_2";
421
422        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
423        assert_eq!(info.os_type(), Type::Kali);
424        assert_eq!(info.version, Version::Semantic(2023, 2, 0));
425        assert_eq!(info.edition, None);
426        assert_eq!(info.codename, None);
427    }
428
429    #[test]
430    fn mariner_release() {
431        let root = "src/linux/tests/Mariner";
432
433        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
434        assert_eq!(info.os_type(), Type::Mariner);
435        assert_eq!(info.version, Version::Semantic(2, 0, 20220210));
436        assert_eq!(info.edition, None);
437        assert_eq!(info.codename, None);
438    }
439
440    #[test]
441    fn mariner_release_unknown() {
442        let root = "src/linux/tests/Mariner_Unknown";
443
444        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
445        assert_eq!(info.os_type(), Type::Mariner);
446        assert_eq!(info.version, Version::Unknown);
447        assert_eq!(info.edition, None);
448        assert_eq!(info.codename, None);
449    }
450
451    #[test]
452    fn mint_os_release() {
453        let root = "src/linux/tests/Mint";
454
455        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
456        assert_eq!(info.os_type(), Type::Mint);
457        assert_eq!(info.version, Version::Semantic(20, 0, 0));
458        assert_eq!(info.edition, None);
459        assert_eq!(info.codename, None);
460    }
461
462    #[test]
463    fn nixos_os_release() {
464        let root = "src/linux/tests/NixOS";
465
466        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
467        assert_eq!(info.os_type(), Type::NixOS);
468        assert_eq!(
469            info.version,
470            Version::Custom("21.05pre275822.916ee862e87".to_string())
471        );
472        assert_eq!(info.edition, None);
473        assert_eq!(info.codename, None);
474    }
475
476    #[test]
477    fn nobara_os_release() {
478        let root = "src/linux/tests/Nobara";
479
480        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
481        assert_eq!(info.os_type(), Type::Nobara);
482        assert_eq!(info.version, Version::Semantic(39, 0, 0));
483        assert_eq!(info.edition, None);
484        assert_eq!(info.codename, None);
485    }
486
487    #[test]
488    fn uos_os_release() {
489        let root = "src/linux/tests/Uos";
490
491        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
492        assert_eq!(info.os_type(), Type::Uos);
493        assert_eq!(info.version, Version::Semantic(20, 0, 0));
494        assert_eq!(info.edition, None);
495        assert_eq!(info.codename, None);
496    }
497
498    #[test]
499    fn none_invalid_os_release() {
500        let root = "src/linux/tests/none_invalid_os_release";
501
502        let info = retrieve(&DISTRIBUTIONS, root);
503        assert_eq!(info, None);
504    }
505
506    #[test]
507    fn none_no_release() {
508        let root = "src/linux/tests/none_no_release";
509
510        let info = retrieve(&DISTRIBUTIONS, root);
511        assert_eq!(info, None);
512    }
513
514    #[test]
515    fn none_no_path() {
516        let root = "src/linux/tests/none_no_path";
517
518        let info = retrieve(&DISTRIBUTIONS, root);
519        assert_eq!(info, None);
520    }
521
522    #[test]
523    fn opencloudos_os_release() {
524        let root = "src/linux/tests/OpenCloudOS";
525
526        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
527        assert_eq!(info.os_type(), Type::OpenCloudOS);
528        assert_eq!(info.version, Version::Semantic(8, 6, 0));
529        assert_eq!(info.edition, None);
530        assert_eq!(info.codename, None);
531    }
532
533    #[test]
534    fn openeuler_os_release() {
535        let root = "src/linux/tests/openEuler";
536
537        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
538        assert_eq!(info.os_type(), Type::openEuler);
539        assert_eq!(info.version, Version::Semantic(22, 3, 0));
540        assert_eq!(info.edition, None);
541        assert_eq!(info.codename, None);
542    }
543
544    #[test]
545    fn opensuse_tumbleweed_os_release() {
546        let root = "src/linux/tests/openSUSE_Tumbleweed";
547
548        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
549        assert_eq!(info.os_type(), Type::openSUSE);
550        assert_eq!(info.version, Version::Semantic(20230816, 0, 0));
551        assert_eq!(info.edition, None);
552        assert_eq!(info.codename, None);
553    }
554
555    #[test]
556    fn oracle_linux_os_release() {
557        let root = "src/linux/tests/OracleLinux";
558
559        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
560        assert_eq!(info.os_type(), Type::OracleLinux);
561        assert_eq!(info.version, Version::Semantic(8, 1, 0));
562        assert_eq!(info.edition, None);
563        assert_eq!(info.codename, None);
564    }
565
566    #[test]
567    fn rhel_8_os_release() {
568        let root = "src/linux/tests/RedHatEnterprise_8";
569
570        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
571        assert_eq!(info.os_type(), Type::RedHatEnterprise);
572        assert_eq!(info.version, Version::Semantic(8, 2, 0));
573        assert_eq!(info.edition, None);
574        assert_eq!(info.codename, None);
575    }
576
577    #[test]
578    fn rhel_7_os_release() {
579        let root = "src/linux/tests/RedHatEnterprise_7";
580
581        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
582        assert_eq!(info.os_type(), Type::RedHatEnterprise);
583        assert_eq!(info.version, Version::Semantic(7, 9, 0));
584        assert_eq!(info.edition, None);
585        assert_eq!(info.codename, None);
586    }
587
588    #[test]
589    fn redhat_release() {
590        let root = "src/linux/tests/RedHatEnterprise";
591
592        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
593        assert_eq!(info.os_type(), Type::RedHatEnterprise);
594        assert_eq!(info.version, Version::Custom("XX".to_owned()));
595        assert_eq!(info.edition, None);
596        assert_eq!(info.codename, None);
597    }
598
599    #[test]
600    fn redhat_release_unknown() {
601        let root = "src/linux/tests/RedHatEnterprise_Unknown";
602
603        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
604        assert_eq!(info.os_type(), Type::RedHatEnterprise);
605        assert_eq!(info.version, Version::Unknown);
606        assert_eq!(info.edition, None);
607        assert_eq!(info.codename, None);
608    }
609
610    #[test]
611    fn rocky_9_2_release() {
612        let root = "src/linux/tests/RockyLinux-9.2";
613
614        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
615        assert_eq!(info.os_type(), Type::RockyLinux);
616        assert_eq!(info.version, Version::Semantic(9, 2, 0));
617        assert_eq!(info.edition, None);
618        assert_eq!(info.codename, None);
619    }
620
621    #[test]
622    fn suse_12_os_release() {
623        let root = "src/linux/tests/SUSE_12";
624
625        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
626        assert_eq!(info.os_type(), Type::SUSE);
627        assert_eq!(info.version, Version::Semantic(12, 5, 0));
628        assert_eq!(info.edition, None);
629        assert_eq!(info.codename, None);
630    }
631
632    #[test]
633    fn suse_15_os_release() {
634        let root = "src/linux/tests/SUSE_15";
635
636        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
637        assert_eq!(info.os_type(), Type::SUSE);
638        assert_eq!(info.version, Version::Semantic(15, 2, 0));
639        assert_eq!(info.edition, None);
640        assert_eq!(info.codename, None);
641    }
642
643    #[test]
644    fn ubuntu_os_release() {
645        let root = "src/linux/tests/Ubuntu";
646
647        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
648        assert_eq!(info.os_type(), Type::Ubuntu);
649        assert_eq!(info.version, Version::Semantic(18, 10, 0));
650        assert_eq!(info.edition, None);
651        assert_eq!(info.codename, None);
652    }
653
654    #[test]
655    fn ultramarine_os_release() {
656        let root = "src/linux/tests/Ultramarine";
657
658        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
659        assert_eq!(info.os_type(), Type::Ultramarine);
660        assert_eq!(info.version, Version::Semantic(39, 0, 0));
661        assert_eq!(info.edition, None);
662        assert_eq!(info.codename, None);
663    }
664
665    #[test]
666    fn void_os_release() {
667        let root = "src/linux/tests/Void";
668
669        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
670        assert_eq!(info.os_type(), Type::Void);
671        assert_eq!(info.version, Version::Unknown);
672        assert_eq!(info.edition, None);
673        assert_eq!(info.codename, None);
674    }
675
676    #[test]
677    fn cachy_os_release() {
678        let root = "src/linux/tests/CachyOS";
679
680        let info = retrieve(&DISTRIBUTIONS, root).unwrap();
681        assert_eq!(info.os_type(), Type::CachyOS);
682        assert_eq!(info.version, Version::Unknown);
683        assert_eq!(info.edition, None);
684        assert_eq!(info.codename, None);
685    }
686
687    #[test]
688    fn release_info_debug() {
689        dbg!("{:?}", &DISTRIBUTIONS[0]);
690    }
691}