Skip to content
3 changes: 0 additions & 3 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1896,9 +1896,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 @@ -80,10 +80,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, repoLink string, commit *
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 @@ -143,27 +134,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
46 changes: 10 additions & 36 deletions modules/git/commit_info_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,20 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *
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
}

maps.Copy(revs, commits)
}
} else {
sort.Strings(entryPaths)
revs, err = GetLastCommitForPaths(ctx, commit, treePath, entryPaths)
}
if err != nil {
return nil, nil, err
maps.Copy(revs, commits)
}

commitsInfo := make([]CommitInfo, len(tes))
Expand Down Expand Up @@ -84,25 +77,6 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *
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 @@ -384,14 +384,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