Add sorting for prefixed semver

Strips non-numeric prefixes when checking semver. This also adds a
secondary layer to the sort whereby identical semvers are sorted
relative to eachother lexigraphically.

This will ensure a more stable sort for non-versioned tags (eg. `latest`
or `edge`) as well as multiple variants tagged with the same number.
(eg `1.0.0-alpine` compared to `1.0.0-ubuntu`).

Fixes #758
This commit is contained in:
Ian Fijolek
2023-01-13 15:03:24 -08:00
parent 463130b67f
commit e974fbbc2c
2 changed files with 21 additions and 4 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
"unicode"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
) )
@@ -22,9 +23,9 @@ func SortTags(tags []string, sortTag SortTag) []string {
return tags return tags
case SortTagSemver: case SortTagSemver:
semverIsh := func(s string) string { semverIsh := func(s string) string {
if semver.IsValid(s) { s = strings.TrimLeftFunc(s, func(r rune) bool {
return s return !unicode.IsNumber(r)
} })
if vt := fmt.Sprintf("v%s", s); semver.IsValid(vt) { if vt := fmt.Sprintf("v%s", s); semver.IsValid(vt) {
return vt return vt
} }
@@ -36,7 +37,13 @@ func SortTags(tags []string, sortTag SortTag) []string {
} else if c < 0 { } else if c < 0 {
return false return false
} }
return strings.Count(tags[i], ".") > strings.Count(tags[j], ".") if c := strings.Count(tags[i], ".") - strings.Count(tags[j], "."); c > 0 {
return true
} else if c < 0 {
return false
}
return strings.Compare(tags[i], tags[j]) < 0
}) })
return tags return tags
default: default:

View File

@@ -60,6 +60,8 @@ func TestTagsSort(t *testing.T) {
"4.8.0", "4.8.0",
"4.8.1", "4.8.1",
"4.9.0", "4.9.0",
"ubuntu-5.0",
"alpine-5.0",
"edge", "edge",
"latest", "latest",
} }
@@ -103,6 +105,8 @@ func TestTagsSort(t *testing.T) {
"4.8.0", "4.8.0",
"4.8.1", "4.8.1",
"4.9.0", "4.9.0",
"ubuntu-5.0",
"alpine-5.0",
"edge", "edge",
"latest", "latest",
}, },
@@ -141,16 +145,20 @@ func TestTagsSort(t *testing.T) {
"4.8.0", "4.8.0",
"4.8.1", "4.8.1",
"4.9.0", "4.9.0",
"alpine-5.0",
"edge", "edge",
"latest", "latest",
"ubuntu-5.0",
}, },
}, },
{ {
name: "sort reverse", name: "sort reverse",
sortTag: registry.SortTagReverse, sortTag: registry.SortTagReverse,
expected: []string{ expected: []string{
"ubuntu-5.0",
"latest", "latest",
"edge", "edge",
"alpine-5.0",
"4.9.0", "4.9.0",
"4.8.1", "4.8.1",
"4.8.0", "4.8.0",
@@ -187,6 +195,8 @@ func TestTagsSort(t *testing.T) {
name: "sort semver", name: "sort semver",
sortTag: registry.SortTagSemver, sortTag: registry.SortTagSemver,
expected: []string{ expected: []string{
"alpine-5.0",
"ubuntu-5.0",
"4.21.0", "4.21.0",
"4.21", "4.21",
"4.20.1", "4.20.1",