debian/version: dpkg-compatible version comparison
Implement the documented dpkg ordering algorithm (Debian Policy 5.6.1): numeric epoch, then upstream/revision compared as alternating non-digit and digit chunks, with '~' ordering before anything including the empty chunk and letters before non-letters in non-digit chunks. Adds Ord/PartialOrd for DebianVersion, a free compare() and a later_than() convenience. Unit tests port all vectors from dpkg's scripts/t/Dpkg_Version.t plus Ubuntu-flavored cases (security uploads, ~ppa1 backports). Differential gate: every vector cross-checked against real 'dpkg --compare-versions' for <<, <=, =, >= and >>.
This commit is contained in:
@@ -909,6 +909,46 @@ mod differential_tests {
|
||||
diff_arch_env_one(None);
|
||||
}
|
||||
|
||||
/// Differential check of [`crate::debian::version`] against real
|
||||
/// `dpkg --compare-versions` over every ported dpkg test vector and
|
||||
/// every relation operator.
|
||||
#[test]
|
||||
fn diff_version_compare_against_dpkg() {
|
||||
let vectors = crate::debian::version::test_vectors::COMPARE;
|
||||
assert!(!vectors.is_empty());
|
||||
for (a, b, expected) in vectors {
|
||||
let va = crate::debian::DebianVersion::parse(a)
|
||||
.unwrap_or_else(|e| panic!("parse {a}: {e}"));
|
||||
let vb = crate::debian::DebianVersion::parse(b)
|
||||
.unwrap_or_else(|e| panic!("parse {b}: {e}"));
|
||||
let ours = match va.cmp(&vb) {
|
||||
std::cmp::Ordering::Less => -1,
|
||||
std::cmp::Ordering::Equal => 0,
|
||||
std::cmp::Ordering::Greater => 1,
|
||||
};
|
||||
assert_eq!(ours, *expected, "native compare: {a} cmp {b}");
|
||||
|
||||
// Cross-check the relation operators against the real tool.
|
||||
for (op, holds) in [
|
||||
("<<", *expected < 0),
|
||||
("<=", *expected <= 0),
|
||||
("=", *expected == 0),
|
||||
(">=", *expected >= 0),
|
||||
(">>", *expected > 0),
|
||||
] {
|
||||
let output = Command::new("dpkg")
|
||||
.args(["--compare-versions", "--", a, op, b])
|
||||
.status()
|
||||
.expect("run dpkg --compare-versions");
|
||||
assert_eq!(
|
||||
output.success(),
|
||||
holds,
|
||||
"dpkg --compare-versions -- {a} {op} {b}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_native_minimal() {
|
||||
differential_case(&FixtureSpec::new("pkh-diff-a", "1.0-1", "unstable"));
|
||||
|
||||
Reference in New Issue
Block a user