From ab3899f656405f958222484054dba90f6bb92243 Mon Sep 17 00:00:00 2001 From: Sameer Date: Tue, 31 Mar 2026 11:53:03 +0530 Subject: [PATCH] fix: refine stability precedence to support standard prerelease sorting Signed-off-by: Sameer --- v4/semver.go | 28 ++++++---------------------- v4/semver_test.go | 10 ++++++++++ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/v4/semver.go b/v4/semver.go index a654035..af8d22d 100644 --- a/v4/semver.go +++ b/v4/semver.go @@ -470,21 +470,19 @@ func (v versionExtension) Compare(o versionExtension) int { // 2. Handle Numeric vs Alphanumeric // Identify segments containing pre-release identifiers (rc, alpha, beta). - isPreReleaseLabel := func(s string) bool { - sl := strings.ToLower(s) - return strings.Contains(sl, "rc") || (strings.Contains(sl, "-") && - (strings.Contains(sl, "alpha") || strings.Contains(sl, "beta"))) + isStabilityLabel := func(s string) bool { + return strings.Contains(s, "-") } if v.IsNum && !o.IsNum { - if isPreReleaseLabel(o.VersionStr) { - return 1 // Stability Priority: Stable > Pre-release + if isStabilityLabel(o.VersionStr) { + return 1 // Number wins against an RC/Alpha/Beta string } return -1 // Standard SemVer: Number < String } if !v.IsNum && o.IsNum { - if isPreReleaseLabel(v.VersionStr) { - return -1 // Stability Priority: Pre-release < Stable + if isStabilityLabel(v.VersionStr) { + return -1 // RC/Alpha/Beta string loses against a Number } return 1 // Standard SemVer: String > Number } @@ -494,20 +492,6 @@ func (v versionExtension) Compare(o versionExtension) int { return 0 } - // Pre-release marker check for string-vs-string - isPre := func(s string) bool { - sl := strings.ToLower(s) - return strings.Contains(sl, "rc") || strings.Contains(sl, "alpha") || strings.Contains(sl, "beta") - } - - preV, preO := isPre(v.VersionStr), isPre(o.VersionStr) - if preV != preO { - if preV { - return -1 - } - return 1 - } - // Natural sort fallback for generic segments (e.g. "9-fips" vs "10-fips") if naturalLess(v.VersionStr, o.VersionStr) { return -1 diff --git a/v4/semver_test.go b/v4/semver_test.go index 835f9f2..5fb917c 100644 --- a/v4/semver_test.go +++ b/v4/semver_test.go @@ -597,6 +597,16 @@ func TestEdgeCases_NaturalSortAndMetadata(t *testing.T) { // 3. Mixed Alphanumeric: abc2 should be less than abc10 {"1.0.0+abc2", "1.0.0+abc10", -1, "Natural sort: abc2 should be less than abc10"}, + + // 4. Vendir Compatibility (The new case pre < rc) + {"0.0.1-pre.1", "0.0.1-rc.0", -1, "Vendir: pre < rc alphabetically"}, + + // 5. Standard SemVer: Numeric segments are always less than alphanumeric ones + // Compares segment '1' (Numeric) vs segment 'beta' (Alphanumeric) + {"1.0.0-alpha.1", "1.0.0-alpha.beta", -1, "Standard: numeric < alphanumeric"}, + + // 6. Stability Check: Ensure alpha/beta without hyphens follow standard rules + {"1.0.0-beta", "1.0.0-rc", -1, "Standard: beta < rc alphabetically as segments have no internal hyphens"}, } for _, tt := range tests {