distro_info: add UNRELEASED series handling, use it in deb and chlog
This commit is contained in:
@@ -83,8 +83,20 @@ async fn build_binary_package_impl(
|
||||
let changelog_path = cwd.join("debian/changelog");
|
||||
let (package, version, package_series) =
|
||||
crate::changelog::parse_changelog_header(&changelog_path)?;
|
||||
// UNRELEASED is not a real archive series: without an explicit --series,
|
||||
// build against the development series of the host vendor's distribution
|
||||
// instead. An explicit --series always wins.
|
||||
let resolved_series;
|
||||
let series = if let Some(s) = series {
|
||||
s
|
||||
} else if crate::distro_info::is_unreleased(&package_series) {
|
||||
let dist = crate::build::env::current_vendor();
|
||||
resolved_series = crate::distro_info::effective_series(&package_series, &dist).await?;
|
||||
log::info!(
|
||||
"Changelog is UNRELEASED, building against series {}",
|
||||
resolved_series
|
||||
);
|
||||
resolved_series.as_str()
|
||||
} else {
|
||||
&package_series
|
||||
};
|
||||
|
||||
@@ -169,6 +169,16 @@ pub fn supported_dists() -> Vec<String> {
|
||||
DATA.dist.keys().cloned().collect()
|
||||
}
|
||||
|
||||
/// Special changelog distribution marking an entry that has not been
|
||||
/// released to any archive series yet
|
||||
pub const UNRELEASED: &str = "UNRELEASED";
|
||||
|
||||
/// Whether `series` is the special [`UNRELEASED`] distribution rather than
|
||||
/// a real archive series
|
||||
pub fn is_unreleased(series: &str) -> bool {
|
||||
series == UNRELEASED
|
||||
}
|
||||
|
||||
/// Get time-ordered list of series information for a distribution, development series first
|
||||
pub async fn get_ordered_series(dist: &str) -> Result<Vec<SeriesInformation>, Box<dyn Error>> {
|
||||
let dist_data = DATA.dist.get(dist).ok_or_else(|| {
|
||||
@@ -206,6 +216,24 @@ pub async fn get_ordered_series_name(dist: &str) -> Result<Vec<String>, Box<dyn
|
||||
Ok(series.iter().map(|info| info.series.clone()).collect())
|
||||
}
|
||||
|
||||
/// The series to actually target when the changelog says [`UNRELEASED`]:
|
||||
/// the development series of `dist`, i.e. the first entry of
|
||||
/// [`get_ordered_series_name`] (which is documented "development series
|
||||
/// first"). UNRELEASED work conventionally targets the next release, not
|
||||
/// the last stable one. Any other `series` is returned unchanged. Errors
|
||||
/// when `dist` is unknown or has no series list.
|
||||
pub async fn effective_series(series: &str, dist: &str) -> Result<String, Box<dyn Error>> {
|
||||
if !is_unreleased(series) {
|
||||
return Ok(series.to_string());
|
||||
}
|
||||
|
||||
get_ordered_series_name(dist)
|
||||
.await?
|
||||
.into_iter()
|
||||
.next()
|
||||
.ok_or_else(|| format!("Distribution '{}' has no series to target", dist).into())
|
||||
}
|
||||
|
||||
/// Get the latest released series for a dist (excluding future releases and special cases like sid)
|
||||
pub async fn get_latest_released_series(dist: &str) -> Result<String, Box<dyn Error>> {
|
||||
let latest = get_n_latest_released_series(dist, 1).await?;
|
||||
@@ -523,6 +551,52 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_unreleased() {
|
||||
// Matching is exact: UNRELEASED is uppercase by Debian convention
|
||||
assert!(is_unreleased("UNRELEASED"));
|
||||
assert!(!is_unreleased("unreleased"));
|
||||
assert!(!is_unreleased("noble"));
|
||||
assert!(!is_unreleased(""));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_effective_series_passthrough() {
|
||||
// A real series is returned unchanged, and the dist is not even
|
||||
// looked up (an unknown dist only matters for UNRELEASED)
|
||||
assert_eq!(effective_series("noble", "ubuntu").await.unwrap(), "noble");
|
||||
assert_eq!(effective_series("sid", "debian").await.unwrap(), "sid");
|
||||
assert_eq!(
|
||||
effective_series("noble", "unknown-distro").await.unwrap(),
|
||||
"noble"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_effective_series_unreleased() {
|
||||
// UNRELEASED resolves to the development series of the dist, i.e.
|
||||
// the first entry of the time-ordered list. On current distro-info
|
||||
// data this is the next Ubuntu release, while Debian's list starts
|
||||
// with 'experimental' (sid comes second), so assert against the
|
||||
// data itself rather than a hardcoded name.
|
||||
for dist in ["ubuntu", "debian"] {
|
||||
let ordered = get_ordered_series_name(dist).await.unwrap();
|
||||
let resolved = effective_series(UNRELEASED, dist).await.unwrap();
|
||||
assert_eq!(resolved, ordered[0]);
|
||||
assert_ne!(resolved, UNRELEASED);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_effective_series_unknown_dist() {
|
||||
// UNRELEASED on an unknown distribution cannot be resolved
|
||||
assert!(
|
||||
effective_series(UNRELEASED, "unknown-distro")
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_debian_series() {
|
||||
let series = get_ordered_series_name("debian").await.unwrap();
|
||||
|
||||
+27
-2
@@ -198,14 +198,39 @@ fn main() {
|
||||
let changelog_path = cwd.join("debian/changelog");
|
||||
match pkh::changelog::parse_changelog_header(&changelog_path) {
|
||||
Ok((_pkg, _ver, current_series)) => {
|
||||
// Try to get the list of available series for this distribution
|
||||
// UNRELEASED is not a real series: offer it as a
|
||||
// pinned first entry (selecting it keeps the changelog
|
||||
// unreleased) on top of the current vendor's series
|
||||
// list, defaulting to the development series. Any
|
||||
// other series resolves through the series list of
|
||||
// its own distribution.
|
||||
match rt.block_on(async {
|
||||
if pkh::distro_info::is_unreleased(¤t_series) {
|
||||
let dist = pkh::build::env::current_vendor();
|
||||
let mut series_list =
|
||||
vec![pkh::distro_info::UNRELEASED.to_string()];
|
||||
series_list.extend(
|
||||
pkh::distro_info::get_ordered_series_name(&dist).await?,
|
||||
);
|
||||
Ok(series_list)
|
||||
} else {
|
||||
let dist =
|
||||
pkh::distro_info::get_dist_from_series(¤t_series).await?;
|
||||
pkh::distro_info::get_ordered_series_name(&dist).await
|
||||
}
|
||||
}) {
|
||||
Ok(series_list) => {
|
||||
match pkh::ui::select_series(&series_list, ¤t_series) {
|
||||
// Default to the development series (the
|
||||
// first real entry) when the changelog is
|
||||
// UNRELEASED, not to the pinned entry itself
|
||||
let default = if pkh::distro_info::is_unreleased(¤t_series)
|
||||
&& series_list.len() > 1
|
||||
{
|
||||
series_list[1].clone()
|
||||
} else {
|
||||
current_series.clone()
|
||||
};
|
||||
match pkh::ui::select_series(&series_list, &default) {
|
||||
Ok(selected) => Some(selected),
|
||||
Err(e) => {
|
||||
error!(
|
||||
|
||||
Reference in New Issue
Block a user