Skip to content

Commit

Permalink
Add version sort support
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Jun 16, 2023
1 parent e02bf9e commit ca00c90
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 7 deletions.
42 changes: 35 additions & 7 deletions internal/filter/sort/sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"sort"

"github.com/wader/bump/internal/filter"
"github.com/wader/bump/internal/versioncmp"
)

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

type sortType int

const (
sortAlphabetical sortType = iota
sortVersion
)

// New sort filter
func New(prefix string, arg string) (filter filter.Filter, err error) {
if prefix != Name {
return nil, nil
}
if arg != "" {
return nil, fmt.Errorf("arg should be empty")
var sortType sortType
if arg == "" || arg == "alphabetical" {
sortType = sortAlphabetical
} else if arg == "version" {
sortType = sortVersion
} else {
return nil, fmt.Errorf("arg should be empty, alphabetical or version")
}
return sortFilter{}, nil
return sortFilter{sortType: sortType}, nil
}

type sortFilter struct{}
type sortFilter struct {
sortType sortType
}

func (f sortFilter) String() string {
return Name
}

func (f sortFilter) Filter(versions filter.Versions, versionKey string) (filter.Versions, string, error) {
svs := append(filter.Versions{}, versions...)
sort.Slice(svs, func(i int, j int) bool {
return svs[i][versionKey] > svs[j][versionKey]
})

switch f.sortType {
case sortAlphabetical:
sort.Slice(svs, func(i int, j int) bool {
return svs[i][versionKey] < svs[j][versionKey]
})
case sortVersion:
sort.Slice(svs, func(i int, j int) bool {
return !versioncmp.Cmp(svs[i][versionKey], svs[j][versionKey])
})
default:
panic("unreachable")
}

// svs = slicex.Reverse(svs)

return svs, versionKey, nil
}
9 changes: 9 additions & 0 deletions internal/slicex/slicex.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@ func Unique[T comparable](s []T) []T {
}
return us
}

func Reverse[T any](s []T) []T {
rs := make([]T, len(s))
l := len(s)
for i, v := range s {
rs[l-i-1] = v
}
return rs
}
75 changes: 75 additions & 0 deletions internal/versioncmp/versioncmp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package versioncmp

import (
"strconv"
"unicode"
)

func Split(a string) []any {
if len(a) == 0 {
return nil
}

lastIsDigit := unicode.IsDigit(rune(a[0]))
lastIndex := 0
var parts []any

add := func(isNumber bool, s string) {
if isNumber {
n, _ := strconv.ParseInt(s, 10, 64)
parts = append(parts, n)
} else {
parts = append(parts, s)
}
}

for i, r := range a[1:] {
isDigit := unicode.IsDigit(r)
if isDigit != lastIsDigit {
add(lastIsDigit, a[lastIndex:i+1])
lastIsDigit = isDigit
lastIndex = i + 1
continue
}
}

if lastIndex != len(a) {
add(lastIsDigit, a[lastIndex:])
}

return parts
}

func Cmp(a, b string) bool {
ap := Split(a)
bp := Split(b)
for i := 0; i < len(ap) && i < len(bp); i++ {
ae := ap[i]
be := bp[i]

switch ae := ae.(type) {
case int64:
switch be := be.(type) {
case int64:
if ae == be {
continue
}
return ae < be
default:
return true
}
case string:
switch be := be.(type) {
case string:
if ae == be {
continue
}
return ae < be
default:
return false
}
}
}

return len(ap) <= len(bp)
}
24 changes: 24 additions & 0 deletions internal/versioncmp/versioncmp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package versioncmp_test

import (
"log"
"sort"
"testing"

"github.com/wader/bump/internal/versioncmp"
)

func TestCmp(t *testing.T) {

// s := []string{"ab.22.cc", "ab.11.dd", "ab.11.dd"}

s := []string{"1_9_13p2", "1_9_13", "1_9_11"}

log.Printf("b: %#+v\n", s)

sort.SliceStable(s, func(i, j int) bool {
return versioncmp.Cmp(s[i], s[j])
})

log.Printf("a: %#+v\n", s)
}

0 comments on commit ca00c90

Please sign in to comment.