Skip to content

Commit ca00c90

Browse files
committed
Add version sort support
1 parent e02bf9e commit ca00c90

File tree

4 files changed

+143
-7
lines changed

4 files changed

+143
-7
lines changed

internal/filter/sort/sort.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"sort"
66

77
"github.com/wader/bump/internal/filter"
8+
"github.com/wader/bump/internal/versioncmp"
89
)
910

1011
// Name of filter
@@ -19,27 +20,54 @@ Sort versions reverse alphabetically.
1920
static:a,b,c|sort
2021
`[1:]
2122

23+
type sortType int
24+
25+
const (
26+
sortAlphabetical sortType = iota
27+
sortVersion
28+
)
29+
2230
// New sort filter
2331
func New(prefix string, arg string) (filter filter.Filter, err error) {
2432
if prefix != Name {
2533
return nil, nil
2634
}
27-
if arg != "" {
28-
return nil, fmt.Errorf("arg should be empty")
35+
var sortType sortType
36+
if arg == "" || arg == "alphabetical" {
37+
sortType = sortAlphabetical
38+
} else if arg == "version" {
39+
sortType = sortVersion
40+
} else {
41+
return nil, fmt.Errorf("arg should be empty, alphabetical or version")
2942
}
30-
return sortFilter{}, nil
43+
return sortFilter{sortType: sortType}, nil
3144
}
3245

33-
type sortFilter struct{}
46+
type sortFilter struct {
47+
sortType sortType
48+
}
3449

3550
func (f sortFilter) String() string {
3651
return Name
3752
}
3853

3954
func (f sortFilter) Filter(versions filter.Versions, versionKey string) (filter.Versions, string, error) {
4055
svs := append(filter.Versions{}, versions...)
41-
sort.Slice(svs, func(i int, j int) bool {
42-
return svs[i][versionKey] > svs[j][versionKey]
43-
})
56+
57+
switch f.sortType {
58+
case sortAlphabetical:
59+
sort.Slice(svs, func(i int, j int) bool {
60+
return svs[i][versionKey] < svs[j][versionKey]
61+
})
62+
case sortVersion:
63+
sort.Slice(svs, func(i int, j int) bool {
64+
return !versioncmp.Cmp(svs[i][versionKey], svs[j][versionKey])
65+
})
66+
default:
67+
panic("unreachable")
68+
}
69+
70+
// svs = slicex.Reverse(svs)
71+
4472
return svs, versionKey, nil
4573
}

internal/slicex/slicex.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,12 @@ func Unique[T comparable](s []T) []T {
2121
}
2222
return us
2323
}
24+
25+
func Reverse[T any](s []T) []T {
26+
rs := make([]T, len(s))
27+
l := len(s)
28+
for i, v := range s {
29+
rs[l-i-1] = v
30+
}
31+
return rs
32+
}

internal/versioncmp/versioncmp.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package versioncmp
2+
3+
import (
4+
"strconv"
5+
"unicode"
6+
)
7+
8+
func Split(a string) []any {
9+
if len(a) == 0 {
10+
return nil
11+
}
12+
13+
lastIsDigit := unicode.IsDigit(rune(a[0]))
14+
lastIndex := 0
15+
var parts []any
16+
17+
add := func(isNumber bool, s string) {
18+
if isNumber {
19+
n, _ := strconv.ParseInt(s, 10, 64)
20+
parts = append(parts, n)
21+
} else {
22+
parts = append(parts, s)
23+
}
24+
}
25+
26+
for i, r := range a[1:] {
27+
isDigit := unicode.IsDigit(r)
28+
if isDigit != lastIsDigit {
29+
add(lastIsDigit, a[lastIndex:i+1])
30+
lastIsDigit = isDigit
31+
lastIndex = i + 1
32+
continue
33+
}
34+
}
35+
36+
if lastIndex != len(a) {
37+
add(lastIsDigit, a[lastIndex:])
38+
}
39+
40+
return parts
41+
}
42+
43+
func Cmp(a, b string) bool {
44+
ap := Split(a)
45+
bp := Split(b)
46+
for i := 0; i < len(ap) && i < len(bp); i++ {
47+
ae := ap[i]
48+
be := bp[i]
49+
50+
switch ae := ae.(type) {
51+
case int64:
52+
switch be := be.(type) {
53+
case int64:
54+
if ae == be {
55+
continue
56+
}
57+
return ae < be
58+
default:
59+
return true
60+
}
61+
case string:
62+
switch be := be.(type) {
63+
case string:
64+
if ae == be {
65+
continue
66+
}
67+
return ae < be
68+
default:
69+
return false
70+
}
71+
}
72+
}
73+
74+
return len(ap) <= len(bp)
75+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package versioncmp_test
2+
3+
import (
4+
"log"
5+
"sort"
6+
"testing"
7+
8+
"github.com/wader/bump/internal/versioncmp"
9+
)
10+
11+
func TestCmp(t *testing.T) {
12+
13+
// s := []string{"ab.22.cc", "ab.11.dd", "ab.11.dd"}
14+
15+
s := []string{"1_9_13p2", "1_9_13", "1_9_11"}
16+
17+
log.Printf("b: %#+v\n", s)
18+
19+
sort.SliceStable(s, func(i, j int) bool {
20+
return versioncmp.Cmp(s[i], s[j])
21+
})
22+
23+
log.Printf("a: %#+v\n", s)
24+
}

0 commit comments

Comments
 (0)