forked from tangled.org/core
this repo has no description

knotserver: last commit for each file

This is a super trivial implementation last commit for each file. It's
slow and inefficient despite using ristretto for in-memory caching.

We should move this to storing in sqlite in the future.

Changed files
+75 -7
knotserver
types
+2
go.mod
···
github.com/bluesky-social/jetstream v0.0.0-20241210005130-ea96859b93d1
github.com/casbin/casbin/v2 v2.103.0
github.com/cyphar/filepath-securejoin v0.3.3
+
github.com/dgraph-io/ristretto v0.2.0
github.com/dustin/go-humanize v1.0.1
github.com/gliderlabs/ssh v0.3.5
github.com/go-chi/chi/v5 v5.2.0
···
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
+
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
+4
go.sum
···
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
+
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
+
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
+
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+48
knotserver/git/git.go
···
"io/fs"
"path"
"sort"
+
"sync"
"time"
+
"github.com/dgraph-io/ristretto"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
+
+
var (
+
commitCache *ristretto.Cache
+
cacheMu sync.RWMutex
+
)
+
+
func init() {
+
cache, _ := ristretto.NewCache(&ristretto.Config{
+
NumCounters: 1e7,
+
MaxCost: 1 << 30,
+
BufferItems: 64,
+
})
+
commitCache = cache
+
}
var (
ErrBinaryFile = fmt.Errorf("binary file")
···
}
return nil
+
}
+
+
func (g *GitRepo) LastCommitTime(filePath string) (*object.Commit, error) {
+
cacheMu.RLock()
+
if commit, exists := commitCache.Get(filePath); exists {
+
cacheMu.RUnlock()
+
return commit.(*object.Commit), nil
+
}
+
cacheMu.RUnlock()
+
+
commitIter, err := g.r.Log(&git.LogOptions{
+
From: g.h,
+
PathFilter: func(s string) bool {
+
return s == filePath
+
},
+
Order: git.LogOrderCommitterTime,
+
})
+
+
if err != nil {
+
return nil, fmt.Errorf("failed to get commit log for %s: %w", filePath, err)
+
}
+
+
commit, err := commitIter.Next()
+
if err != nil {
+
return nil, fmt.Errorf("no commit found for %s", filePath)
+
}
+
+
cacheMu.Lock()
+
commitCache.Set(filePath, commit, 1)
+
cacheMu.Unlock()
+
+
return commit, nil
}
func newInfoWrapper(
+15 -7
knotserver/git/tree.go
···
}
if path == "" {
-
files = makeNiceTree(tree)
+
files = g.makeNiceTree(tree)
} else {
o, err := tree.FindEntry(path)
if err != nil {
···
return nil, err
}
-
files = makeNiceTree(subtree)
+
files = g.makeNiceTree(subtree)
}
}
return files, nil
}
-
func makeNiceTree(t *object.Tree) []types.NiceTree {
+
func (g *GitRepo) makeNiceTree(t *object.Tree) []types.NiceTree {
nts := []types.NiceTree{}
for _, e := range t.Entries {
mode, _ := e.Mode.ToOSFileMode()
sz, _ := t.Size(e.Name)
+
+
lastCommit, err := g.LastCommitTime(e.Name)
+
if err != nil {
+
continue
+
}
+
nts = append(nts, types.NiceTree{
-
Name: e.Name,
-
Mode: mode.String(),
-
IsFile: e.Mode.IsFile(),
-
Size: sz,
+
Name: e.Name,
+
Mode: mode.String(),
+
IsFile: e.Mode.IsFile(),
+
Size: sz,
+
LastCommit: lastCommit,
})
+
}
return nts
+6
types/tree.go
···
package types
+
import (
+
"github.com/go-git/go-git/v5/plumbing/object"
+
)
+
// A nicer git tree representation.
type NiceTree struct {
Name string `json:"name"`
···
Size int64 `json:"size"`
IsFile bool `json:"is_file"`
IsSubtree bool `json:"is_subtree"`
+
+
LastCommit *object.Commit `json:"last_commit,omitempty"`
}