debian_analyzer/
release_info.rs1pub use breezyshim::debian::Vendor;
4use chrono::{NaiveDate, Utc};
5use distro_info::DistroInfo;
6
7pub const DEBIAN_POCKETS: &[&str] = &["", "-security", "-proposed-updates", "-backports"];
9
10pub const UBUNTU_POCKETS: &[&str] = &["", "-proposed", "-updates", "-security", "-backports"];
12
13pub fn debian_releases() -> Vec<String> {
15 let debian = distro_info::DebianDistroInfo::new().unwrap();
16 debian
17 .all_at(Utc::now().naive_utc().date())
18 .into_iter()
19 .map(|r| r.series().to_string())
20 .collect()
21}
22
23pub fn ubuntu_releases() -> Vec<String> {
25 let ubuntu = distro_info::UbuntuDistroInfo::new().unwrap();
26 ubuntu
27 .all_at(Utc::now().naive_utc().date())
28 .into_iter()
29 .map(|r| r.series().to_string())
30 .collect()
31}
32
33pub fn suite_to_distribution(suite: &str) -> Option<Vendor> {
42 let all_debian = debian_releases()
43 .iter()
44 .flat_map(|r| DEBIAN_POCKETS.iter().map(move |t| format!("{}{}", r, t)))
45 .collect::<Vec<_>>();
46 let all_ubuntu = ubuntu_releases()
47 .iter()
48 .flat_map(|r| UBUNTU_POCKETS.iter().map(move |t| format!("{}{}", r, t)))
49 .collect::<Vec<_>>();
50 if all_debian.contains(&suite.to_string()) {
51 return Some(Vendor::Debian);
52 }
53 if all_ubuntu.contains(&suite.to_string()) {
54 return Some(Vendor::Ubuntu);
55 }
56
57 if suite == "kali" || suite.starts_with("kali-") {
58 return Some(Vendor::Kali);
59 }
60
61 None
62}
63
64pub fn release_aliases(name: &str, date: Option<NaiveDate>) -> Vec<String> {
66 let mut ret = vec![];
67 let debian_info = distro_info::DebianDistroInfo::new().unwrap();
68 let all_released = debian_info.released(date.unwrap_or(Utc::now().naive_utc().date()));
69 if all_released[0].series() == name {
70 ret.push("stable".to_string());
71 }
72 if all_released[1].series() == name {
73 ret.push("oldstable".to_string());
74 }
75 if all_released[2].series() == name {
76 ret.push("oldoldstable".to_string());
77 }
78
79 if name == "sid" {
80 ret.push("unstable".to_string());
81 }
82
83 let ubuntu_info = distro_info::UbuntuDistroInfo::new().unwrap();
84
85 let all_released = ubuntu_info.released(date.unwrap_or(Utc::now().naive_utc().date()));
86 for series in all_released.iter() {
87 if series.codename() == name {
88 ret.push(series.series().to_string());
89 }
90 }
91
92 ret
93}
94
95pub fn resolve_release_codename(name: &str, date: Option<NaiveDate>) -> Option<String> {
97 let date = date.unwrap_or(Utc::now().naive_utc().date());
98 let (distro, mut name) = if let Some((distro, name)) = name.split_once('/') {
99 (Some(distro), name)
100 } else {
101 (None, name)
102 };
103 let active = |x: &Option<NaiveDate>| x.map(|x| x > date).unwrap_or(false);
104 if distro.is_none() || distro == Some("debian") {
105 let debian = distro_info::DebianDistroInfo::new().unwrap();
106 if name == "lts" {
107 let lts = debian
108 .all_at(date)
109 .into_iter()
110 .filter(|r| active(r.eol_lts()))
111 .min_by_key(|r| r.created());
112 return lts.map(|r| r.series().to_string());
113 }
114 if name == "elts" {
115 let elts = debian
116 .all_at(date)
117 .into_iter()
118 .filter(|r| active(r.eol_elts()))
119 .min_by_key(|r| r.created());
120 return elts.map(|r| r.series().to_string());
121 }
122 let mut all_released = debian
123 .all_at(date)
124 .into_iter()
125 .filter(|r| r.release().is_some())
126 .collect::<Vec<_>>();
127 all_released.sort_by_key(|r| r.created());
128 all_released.reverse();
129 if name == "stable" {
130 return Some(all_released[0].series().to_string());
131 }
132 if name == "oldstable" {
133 return Some(all_released[1].series().to_string());
134 }
135 if name == "oldoldstable" {
136 return Some(all_released[2].series().to_string());
137 }
138 if name == "unstable" {
139 name = "sid";
140 }
141 if name == "testing" {
142 let mut all_unreleased = debian
143 .all_at(date)
144 .into_iter()
145 .filter(|r| r.release().is_none())
146 .collect::<Vec<_>>();
147 all_unreleased.sort_by_key(|r| r.created());
148 return Some(all_unreleased.last().unwrap().series().to_string());
149 }
150
151 let all = debian.all_at(date);
152 if let Some(series) = all
153 .iter()
154 .find(|r| r.codename() == name || r.series() == name)
155 {
156 return Some(series.series().to_string());
157 }
158 }
159 if distro.is_none() || distro == Some("ubuntu") {
160 let ubuntu = distro_info::UbuntuDistroInfo::new().unwrap();
161 if name == "esm" {
162 return ubuntu
163 .all_at(date)
164 .into_iter()
165 .filter(|r| active(r.eol_esm()))
166 .min_by_key(|r| r.created())
167 .map(|r| r.series().to_string());
168 }
169 if name == "lts" {
170 return ubuntu
171 .all_at(date)
172 .into_iter()
173 .filter(|r| r.is_lts() && r.supported_at(date))
174 .min_by_key(|r| r.created())
175 .map(|r| r.series().to_string());
176 }
177 let all = ubuntu.all_at(date);
178 if let Some(series) = all
179 .iter()
180 .find(|r| r.codename() == name || r.series() == name)
181 {
182 return Some(series.series().to_string());
183 }
184 }
185 None
186}
187
188include!(concat!(env!("OUT_DIR"), "/key_package_versions.rs"));
189
190#[cfg(test)]
191mod tests {
192 use super::resolve_release_codename;
193
194 #[test]
195 fn test_debian() {
196 assert_eq!("sid", resolve_release_codename("debian/sid", None).unwrap());
197 assert_eq!("sid", resolve_release_codename("sid", None).unwrap());
198 assert_eq!("sid", resolve_release_codename("unstable", None).unwrap());
199 assert_eq!(
200 "experimental",
201 resolve_release_codename("experimental", None).unwrap()
202 );
203 }
204
205 #[test]
206 fn test_ubuntu() {
207 assert_eq!(
208 "trusty",
209 resolve_release_codename("ubuntu/trusty", None).unwrap()
210 );
211 assert_eq!("trusty", resolve_release_codename("trusty", None).unwrap());
212 assert!(resolve_release_codename("ubuntu/lts", None).is_some());
213 }
214
215 #[test]
216 fn test_resolve_debian() {
217 assert_eq!("sid", resolve_release_codename("sid", None).unwrap());
218 assert_eq!("buster", resolve_release_codename("buster", None).unwrap());
219 assert_eq!("sid", resolve_release_codename("unstable", None).unwrap());
220 assert_eq!(
221 "sid",
222 resolve_release_codename("debian/unstable", None).unwrap()
223 );
224 assert!(resolve_release_codename("oldstable", None).is_some());
225 assert!(resolve_release_codename("oldoldstable", None).is_some());
226 }
227
228 #[test]
229 fn test_resolve_unknown() {
230 assert!(resolve_release_codename("blah", None).is_none());
231 }
232
233 #[test]
234 fn test_resolve_ubuntu() {
235 assert_eq!("trusty", resolve_release_codename("trusty", None).unwrap());
236 assert_eq!(
237 "trusty",
238 resolve_release_codename("ubuntu/trusty", None).unwrap()
239 );
240 assert!(resolve_release_codename("ubuntu/lts", None).is_some())
241 }
242
243 #[test]
244 fn test_resolve_ubuntu_esm() {
245 assert!(resolve_release_codename("ubuntu/esm", None).is_some())
246 }
247
248 #[test]
249 fn test_debhelper_versions() {
250 assert!(super::debhelper_versions.get("sid").is_some());
251 assert!(super::debhelper_versions.get("trixie").is_some());
252 }
253}