main
jolheiser 2025-06-04 15:42:48 -05:00
parent ebe2dc4603
commit b8ca3fc4b8
No known key found for this signature in database
7 changed files with 113 additions and 18 deletions

View File

@ -7,13 +7,60 @@ import (
"io/fs"
"os"
"path/filepath"
"slices"
)
// RepoMeta is the meta information a Repo can have
type RepoMeta struct {
Description string `json:"description"`
Private bool `json:"private"`
Tags []string `json:"tags"`
Description string `json:"description"`
Private bool `json:"private"`
Tags TagSet `json:"tags"`
}
// TagSet is a Set of tags
type TagSet map[string]struct{}
// Add adds a tag to the set
func (t TagSet) Add(tag string) {
t[tag] = struct{}{}
}
// Remove removes a tag from the set
func (t TagSet) Remove(tag string) {
delete(t, tag)
}
// Contains checks if a tag is in the set
func (t TagSet) Contains(tag string) bool {
_, ok := t[tag]
return ok
}
// Slice returns the set as a (sorted) slice
func (t TagSet) Slice() []string {
s := make([]string, 0, len(t))
for k := range t {
s = append(s, k)
}
slices.Sort(s)
return s
}
// MarshalJSON implements [json.Marshaler]
func (t TagSet) MarshalJSON() ([]byte, error) {
return json.Marshal(t.Slice())
}
// UnmarshalJSON implements [json.Unmarshaler]
func (t *TagSet) UnmarshalJSON(b []byte) error {
var s []string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
for _, ss := range s {
t.Add(ss)
}
return nil
}
// Update updates meta given another RepoMeta

View File

@ -0,0 +1,53 @@
package git
import (
"encoding/json"
"testing"
"github.com/alecthomas/assert/v2"
)
func TestTagSet(t *testing.T) {
set := make(TagSet)
assert.Equal(t, 0, len(set))
assert.Equal(t, 0, len(set.Slice()))
set.Add("foo")
assert.Equal(t, 1, len(set))
assert.Equal(t, 1, len(set.Slice()))
assert.True(t, set.Contains("foo"))
set.Add("bar")
assert.Equal(t, 2, len(set))
assert.Equal(t, 2, len(set.Slice()))
assert.True(t, set.Contains("foo"))
assert.True(t, set.Contains("bar"))
set.Add("bar")
assert.Equal(t, 2, len(set))
assert.Equal(t, 2, len(set.Slice()))
assert.True(t, set.Contains("foo"))
assert.True(t, set.Contains("bar"))
set.Remove("foo")
assert.Equal(t, 1, len(set))
assert.Equal(t, 1, len(set.Slice()))
assert.False(t, set.Contains("foo"))
assert.True(t, set.Contains("bar"))
set.Add("foo")
set.Add("baz")
j, err := json.Marshal(set)
assert.NoError(t, err)
assert.Equal(t, `["bar","baz","foo"]`, string(j))
set = make(TagSet)
b := []byte(`["foo","bar","baz"]`)
err = json.Unmarshal(b, &set)
assert.NoError(t, err)
assert.Equal(t, 3, len(set))
assert.Equal(t, 3, len(set.Slice()))
assert.True(t, set.Contains("foo"))
assert.True(t, set.Contains("bar"))
assert.True(t, set.Contains("baz"))
}

View File

@ -58,15 +58,11 @@ func HandlePushOptions(repo *Repo, opts []*packp.Option) error {
remove = true
tagValue = strings.TrimPrefix(tagValue, "-")
}
for idx, tag := range repo.Meta.Tags {
if strings.EqualFold(tag, tagValue) {
if remove {
repo.Meta.Tags = append(repo.Meta.Tags[:idx], repo.Meta.Tags[idx+1:]...)
} else {
repo.Meta.Tags = append(repo.Meta.Tags, strings.ToLower(tagValue))
}
break
}
tagValue = strings.ToLower(tagValue)
if remove {
repo.Meta.Tags.Remove(tagValue)
} else {
repo.Meta.Tags.Add(tagValue)
}
}
}

View File

@ -92,7 +92,7 @@ func IndexTemplate(ic IndexContext) Node {
),
),
Div(Class("sm:col-span-1 text-subtext0"),
Map(repo.Meta.Tags, func(tag string) Node {
Map(repo.Meta.Tags.Slice(), func(tag string) Node {
return A(Class("rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block"), Href("?tag="+tag), Text(tag))
}),
),

View File

@ -126,7 +126,7 @@ func (rh repoHandler) repoHeaderContext(repo *git.Repo, r *http.Request) html.Re
Name: chi.URLParam(r, "repo"),
Ref: ref,
CloneURL: rh.s.CloneURL,
Tags: repo.Meta.Tags,
Tags: repo.Meta.Tags.Slice(),
}
}

View File

@ -3,7 +3,6 @@ package http
import (
"net/http"
"os"
"slices"
"sort"
"strings"
"time"
@ -34,10 +33,10 @@ func (rh repoHandler) index(w http.ResponseWriter, r *http.Request) error {
if !rh.s.ShowPrivate {
continue
}
repo.Meta.Tags = append(repo.Meta.Tags, "private")
repo.Meta.Tags.Add("private")
}
if tagFilter != "" && !slices.Contains(repo.Meta.Tags, strings.ToLower(tagFilter)) {
if tagFilter != "" && !repo.Meta.Tags.Contains(strings.ToLower(tagFilter)) {
continue
}
repos = append(repos, repo)

View File

@ -30,7 +30,7 @@ func (rh repoHandler) repoMiddleware(next http.Handler) http.Handler {
if !rh.s.ShowPrivate {
return httperr.Status(errors.New("could not get git repo"), http.StatusNotFound)
}
repo.Meta.Tags = append(repo.Meta.Tags, "private")
repo.Meta.Tags.Add("private")
}
r = r.WithContext(context.WithValue(r.Context(), repoCtxKey, repo))
next.ServeHTTP(w, r)