Skip to content

Commit 037e4c9

Browse files
committed
handle both versions with and without leading v
1 parent 27454d9 commit 037e4c9

3 files changed

Lines changed: 77 additions & 0 deletions

File tree

internal/gitsemver/gitsemver_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,29 @@ func Test_VersionStringer_GetTag_ClosestTagNotOverriddenByUnreachableSameTreeTag
414414
t.Fatalf("expected sameTree false, got true")
415415
}
416416
}
417+
418+
func Test_VersionStringer_GetTag_PicksHighestMixedPrefixTagOnSameTree(t *testing.T) {
419+
repo := t.TempDir()
420+
runGit(t, repo, nil, "init", "-q")
421+
runGit(t, repo, nil, "config", "user.email", "test@example.com")
422+
runGit(t, repo, nil, "config", "user.name", "Test")
423+
424+
commitAt(t, repo, "a.txt", "a\n", "c1", "2020-01-01T00:00:00Z")
425+
runGit(t, repo, nil, "tag", "v1.2.3")
426+
runGit(t, repo, nil, "tag", "2.0.0")
427+
428+
vs, err := gitsemver.New("git", nil)
429+
if err != nil {
430+
t.Fatal(err)
431+
}
432+
tag, sameTree, err := vs.GetTag(repo)
433+
if err != nil {
434+
t.Fatal(err)
435+
}
436+
if tag != "2.0.0" {
437+
t.Fatalf("expected highest mixed-prefix tag 2.0.0, got %q", tag)
438+
}
439+
if !sameTree {
440+
t.Fatalf("expected sameTree true, got false")
441+
}
442+
}

internal/gitsemver/gitter.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"path/filepath"
1111
"regexp"
1212
"runtime"
13+
"sort"
1314
"strconv"
1415
"strings"
1516
)
@@ -158,6 +159,20 @@ func (dg DefaultGitter) CheckGitRepo(dir string) (repo string, err error) {
158159
// with or without a leading "v".
159160
var reMatchSemver = regexp.MustCompile(`^v?[0-9]+(?:\.[0-9]+)?(?:\.[0-9]+)?$`)
160161

162+
func semverKey(tag string) [3]int {
163+
var key [3]int
164+
core := strings.TrimPrefix(tag, "v")
165+
parts := strings.Split(core, ".")
166+
for i := 0; i < len(parts) && i < len(key); i++ {
167+
n, err := strconv.Atoi(parts[i])
168+
if err != nil {
169+
break
170+
}
171+
key[i] = n
172+
}
173+
return key
174+
}
175+
161176
// GetTags returns all tags, sorted by version descending.
162177
// The latest tag is the first in the list.
163178
func (dg DefaultGitter) GetTags(repo string) (tags []string, err error) {
@@ -168,6 +183,18 @@ func (dg DefaultGitter) GetTags(repo string) (tags []string, err error) {
168183
tags = append(tags, tag)
169184
}
170185
}
186+
// Git's multi-pattern listing can interleave v-prefixed and non-prefixed
187+
// tags in a way that is not globally version-sorted. Normalize here.
188+
sort.SliceStable(tags, func(i, j int) bool {
189+
left := semverKey(tags[i])
190+
right := semverKey(tags[j])
191+
for idx := range left {
192+
if left[idx] != right[idx] {
193+
return left[idx] > right[idx]
194+
}
195+
}
196+
return false
197+
})
171198
}
172199
return
173200
}

internal/gitsemver/gitter_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,30 @@ func Test_DefaultGitter_GetTags_IncludesSingleDigitSemverTags(t *testing.T) {
201201
}
202202
}
203203

204+
func Test_DefaultGitter_GetTags_SortsMixedPrefixSemverDescending(t *testing.T) {
205+
repo := t.TempDir()
206+
runGit(t, repo, nil, "init", "-q")
207+
runGit(t, repo, nil, "config", "user.email", "test@example.com")
208+
runGit(t, repo, nil, "config", "user.name", "Test")
209+
commitAt(t, repo, "a.txt", "a\n", "c1", "2020-01-01T00:00:00Z")
210+
runGit(t, repo, nil, "tag", "v1.2.3")
211+
runGit(t, repo, nil, "tag", "2.0.0")
212+
runGit(t, repo, nil, "tag", "v10.0.0")
213+
runGit(t, repo, nil, "tag", "1.2.4")
214+
215+
dg, err := gitsemver.NewDefaultGitter("git", nil)
216+
if err != nil {
217+
t.Fatal(err)
218+
}
219+
tags, err := dg.GetTags(repo)
220+
if err != nil {
221+
t.Fatal(err)
222+
}
223+
if slices.Compare(tags, []string{"v10.0.0", "2.0.0", "1.2.4", "v1.2.3"}) != 0 {
224+
t.Fatalf("unexpected tags: %v", tags)
225+
}
226+
}
227+
204228
func Test_DefaultGitter_GetCurrentTreeHash(t *testing.T) {
205229
dg, err := gitsemver.NewDefaultGitter("git", nil)
206230
if err != nil {

0 commit comments

Comments
 (0)