apt_sources/
distribution.rs1use std::fs;
2
3#[derive(Debug, Clone, PartialEq)]
5pub enum Distribution {
6 Ubuntu,
8 Debian,
10 Other(String),
12}
13
14impl std::fmt::Display for Distribution {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 Distribution::Ubuntu => write!(f, "Ubuntu"),
18 Distribution::Debian => write!(f, "Debian"),
19 Distribution::Other(name) => write!(f, "{}", name),
20 }
21 }
22}
23
24impl Distribution {
25 pub fn current() -> Option<Distribution> {
29 let content = fs::read_to_string("/etc/os-release").ok()?;
30
31 for line in content.lines() {
32 if line.starts_with("ID=") {
33 let id = line
34 .trim_start_matches("ID=")
35 .trim_matches('"')
36 .to_lowercase();
37
38 return Some(match id.as_str() {
39 "ubuntu" => Distribution::Ubuntu,
40 "debian" => Distribution::Debian,
41 other => Distribution::Other(other.to_owned()),
42 });
43 }
44 }
45
46 None
47 }
48
49 pub fn default_components(&self) -> Vec<&'static str> {
51 match self {
52 Distribution::Ubuntu => vec!["main", "universe"],
53 Distribution::Debian => vec!["main"],
54 Distribution::Other(_) => vec!["main"],
55 }
56 }
57
58 pub fn sources_basename(&self) -> Option<&'static str> {
63 match self {
64 Distribution::Ubuntu => Some("ubuntu"),
65 Distribution::Debian => Some("debian"),
66 Distribution::Other(_) => None,
67 }
68 }
69
70 pub fn is_main_repository(&self, repo: &crate::Repository) -> bool {
72 for uri in &repo.uris {
73 if let Some(host) = uri.host_str() {
74 match self {
75 Distribution::Ubuntu => {
76 if host.contains("ubuntu.com")
77 || host.contains("canonical.com")
78 || host == "archive.ubuntu.com"
79 || host == "security.ubuntu.com"
80 || host == "ports.ubuntu.com"
81 {
82 return true;
83 }
84 }
85 Distribution::Debian => {
86 if host.contains("debian.org")
87 || host == "deb.debian.org"
88 || host == "security.debian.org"
89 {
90 return true;
91 }
92 }
93 _ => {}
94 }
95 }
96 }
97 false
98 }
99}
100
101pub fn get_system_info() -> Option<(String, String)> {
106 let content = fs::read_to_string("/etc/os-release").ok()?;
107
108 let codename = content
109 .lines()
110 .find(|line| line.starts_with("VERSION_CODENAME="))
111 .map(|line| {
112 line.trim_start_matches("VERSION_CODENAME=")
113 .trim_matches('"')
114 .to_string()
115 })?;
116
117 Some((codename, String::new()))
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_is_main_repository() {
128 let dist = Distribution::Ubuntu;
129 let repo = crate::Repository {
130 uris: vec![url::Url::parse("http://archive.ubuntu.com/ubuntu").unwrap()],
131 suites: vec!["jammy".to_string()],
132 components: Some(vec!["main".to_string()]),
133 ..Default::default()
134 };
135 assert!(dist.is_main_repository(&repo));
136
137 let non_main_repo = crate::Repository {
138 uris: vec![url::Url::parse("http://example.com/ubuntu").unwrap()],
139 suites: vec!["jammy".to_string()],
140 components: Some(vec!["main".to_string()]),
141 ..Default::default()
142 };
143 assert!(!dist.is_main_repository(&non_main_repo));
144 }
145
146 #[test]
147 fn test_is_main_repository_all_ubuntu_hosts() {
148 let dist = Distribution::Ubuntu;
149
150 let ubuntu_hosts = [
152 "http://archive.ubuntu.com/ubuntu",
153 "http://security.ubuntu.com/ubuntu",
154 "http://ports.ubuntu.com/ubuntu-ports",
155 "http://us.archive.ubuntu.com/ubuntu", "http://mirrors.canonical.com/ubuntu", ];
158
159 for host in &ubuntu_hosts {
160 let repo = crate::Repository {
161 uris: vec![url::Url::parse(host).unwrap()],
162 ..Default::default()
163 };
164 assert!(dist.is_main_repository(&repo), "Failed for host: {}", host);
165 }
166 }
167
168 #[test]
169 fn test_is_main_repository_all_debian_hosts() {
170 let dist = Distribution::Debian;
171
172 let debian_hosts = [
174 "http://deb.debian.org/debian",
175 "http://security.debian.org/debian-security",
176 "http://ftp.debian.org/debian", "http://mirrors.debian.org/debian", ];
179
180 for host in &debian_hosts {
181 let repo = crate::Repository {
182 uris: vec![url::Url::parse(host).unwrap()],
183 ..Default::default()
184 };
185 assert!(dist.is_main_repository(&repo), "Failed for host: {}", host);
186 }
187 }
188
189 #[test]
190 fn test_is_main_repository_other_distribution() {
191 let dist = Distribution::Other("mint".to_string());
192
193 let repo = crate::Repository {
195 uris: vec![url::Url::parse("http://archive.ubuntu.com/ubuntu").unwrap()],
196 ..Default::default()
197 };
198 assert!(!dist.is_main_repository(&repo));
199
200 let repo2 = crate::Repository {
201 uris: vec![url::Url::parse("http://deb.debian.org/debian").unwrap()],
202 ..Default::default()
203 };
204 assert!(!dist.is_main_repository(&repo2));
205 }
206
207 #[test]
208 fn test_is_main_repository_empty_uris() {
209 let dist = Distribution::Ubuntu;
210 let repo = crate::Repository {
211 uris: vec![],
212 ..Default::default()
213 };
214 assert!(!dist.is_main_repository(&repo));
215 }
216
217 #[test]
218 fn test_is_main_repository_multiple_uris() {
219 let dist = Distribution::Ubuntu;
220 let repo = crate::Repository {
221 uris: vec![
222 url::Url::parse("http://example.com/ubuntu").unwrap(),
223 url::Url::parse("http://archive.ubuntu.com/ubuntu").unwrap(),
224 ],
225 ..Default::default()
226 };
227 assert!(dist.is_main_repository(&repo));
229 }
230
231 #[test]
232 fn test_default_components() {
233 assert_eq!(
234 Distribution::Ubuntu.default_components(),
235 vec!["main", "universe"]
236 );
237 assert_eq!(Distribution::Debian.default_components(), vec!["main"]);
238 assert_eq!(
239 Distribution::Other("mint".to_string()).default_components(),
240 vec!["main"]
241 );
242 }
243}