distro_info: match changelog suite names with their series
Debian packages conventionally target 'unstable' in their debian/changelog distribution field, but the series data (the distro-info CSVs) only knows codenames: the suite is the alias 'unstable' of the series 'sid', a mapping the debian-distro-info tool resolves internally without exposing it in its data. Add a per-dist suite_aliases reference-data key (debian: unstable -> sid), with two helpers on top: resolve_suite_alias, identifying a changelog suite name with its series codename and the dist that codename belongs to, and series_suite_alias, the inverse direction. The two names identify the same series.
This commit is contained in:
@@ -28,6 +28,12 @@
|
||||
## series (`<series>-updates`, ...). Deliberately not the
|
||||
## `pockets` key: that one is the *search order* of pull,
|
||||
## where backports must not fold in.
|
||||
## suite_aliases: the changelog suite names that alias a series
|
||||
## codename: Debian packages conventionally target
|
||||
## 'unstable' where the series data carries 'sid'.
|
||||
## Mapped suite name -> series codename; the two
|
||||
## names identify the same series, and the selector
|
||||
## offers the aliased entry as '<suite> (<series>)'.
|
||||
## build_profiles: the vendor's default DEB_BUILD_PROFILES (Ubuntu
|
||||
## activates derivative.ubuntu noudeb, Debian none),
|
||||
## mirroring what Dpkg::BuildProfiles resolves when the
|
||||
@@ -47,6 +53,10 @@ dist:
|
||||
- updates
|
||||
- security
|
||||
- proposed-updates
|
||||
# Debian changelogs conventionally target 'unstable'; the series data
|
||||
# knows the same series as 'sid'.
|
||||
suite_aliases:
|
||||
unstable: sid
|
||||
sections:
|
||||
# Valid Section values for debian/control: the Debian policy section
|
||||
# list unioned with the sections observed in the live Ubuntu archive.
|
||||
|
||||
@@ -87,6 +87,11 @@ struct DistData {
|
||||
cross_pockets: Vec<String>,
|
||||
#[serde(default)]
|
||||
build_profiles: Vec<String>,
|
||||
/// Changelog suite names aliasing a distro-info series codename
|
||||
/// ('unstable' for Debian's 'sid'): the two names identify the same
|
||||
/// series ([`series_suite_alias`], [`resolve_suite_alias`])
|
||||
#[serde(default)]
|
||||
suite_aliases: HashMap<String, String>,
|
||||
series: SeriesInfo,
|
||||
}
|
||||
|
||||
@@ -413,6 +418,30 @@ pub async fn get_dist_from_series(series: &str) -> Result<String, Box<dyn Error>
|
||||
Err(format!("Unknown series: {}", series).into())
|
||||
}
|
||||
|
||||
/// The changelog suite name that aliases the series codename of `dist`
|
||||
/// (Debian's 'unstable' for 'sid'): the two names identify the same
|
||||
/// series. `None` when the series carries no suite alias.
|
||||
pub fn series_suite_alias(dist: &str, series: &str) -> Option<String> {
|
||||
dist_data(dist)
|
||||
.ok()?
|
||||
.suite_aliases
|
||||
.iter()
|
||||
.find(|(_suite, codename)| codename.as_str() == series)
|
||||
.map(|(suite, _)| suite.clone())
|
||||
}
|
||||
|
||||
/// Identify a changelog suite name with the distro-info series codename
|
||||
/// it aliases (Debian's 'unstable' is 'sid'), and the dist that codename
|
||||
/// belongs to. `None` when `suite` is not a known alias of any dist.
|
||||
pub fn resolve_suite_alias(suite: &str) -> Option<(String, String)> {
|
||||
for (dist, data) in DATA.dist.iter() {
|
||||
if let Some(codename) = data.suite_aliases.get(suite) {
|
||||
return Some((dist.clone(), codename.clone()));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Get the package pockets available for a given distribution, in search order
|
||||
///
|
||||
/// The main archive ('') comes first so that a search without an explicit
|
||||
@@ -1035,6 +1064,41 @@ mod tests {
|
||||
assert!(series.contains(&"jammy".to_string()));
|
||||
}
|
||||
|
||||
/// Suite aliases identify a changelog suite name with the series
|
||||
/// codename of the same series: Debian's 'unstable' is 'sid'
|
||||
#[test]
|
||||
fn test_suite_aliases() {
|
||||
assert_eq!(
|
||||
resolve_suite_alias("unstable"),
|
||||
Some(("debian".to_string(), "sid".to_string()))
|
||||
);
|
||||
// A series codename or unknown suite is not an alias
|
||||
assert_eq!(resolve_suite_alias("sid"), None);
|
||||
assert_eq!(resolve_suite_alias("noble"), None);
|
||||
assert_eq!(
|
||||
series_suite_alias("debian", "sid"),
|
||||
Some("unstable".to_string())
|
||||
);
|
||||
assert_eq!(series_suite_alias("debian", "trixie"), None);
|
||||
assert_eq!(series_suite_alias("ubuntu", "noble"), None);
|
||||
}
|
||||
|
||||
/// Every suite alias must map to a real series of its dist, or the
|
||||
/// selector would offer a phantom entry
|
||||
#[tokio::test]
|
||||
async fn test_suite_aliases_target_real_series() {
|
||||
for (dist, data) in DATA.dist.iter() {
|
||||
for (suite, codename) in &data.suite_aliases {
|
||||
let series = get_ordered_series_name(dist).await.unwrap_or_default();
|
||||
assert!(
|
||||
series.contains(codename),
|
||||
"suite alias '{suite}' of {dist} maps to '{codename}', \
|
||||
which is not a known series"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_dist_from_series() {
|
||||
assert_eq!(get_dist_from_series("sid").await.unwrap(), "debian");
|
||||
|
||||
Reference in New Issue
Block a user