Skip to content

Commit

Permalink
Merge pull request #158 from initia-labs/fix/new-compare-sem-ver
Browse files Browse the repository at this point in the history
fix: compare semver standard
  • Loading branch information
Benzbeeb authored Mar 11, 2025
2 parents f9dd081 + 888d7d1 commit 96c04ab
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 18 deletions.
52 changes: 46 additions & 6 deletions cosmosutils/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,13 @@ func SortVersions(versions BinaryVersionWithDownloadURL) []string {
return versionTags
}

// CompareSemVer compares two semantic version strings and returns true if v1 should be ordered before v2
// CompareSemVer compares two semantic version strings and returns true if v1 is greater than v2.
// Examples:
// - CompareSemVer("v2.0.0", "v1.0.0") returns true
// - CompareSemVer("v1.2.0", "v1.1.0") returns true
// - CompareSemVer("v1.0.0", "v1.0.0-beta") returns true
// - CompareSemVer("v1.0.0-beta.2", "v1.0.0-beta.1") returns true
// - CompareSemVer("v1.0.0", "v2.0.0") returns false
func CompareSemVer(v1, v2 string) bool {
// Trim "v" prefix
v1 = strings.TrimPrefix(v1, "v")
Expand All @@ -237,15 +243,49 @@ func CompareSemVer(v1, v2 string) bool {
}
}

// Compare pre-release parts if main versions are equal
// A pre-release version is always ordered greater than the normal version
// If main versions are equal, handle pre-release versions
// A pre-release version has lower precedence than the normal version
if v1Pre == "" && v2Pre != "" {
return false
return true // v1 (normal version) is greater
}
if v1Pre != "" && v2Pre == "" {
return true
return false // v2 (normal version) is greater
}
return v1Pre > v2Pre

// If both have pre-release versions, compare them
if v1Pre != "" && v2Pre != "" {
v1PreParts := strings.Split(v1Pre, ".")
v2PreParts := strings.Split(v2Pre, ".")

// Compare each pre-release identifier
minLen := len(v1PreParts)
if len(v2PreParts) < minLen {
minLen = len(v2PreParts)
}

for i := 0; i < minLen; i++ {
// Try to compare as integers first
v1Int, v1IsInt := strconv.Atoi(v1PreParts[i])
v2Int, v2IsInt := strconv.Atoi(v2PreParts[i])

if v1IsInt == nil && v2IsInt == nil {
// Both are integers
if v1Int != v2Int {
return v1Int > v2Int
}
} else {
// Compare as strings if not both integers
if v1PreParts[i] != v2PreParts[i] {
return v1PreParts[i] > v2PreParts[i]
}
}
}

// If all parts so far are equal, longer one is greater
return len(v1PreParts) > len(v2PreParts)
}

return false // versions are exactly equal
}

// splitVersion separates the main version (e.g., "0.4.11") from the pre-release (e.g., "Binarytion.1")
Expand Down
33 changes: 21 additions & 12 deletions cosmosutils/binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,6 @@ func TestCompareSemVer(t *testing.T) {
v2: "1.0.0",
expected: false,
},
{
v1: "1.0.0",
v2: "1.0.0-1",
expected: false,
},
{
v1: "1.0.0-2",
v2: "1.0.0-1",
expected: true,
},
{
v1: "1.2.0",
v2: "1.1.9",
Expand All @@ -54,10 +44,29 @@ func TestCompareSemVer(t *testing.T) {
expected: false,
},
{
v1: "1.0.0",
v2: "1.0.0-2",
name: "complex prerelease identifiers",
v1: "1.0.0-alpha.2",
v2: "1.0.0-alpha.1",
expected: true,
},
{
name: "complex prerelease identifiers reverse",
v1: "1.0.0-alpha.1",
v2: "1.0.0-alpha.2",
expected: false,
},
{
name: "different prerelease identifiers",
v1: "1.0.0-beta.1",
v2: "1.0.0-alpha.2",
expected: true,
},
{
name: "release vs complex prerelease",
v1: "1.0.0",
v2: "1.0.0-beta.1",
expected: true,
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 96c04ab

Please sign in to comment.