You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

last_commit_cache_gogit.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. //go:build gogit
  5. package git
  6. import (
  7. "context"
  8. "code.gitea.io/gitea/modules/log"
  9. "github.com/go-git/go-git/v5/plumbing/object"
  10. cgobject "github.com/go-git/go-git/v5/plumbing/object/commitgraph"
  11. )
  12. // LastCommitCache represents a cache to store last commit
  13. type LastCommitCache struct {
  14. repoPath string
  15. ttl func() int64
  16. repo *Repository
  17. commitCache map[string]*object.Commit
  18. cache Cache
  19. }
  20. // NewLastCommitCache creates a new last commit cache for repo
  21. func NewLastCommitCache(repoPath string, gitRepo *Repository, ttl func() int64, cache Cache) *LastCommitCache {
  22. if cache == nil {
  23. return nil
  24. }
  25. return &LastCommitCache{
  26. repoPath: repoPath,
  27. repo: gitRepo,
  28. commitCache: make(map[string]*object.Commit),
  29. ttl: ttl,
  30. cache: cache,
  31. }
  32. }
  33. // Get get the last commit information by commit id and entry path
  34. func (c *LastCommitCache) Get(ref, entryPath string) (interface{}, error) {
  35. v := c.cache.Get(c.getCacheKey(c.repoPath, ref, entryPath))
  36. if vs, ok := v.(string); ok {
  37. log.Debug("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, vs)
  38. if commit, ok := c.commitCache[vs]; ok {
  39. log.Debug("LastCommitCache hit level 2: [%s:%s:%s]", ref, entryPath, vs)
  40. return commit, nil
  41. }
  42. id, err := c.repo.ConvertToSHA1(vs)
  43. if err != nil {
  44. return nil, err
  45. }
  46. commit, err := c.repo.GoGitRepo().CommitObject(id)
  47. if err != nil {
  48. return nil, err
  49. }
  50. c.commitCache[vs] = commit
  51. return commit, nil
  52. }
  53. return nil, nil
  54. }
  55. // CacheCommit will cache the commit from the gitRepository
  56. func (c *LastCommitCache) CacheCommit(ctx context.Context, commit *Commit) error {
  57. commitNodeIndex, _ := commit.repo.CommitNodeIndex()
  58. index, err := commitNodeIndex.Get(commit.ID)
  59. if err != nil {
  60. return err
  61. }
  62. return c.recursiveCache(ctx, index, &commit.Tree, "", 1)
  63. }
  64. func (c *LastCommitCache) recursiveCache(ctx context.Context, index cgobject.CommitNode, tree *Tree, treePath string, level int) error {
  65. if level == 0 {
  66. return nil
  67. }
  68. entries, err := tree.ListEntries()
  69. if err != nil {
  70. return err
  71. }
  72. entryPaths := make([]string, len(entries))
  73. entryMap := make(map[string]*TreeEntry)
  74. for i, entry := range entries {
  75. entryPaths[i] = entry.Name()
  76. entryMap[entry.Name()] = entry
  77. }
  78. commits, err := GetLastCommitForPaths(ctx, c, index, treePath, entryPaths)
  79. if err != nil {
  80. return err
  81. }
  82. for entry := range commits {
  83. if entryMap[entry].IsDir() {
  84. subTree, err := tree.SubTree(entry)
  85. if err != nil {
  86. return err
  87. }
  88. if err := c.recursiveCache(ctx, index, subTree, entry, level-1); err != nil {
  89. return err
  90. }
  91. }
  92. }
  93. return nil
  94. }