chlog: drop a trailing buildN before appending ubuntu1

An Ubuntu upload of a package sitting at X-2build1 produced
X-2build1ubuntu1: the blind append misrepresents the lineage and,
sorting below the proper X-2ubuntu1, could never supersede it. A real
change on top of a rebuild replaces the marker instead, so the
trailing buildN is now stripped before the ubuntu counter is appended
or incremented: X-2build1 becomes X-2ubuntu1, X-2ubuntu1build1
becomes X-2ubuntu2.
This commit is contained in:
2026-09-22 13:00:40 +02:00
parent 5a1c1672cd
commit cc5bbd2297
+65 -2
View File
@@ -137,7 +137,9 @@ pub async fn generate_entry(
enum Bump {
/// Regular upload: increment the trailing number
Normal,
/// Ubuntu upload: `1.0-9` becomes `1.0-9ubuntu1`
/// Ubuntu upload: `1.0-9` becomes `1.0-9ubuntu1`; a trailing
/// no-change-rebuild marker is dropped first (`1.0-9build1` becomes
/// `1.0-9ubuntu1`)
Ubuntu,
/// Non-maintainer upload: `1.0-1` becomes `1.0-1.1`, native `1.0`
/// becomes `1.0+nmu1`
@@ -158,7 +160,7 @@ fn compute_new_version(
bump: Bump,
) -> Result<String, Box<dyn std::error::Error>> {
match bump {
Bump::Ubuntu => increment_suffix(old_version, "ubuntu"),
Bump::Ubuntu => increment_suffix(strip_build_suffix(old_version), "ubuntu"),
Bump::Rebuild => increment_suffix(old_version, "build"),
Bump::Nmu => {
if old_version.contains('-') {
@@ -177,6 +179,19 @@ fn compute_new_version(
}
}
/// The version an Ubuntu upload is numbered from: a trailing
/// no-change-rebuild marker is dropped, because a real change on top of a
/// rebuild replaces the marker rather than appending to it — `X-2build1`
/// becomes `X-2ubuntu1`, where an appended `X-2build1ubuntu1` would
/// misrepresent the lineage and sort below `X-2ubuntu1`
fn strip_build_suffix(version: &str) -> &str {
let stem = version.trim_end_matches(|c: char| c.is_ascii_digit());
match stem.strip_suffix("build") {
Some(base) if stem.len() < version.len() => &version[..base.len()],
_ => version,
}
}
/// The version bump a regular ([`EntryKind::Normal`]) upload gets, derived
/// from the vendor of the target series: Ubuntu series number their uploads
/// the Ubuntu way (`1.0-1` becomes `1.0-1ubuntu1`), everything else —
@@ -1139,6 +1154,22 @@ mod tests {
compute_new_version("15.2.0-9ubuntu1", Bump::Ubuntu).unwrap(),
"15.2.0-9ubuntu2"
);
// Ubuntu upload on top of a rebuild drops the buildN marker:
// appending would give 15.2.0-9build1ubuntu1, which sorts below
// the proper 15.2.0-9ubuntu1
assert_eq!(
compute_new_version("15.2.0-9build1", Bump::Ubuntu).unwrap(),
"15.2.0-9ubuntu1"
);
assert_eq!(
compute_new_version("15.2.0-9ubuntu1build1", Bump::Ubuntu).unwrap(),
"15.2.0-9ubuntu2"
);
// Native packages
assert_eq!(
compute_new_version("15.2.0build1", Bump::Ubuntu).unwrap(),
"15.2.0ubuntu1"
);
// No change rebuild
assert_eq!(
@@ -1395,6 +1426,38 @@ mod tests {
assert_eq!(entry.new_version, "1.0-1ubuntu2");
}
/// An Ubuntu upload of a package whose changelog carries a rebuild
/// version drops the buildN marker: 1.0-1build1 numbers the next entry
/// 1.0-1ubuntu1 (1.0-1build1ubuntu1 would sort below 1.0-1ubuntu1).
/// Relies on the host distro-info data listing noble (see the
/// distro_info tests). The git repo provides the maintainer identity:
/// DEBFULLNAME/DEBEMAIL are process-global and other tests mutate them
/// in parallel.
#[tokio::test]
async fn test_generate_entry_ubuntu_series_numbering_after_rebuild() {
let temp_dir = TempDir::new().unwrap();
let repo_dir = temp_dir.path();
setup_repo(repo_dir);
let changelog_path = repo_dir.join("debian/changelog");
std::fs::create_dir_all(repo_dir.join("debian")).unwrap();
std::fs::write(
&changelog_path,
"mypackage (1.0-1build1) noble; urgency=medium\n\n * Initial release\n\n -- Maintainer <m@e.com> Wed, 01 Jan 2020 00:00:00 +0000\n",
)
.unwrap();
let entry = generate_entry(
"debian/changelog",
Some(repo_dir),
None,
Some("noble"),
EntryKind::Normal,
)
.await
.unwrap();
assert_eq!(entry.new_version, "1.0-1ubuntu1");
}
#[test]
fn test_get_maintainer_info() {
let _identity = IDENTITY_LOCK.blocking_lock();