Skip to content

Make last commit cache always available #34311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1886,9 +1886,6 @@ LEVEL = Info
;; Time to keep items in cache if not used, default is 8760 hours.
;; Setting it to -1 disables caching
;ITEM_TTL = 8760h
;;
;; Only enable the cache when repository's commits count great than
;COMMITS_COUNT = 1000

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand Down
5 changes: 1 addition & 4 deletions modules/git/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ func (c *Commit) ParentCount() int {

// GetCommitByPath return the commit of relative path object.
func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) {
if c.repo.LastCommitCache != nil {
return c.repo.LastCommitCache.GetCommitByPath(c.ID.String(), relpath)
}
return c.repo.getCommitByPathWithID(c.ID, relpath)
return c.repo.lastCommitCache.GetCommitByPath(c.ID.String(), relpath)
}

// AddChanges marks local changes to be ready for commit.
Expand Down
46 changes: 9 additions & 37 deletions modules/git/commit_info_gogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,19 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
return nil, nil, err
}

var revs map[string]*Commit
if commit.repo.LastCommitCache != nil {
var unHitPaths []string
revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache)
revs, unHitPaths, err := commit.repo.lastCommitCache.getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths)
if err != nil {
return nil, nil, err
}
if len(unHitPaths) > 0 {
revs2, err := GetLastCommitForPaths(ctx, commit.repo.lastCommitCache, c, treePath, unHitPaths)
if err != nil {
return nil, nil, err
}
if len(unHitPaths) > 0 {
revs2, err := GetLastCommitForPaths(ctx, commit.repo.LastCommitCache, c, treePath, unHitPaths)
if err != nil {
return nil, nil, err
}

for k, v := range revs2 {
revs[k] = v
}
for k, v := range revs2 {
revs[k] = v
}
} else {
revs, err = GetLastCommitForPaths(ctx, nil, c, treePath, entryPaths)
}
if err != nil {
return nil, nil, err
}

commit.repo.gogitStorage.Close()
Expand Down Expand Up @@ -153,27 +144,8 @@ func getFileHashes(c cgobject.CommitNode, treePath string, paths []string) (map[
return hashes, nil
}

func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) {
var unHitEntryPaths []string
results := make(map[string]*Commit)
for _, p := range paths {
lastCommit, err := cache.Get(commitID, path.Join(treePath, p))
if err != nil {
return nil, nil, err
}
if lastCommit != nil {
results[p] = lastCommit
continue
}

unHitEntryPaths = append(unHitEntryPaths, p)
}

return results, unHitEntryPaths, nil
}

// GetLastCommitForPaths returns last commit information
func GetLastCommitForPaths(ctx context.Context, cache *LastCommitCache, c cgobject.CommitNode, treePath string, paths []string) (map[string]*Commit, error) {
func GetLastCommitForPaths(ctx context.Context, cache *lastCommitCache, c cgobject.CommitNode, treePath string, paths []string) (map[string]*Commit, error) {
refSha := c.ID().String()

// We do a tree traversal with nodes sorted by commit time
Expand Down
49 changes: 11 additions & 38 deletions modules/git/commit_info_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"context"
"fmt"
"io"
"path"
"sort"

"code.gitea.io/gitea/modules/log"
Expand All @@ -27,29 +26,22 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
var err error

var revs map[string]*Commit
if commit.repo.LastCommitCache != nil {
var unHitPaths []string
revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache)

var unHitPaths []string
revs, unHitPaths, err = commit.repo.lastCommitCache.getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths)
if err != nil {
return nil, nil, err
}
if len(unHitPaths) > 0 {
sort.Strings(unHitPaths)
commits, err := GetLastCommitForPaths(ctx, commit, treePath, unHitPaths)
if err != nil {
return nil, nil, err
}
if len(unHitPaths) > 0 {
sort.Strings(unHitPaths)
commits, err := GetLastCommitForPaths(ctx, commit, treePath, unHitPaths)
if err != nil {
return nil, nil, err
}

for pth, found := range commits {
revs[pth] = found
}
for pth, found := range commits {
revs[pth] = found
}
} else {
sort.Strings(entryPaths)
revs, err = GetLastCommitForPaths(ctx, commit, treePath, entryPaths)
}
if err != nil {
return nil, nil, err
}

commitsInfo := make([]CommitInfo, len(tes))
Expand Down Expand Up @@ -97,25 +89,6 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
return commitsInfo, treeCommit, nil
}

func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) {
var unHitEntryPaths []string
results := make(map[string]*Commit)
for _, p := range paths {
lastCommit, err := cache.Get(commitID, path.Join(treePath, p))
if err != nil {
return nil, nil, err
}
if lastCommit != nil {
results[p] = lastCommit
continue
}

unHitEntryPaths = append(unHitEntryPaths, p)
}

return results, unHitEntryPaths, nil
}

// GetLastCommitForPaths returns last commit information
func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) {
// We read backwards from the commit to obtain all of the commits
Expand Down
72 changes: 39 additions & 33 deletions modules/git/last_commit_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
package git

import (
"context"
"crypto/sha256"
"fmt"
"path"

"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/log"
Expand All @@ -17,25 +19,21 @@ func getCacheKey(repoPath, commitID, entryPath string) string {
return fmt.Sprintf("last_commit:%x", hashBytes)
}

// LastCommitCache represents a cache to store last commit
type LastCommitCache struct {
repoPath string
ttl func() int64
repo *Repository
commitCache map[string]*Commit
cache cache.StringCache
// lastCommitCache represents a cache to store last commit
type lastCommitCache struct {
repoPath string
repo *Repository
ttl func() int64
cache cache.StringCache
}

// NewLastCommitCache creates a new last commit cache for repo
func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache cache.StringCache) *LastCommitCache {
// newLastCommitCache creates a new last commit cache for repo
func newLastCommitCache(repoPath string, gitRepo *Repository, cache cache.StringCache) *lastCommitCache {
if cache == nil {
return nil
}
if count < setting.CacheService.LastCommit.CommitsCount {
return nil
}

return &LastCommitCache{
return &lastCommitCache{
repoPath: repoPath,
repo: gitRepo,
ttl: setting.LastCommitCacheTTLSeconds,
Expand All @@ -44,7 +42,7 @@ func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache
}

// Put put the last commit id with commit and entry path
func (c *LastCommitCache) Put(ref, entryPath, commitID string) error {
func (c *lastCommitCache) Put(ref, entryPath, commitID string) error {
if c == nil || c.cache == nil {
return nil
}
Expand All @@ -53,7 +51,7 @@ func (c *LastCommitCache) Put(ref, entryPath, commitID string) error {
}

// Get gets the last commit information by commit id and entry path
func (c *LastCommitCache) Get(ref, entryPath string) (*Commit, error) {
func (c *lastCommitCache) Get(ref, entryPath string) (*Commit, error) {
if c == nil || c.cache == nil {
return nil, nil
}
Expand All @@ -63,27 +61,12 @@ func (c *LastCommitCache) Get(ref, entryPath string) (*Commit, error) {
return nil, nil
}

log.Debug("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, commitID)
if c.commitCache != nil {
if commit, ok := c.commitCache[commitID]; ok {
log.Debug("LastCommitCache hit level 2: [%s:%s:%s]", ref, entryPath, commitID)
return commit, nil
}
}

commit, err := c.repo.GetCommit(commitID)
if err != nil {
return nil, err
}
if c.commitCache == nil {
c.commitCache = make(map[string]*Commit)
}
c.commitCache[commitID] = commit
return commit, nil
log.Debug("LastCommitCache hit: [%s:%s:%s]", ref, entryPath, commitID)
return c.repo.GetCommit(commitID)
}

// GetCommitByPath gets the last commit for the entry in the provided commit
func (c *LastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit, error) {
func (c *lastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit, error) {
sha, err := NewIDFromString(commitID)
if err != nil {
return nil, err
Expand All @@ -105,3 +88,26 @@ func (c *LastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit,

return lastCommit, nil
}

func (c *lastCommitCache) getLastCommitForPathsByCache(commitID, treePath string, paths []string) (map[string]*Commit, []string, error) {
var unHitEntryPaths []string
results := make(map[string]*Commit)
for _, p := range paths {
lastCommit, err := c.Get(commitID, path.Join(treePath, p))
if err != nil {
return nil, nil, err
}
if lastCommit != nil {
results[p] = lastCommit
continue
}

unHitEntryPaths = append(unHitEntryPaths, p)
}

return results, unHitEntryPaths, nil
}

func (repo *Repository) CacheCommit(ctx context.Context, commit *Commit) error {
return repo.lastCommitCache.CacheCommit(ctx, commit)
}
15 changes: 6 additions & 9 deletions modules/git/last_commit_cache_gogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,18 @@ import (
)

// CacheCommit will cache the commit from the gitRepository
func (c *Commit) CacheCommit(ctx context.Context) error {
if c.repo.LastCommitCache == nil {
return nil
}
func (c *lastCommitCache) CacheCommit(ctx context.Context, commit *Commit) error {
commitNodeIndex, _ := c.repo.CommitNodeIndex()

index, err := commitNodeIndex.Get(plumbing.Hash(c.ID.RawValue()))
index, err := commitNodeIndex.Get(plumbing.Hash(commit.ID.RawValue()))
if err != nil {
return err
}

return c.recursiveCache(ctx, index, &c.Tree, "", 1)
return c.recursiveCache(ctx, index, commit, &commit.Tree, "", 1)
}

func (c *Commit) recursiveCache(ctx context.Context, index cgobject.CommitNode, tree *Tree, treePath string, level int) error {
func (c *lastCommitCache) recursiveCache(ctx context.Context, index cgobject.CommitNode, commit *Commit, tree *Tree, treePath string, level int) error {
if level == 0 {
return nil
}
Expand All @@ -44,7 +41,7 @@ func (c *Commit) recursiveCache(ctx context.Context, index cgobject.CommitNode,
entryMap[entry.Name()] = entry
}

commits, err := GetLastCommitForPaths(ctx, c.repo.LastCommitCache, index, treePath, entryPaths)
commits, err := GetLastCommitForPaths(ctx, c, index, treePath, entryPaths)
if err != nil {
return err
}
Expand All @@ -55,7 +52,7 @@ func (c *Commit) recursiveCache(ctx context.Context, index cgobject.CommitNode,
if err != nil {
return err
}
if err := c.recursiveCache(ctx, index, subTree, entry, level-1); err != nil {
if err := c.recursiveCache(ctx, index, commit, subTree, entry, level-1); err != nil {
return err
}
}
Expand Down
13 changes: 5 additions & 8 deletions modules/git/last_commit_cache_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ import (
)

// CacheCommit will cache the commit from the gitRepository
func (c *Commit) CacheCommit(ctx context.Context) error {
if c.repo.LastCommitCache == nil {
return nil
}
return c.recursiveCache(ctx, &c.Tree, "", 1)
func (c *lastCommitCache) CacheCommit(ctx context.Context, commit *Commit) error {
return c.recursiveCache(ctx, commit, &commit.Tree, "", 1)
}

func (c *Commit) recursiveCache(ctx context.Context, tree *Tree, treePath string, level int) error {
func (c *lastCommitCache) recursiveCache(ctx context.Context, commit *Commit, tree *Tree, treePath string, level int) error {
if level == 0 {
return nil
}
Expand All @@ -32,7 +29,7 @@ func (c *Commit) recursiveCache(ctx context.Context, tree *Tree, treePath string
entryPaths[i] = entry.Name()
}

_, err = WalkGitLog(ctx, c.repo, c, treePath, entryPaths...)
_, err = WalkGitLog(ctx, c.repo, commit, treePath, entryPaths...)
if err != nil {
return err
}
Expand All @@ -44,7 +41,7 @@ func (c *Commit) recursiveCache(ctx context.Context, tree *Tree, treePath string
if err != nil {
return err
}
if err := c.recursiveCache(ctx, subTree, treeEntry.Name(), level-1); err != nil {
if err := c.recursiveCache(ctx, commit, subTree, treeEntry.Name(), level-1); err != nil {
return err
}
}
Expand Down
4 changes: 2 additions & 2 deletions modules/git/log_name_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,14 @@ heaploop:
changed[i] = false
if results[i] == "" {
results[i] = current.CommitID
if err := repo.LastCommitCache.Put(headRef, path.Join(treepath, paths[i]), current.CommitID); err != nil {
if err := repo.lastCommitCache.Put(headRef, path.Join(treepath, paths[i]), current.CommitID); err != nil {
return nil, err
}
delete(path2idx, paths[i])
remaining--
if results[0] == "" {
results[0] = current.CommitID
if err := repo.LastCommitCache.Put(headRef, treepath, current.CommitID); err != nil {
if err := repo.lastCommitCache.Put(headRef, treepath, current.CommitID); err != nil {
return nil, err
}
delete(path2idx, "")
Expand Down
Loading