Commit 85ec9f4218

85ec9f42188b756a08648c1db06a12f5b8a223d2

parent: 568741bf32

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-12 04:58 UTC

web: refs and the release form order tags by version

Ref #182
internal/gitutil/versions.go added +50
@@ -0,0 +1,50 @@
1package gitutil
2
3import (
4 "sort"
5 "strconv"
6 "strings"
7)
8
9// version parses "v1.2.3" or "1.2" into numeric parts. Anything else is
10// not a version.
11func version(name string) ([]int, bool) {
12 s := strings.TrimPrefix(name, "v")
13 if s == "" {
14 return nil, false
15 }
16 var parts []int
17 for _, p := range strings.Split(s, ".") {
18 n, err := strconv.Atoi(p)
19 if err != nil || n < 0 {
20 return nil, false
21 }
22 parts = append(parts, n)
23 }
24 return parts, true
25}
26
27func versionLess(a, b []int) bool {
28 for i := 0; i < len(a) && i < len(b); i++ {
29 if a[i] != b[i] {
30 return a[i] < b[i]
31 }
32 }
33 return len(a) < len(b)
34}
35
36// SortVersions orders refs newest version first. Names that are not
37// versions follow, by name.
38func SortVersions(refs []Ref) {
39 sort.SliceStable(refs, func(i, j int) bool {
40 vi, oki := version(refs[i].Name)
41 vj, okj := version(refs[j].Name)
42 switch {
43 case oki && okj:
44 return versionLess(vj, vi)
45 case oki != okj:
46 return oki
47 }
48 return refs[i].Name < refs[j].Name
49 })
50}
internal/gitutil/versions_test.go added +18
@@ -0,0 +1,18 @@
1package gitutil
2
3import "testing"
4
5func TestSortVersionsNewestFirst(t *testing.T) {
6 refs := []Ref{{Name: "v1.2.0"}, {Name: "v1.10.0"}, {Name: "nightly"}, {Name: "v1.2.1"}, {Name: "v0.9"}, {Name: "beta"}, {Name: "2.0.0"}}
7 SortVersions(refs)
8 var got []string
9 for _, r := range refs {
10 got = append(got, r.Name)
11 }
12 want := []string{"2.0.0", "v1.10.0", "v1.2.1", "v1.2.0", "v0.9", "beta", "nightly"}
13 for i := range want {
14 if i >= len(got) || got[i] != want[i] {
15 t.Fatalf("order %v, want %v", got, want)
16 }
17 }
18}
internal/httpd/web.go +2
@@ -639,6 +639,7 @@ func (s *Server) releases(w http.ResponseWriter, r *http.Request) {
639639 }
640640 var freeTags []string
641641 if tags, err := gitutil.Refs(p.Dir, "tags"); err == nil {
642 gitutil.SortVersions(tags)
642643 for _, tg := range tags {
643644 if !released[tg.Name] {
644645 freeTags = append(freeTags, tg.Name)
@@ -1963,6 +1964,7 @@ func (s *Server) refs(w http.ResponseWriter, r *http.Request) {
19631964 p.Tab = "refs"
19641965 branches, _ := gitutil.Refs(p.Dir, "heads")
19651966 tags, _ := gitutil.Refs(p.Dir, "tags")
1967 gitutil.SortVersions(tags)
19661968 s.render(w, "refs.html", struct {
19671969 repoPage
19681970 Branches, Tags []gitutil.Ref