forked from tangled.org/core
Monorepo for Tangled

knotserver/git: cache just the commit hash and time

This should help alleviate the memory leakyness that was exhibited when
we stored the entire object.Commit in memory.

Changed files
+40 -17
appview
pages
templates
knotserver
git
types
+2 -2
appview/pages/templates/repo/index.html
··· 79 79 </a> 80 80 81 81 <time class="text-xs text-gray-500" 82 - >{{ timeFmt .LastCommit.Author.When }}</time 82 + >{{ timeFmt .LastCommit.When }}</time 83 83 > 84 84 </div> 85 85 </div> ··· 104 104 </a> 105 105 106 106 <time class="text-xs text-gray-500" 107 - >{{ timeFmt .LastCommit.Author.When }}</time 107 + >{{ timeFmt .LastCommit.When }}</time 108 108 > 109 109 </div> 110 110 </div>
+2 -2
appview/pages/templates/repo/tree.html
··· 44 44 <i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }} 45 45 </div> 46 46 </a> 47 - <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time> 47 + <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time> 48 48 </div> 49 49 </div> 50 50 {{ end }} ··· 59 59 <i class="w-3 h-3" data-lucide="file"></i>{{ .Name }} 60 60 </div> 61 61 </a> 62 - <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time> 62 + <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time> 63 63 </div> 64 64 </div> 65 65 {{ end }}
+26 -11
knotserver/git/git.go
··· 9 9 "os/exec" 10 10 "path" 11 11 "sort" 12 + "strconv" 12 13 "strings" 13 14 "sync" 14 15 "time" ··· 17 18 "github.com/go-git/go-git/v5" 18 19 "github.com/go-git/go-git/v5/plumbing" 19 20 "github.com/go-git/go-git/v5/plumbing/object" 21 + "github.com/sotangled/tangled/types" 20 22 ) 21 23 22 24 var ( ··· 297 299 return nil 298 300 } 299 301 300 - func (g *GitRepo) LastCommitForPath(path string) (*object.Commit, error) { 302 + func (g *GitRepo) LastCommitForPath(path string) (*types.LastCommitInfo, error) { 301 303 cacheKey := fmt.Sprintf("%s:%s", g.h.String(), path) 302 304 cacheMu.RLock() 303 - if commit, found := commitCache.Get(cacheKey); found { 305 + if commitInfo, found := commitCache.Get(cacheKey); found { 304 306 cacheMu.RUnlock() 305 - return commit.(*object.Commit), nil 307 + return commitInfo.(*types.LastCommitInfo), nil 306 308 } 307 309 cacheMu.RUnlock() 308 310 309 - cmd := exec.Command("git", "-C", g.path, "log", "-1", "--format=%H", "--", path) 311 + cmd := exec.Command("git", "-C", g.path, "log", "-1", "--format=%H %ct", "--", path) 310 312 311 313 var out bytes.Buffer 312 314 cmd.Stdout = &out ··· 316 318 return nil, fmt.Errorf("failed to get commit hash: %w", err) 317 319 } 318 320 319 - commitHash := strings.TrimSpace(out.String()) 320 - if commitHash == "" { 321 + output := strings.TrimSpace(out.String()) 322 + if output == "" { 321 323 return nil, fmt.Errorf("no commits found for path: %s", path) 322 324 } 323 325 326 + parts := strings.SplitN(output, " ", 2) 327 + if len(parts) < 2 { 328 + return nil, fmt.Errorf("unexpected commit log format") 329 + } 330 + 331 + commitHash := parts[0] 332 + commitTimeUnix, err := strconv.ParseInt(parts[1], 10, 64) 333 + if err != nil { 334 + return nil, fmt.Errorf("parsing commit time: %w", err) 335 + } 336 + commitTime := time.Unix(commitTimeUnix, 0) 337 + 324 338 hash := plumbing.NewHash(commitHash) 325 339 326 - commit, err := g.r.CommitObject(hash) 327 - if err != nil { 328 - return nil, err 340 + commitInfo := &types.LastCommitInfo{ 341 + Hash: hash, 342 + Message: "", 343 + When: commitTime, 329 344 } 330 345 331 346 cacheMu.Lock() 332 - commitCache.Set(cacheKey, commit, 1) 347 + commitCache.Set(cacheKey, commitInfo, 1) 333 348 cacheMu.Unlock() 334 349 335 - return commit, nil 350 + return commitInfo, nil 336 351 } 337 352 338 353 func newInfoWrapper(
+10 -2
types/tree.go
··· 1 1 package types 2 2 3 3 import ( 4 - "github.com/go-git/go-git/v5/plumbing/object" 4 + "time" 5 + 6 + "github.com/go-git/go-git/v5/plumbing" 5 7 ) 6 8 7 9 // A nicer git tree representation. ··· 12 14 IsFile bool `json:"is_file"` 13 15 IsSubtree bool `json:"is_subtree"` 14 16 15 - LastCommit *object.Commit `json:"last_commit,omitempty"` 17 + LastCommit *LastCommitInfo `json:"last_commit,omitempty"` 18 + } 19 + 20 + type LastCommitInfo struct { 21 + Hash plumbing.Hash 22 + Message string 23 + When time.Time 16 24 }