3.0 KiB
3.0 KiB
Here’s a quick heads‑up that saves a ton of pain when sorting package versions on RHEL/Fedora/SUSE‑style systems: never compare RPM versions as plain strings. RPM compares EVR — Epoch:Version-Release — left‑to‑right, and if epochs differ, it stops right there. Missing epoch is treated as 0. Backports (e.g., old Version with higher Release) and vendor epochs will break naive compares. Use an rpmvercmp‑equivalent and persist versions as a 3‑tuple (epoch, version, release). (RPM)
Why this matters
1:1.0-1>0:2.0-100because1(epoch) beats everything after. (RPM)- Fedora/Red Hat guidelines explicitly say EVR ordering governs upgrade paths; epochs are the most significant input and shouldn’t be removed once added. (Fedora Docs)
Correct approach (any language)
- Parse to NEVRA (Name, Epoch, Version, Release, Arch), then compare by EVR using rpm’s algorithm; don’t roll your own string logic. (Docs.rs)
- If you can’t link against librpm, use a well‑known rpmvercmp implementation for your stack. Python and PHP have ready helpers. (PyPI)
Drop‑in options
- Python:
rpm-vercmp(pure Python) for EVR compares. Storeepochas int (default0),version/releaseas strings, and call the comparator. (PyPI) - .NET/C#: no official rpmvercmp, but mirror the spec: split EVR, compare epochs numerically; for
version/release, compare segment‑by‑segment using rpm rules (alphanumeric runs; numeric segments compare as integers; tildes sort before anything, etc.). (Spec summary in rpm‑version(7).) (RPM) - Rust/Go: model NEVRA (existing crates/docs show structure) and wire a comparator consistent with rpmvercmp. (Docs.rs)
Practical tips for your pipelines
- Persist EVR, not strings like
“1.2.3-4.el9”. Keepepochexplicitly; don’t drop0. (Fedora Docs) - Normalize inputs (e.g., from
rpm -qvsrepoquery) so missing epochs don’t cause mismatches. (CPAN) - Backport‑aware sorting: rely on EVR, not semver. Semver comparisons will misorder distro backports. (Fedora docs highlight EVR as authoritative.) (Red Hat Docs)
If you want, I can sketch a tiny C# RpmEvrComparer tailored to your .NET 10 repos and wire it into your SBOM/VEX flows so Feedser/Vexer sort updates correctly.