code.gitea.io/gitea@v1.22.3/modules/git/last_commit_cache.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package git 5 6 import ( 7 "crypto/sha256" 8 "fmt" 9 10 "code.gitea.io/gitea/modules/cache" 11 "code.gitea.io/gitea/modules/log" 12 "code.gitea.io/gitea/modules/setting" 13 ) 14 15 func getCacheKey(repoPath, commitID, entryPath string) string { 16 hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s", repoPath, commitID, entryPath))) 17 return fmt.Sprintf("last_commit:%x", hashBytes) 18 } 19 20 // LastCommitCache represents a cache to store last commit 21 type LastCommitCache struct { 22 repoPath string 23 ttl func() int64 24 repo *Repository 25 commitCache map[string]*Commit 26 cache cache.StringCache 27 } 28 29 // NewLastCommitCache creates a new last commit cache for repo 30 func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache cache.StringCache) *LastCommitCache { 31 if cache == nil { 32 return nil 33 } 34 if count < setting.CacheService.LastCommit.CommitsCount { 35 return nil 36 } 37 38 return &LastCommitCache{ 39 repoPath: repoPath, 40 repo: gitRepo, 41 ttl: setting.LastCommitCacheTTLSeconds, 42 cache: cache, 43 } 44 } 45 46 // Put put the last commit id with commit and entry path 47 func (c *LastCommitCache) Put(ref, entryPath, commitID string) error { 48 if c == nil || c.cache == nil { 49 return nil 50 } 51 log.Debug("LastCommitCache save: [%s:%s:%s]", ref, entryPath, commitID) 52 return c.cache.Put(getCacheKey(c.repoPath, ref, entryPath), commitID, c.ttl()) 53 } 54 55 // Get gets the last commit information by commit id and entry path 56 func (c *LastCommitCache) Get(ref, entryPath string) (*Commit, error) { 57 if c == nil || c.cache == nil { 58 return nil, nil 59 } 60 61 commitID, ok := c.cache.Get(getCacheKey(c.repoPath, ref, entryPath)) 62 if !ok || commitID == "" { 63 return nil, nil 64 } 65 66 log.Debug("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, commitID) 67 if c.commitCache != nil { 68 if commit, ok := c.commitCache[commitID]; ok { 69 log.Debug("LastCommitCache hit level 2: [%s:%s:%s]", ref, entryPath, commitID) 70 return commit, nil 71 } 72 } 73 74 commit, err := c.repo.GetCommit(commitID) 75 if err != nil { 76 return nil, err 77 } 78 if c.commitCache == nil { 79 c.commitCache = make(map[string]*Commit) 80 } 81 c.commitCache[commitID] = commit 82 return commit, nil 83 } 84 85 // GetCommitByPath gets the last commit for the entry in the provided commit 86 func (c *LastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit, error) { 87 sha, err := NewIDFromString(commitID) 88 if err != nil { 89 return nil, err 90 } 91 92 lastCommit, err := c.Get(sha.String(), entryPath) 93 if err != nil || lastCommit != nil { 94 return lastCommit, err 95 } 96 97 lastCommit, err = c.repo.getCommitByPathWithID(sha, entryPath) 98 if err != nil { 99 return nil, err 100 } 101 102 if err := c.Put(commitID, entryPath, lastCommit.ID.String()); err != nil { 103 log.Error("Unable to cache %s as the last commit for %q in %s %s. Error %v", lastCommit.ID.String(), entryPath, commitID, c.repoPath, err) 104 } 105 106 return lastCommit, nil 107 }