Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add version sort support #112

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 47 additions & 8 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,65 @@ Sort versions reverse alphabetically.
static:a,b,c|sort
`[1:]

type sortType int

const (
sortAlphabetical sortType = iota
sortVersion
)

func (s sortType) String() string {
switch s {
case sortAlphabetical:
return "alphabetical"
case sortVersion:
return "version"
default:
panic("unreachable")
}
}

// 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
return Name + ":" + f.sortType.String()
}

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)
}
Loading