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_nogogit.go 2.9KB

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. // +build !gogit
  6. package git
  7. import (
  8. "bufio"
  9. "context"
  10. "path"
  11. "code.gitea.io/gitea/modules/log"
  12. )
  13. // LastCommitCache represents a cache to store last commit
  14. type LastCommitCache struct {
  15. repoPath string
  16. ttl func() int64
  17. repo *Repository
  18. commitCache map[string]*Commit
  19. cache Cache
  20. }
  21. // NewLastCommitCache creates a new last commit cache for repo
  22. func NewLastCommitCache(repoPath string, gitRepo *Repository, ttl func() int64, cache Cache) *LastCommitCache {
  23. if cache == nil {
  24. return nil
  25. }
  26. return &LastCommitCache{
  27. repoPath: repoPath,
  28. repo: gitRepo,
  29. commitCache: make(map[string]*Commit),
  30. ttl: ttl,
  31. cache: cache,
  32. }
  33. }
  34. // Get get the last commit information by commit id and entry path
  35. func (c *LastCommitCache) Get(ref, entryPath string, wr WriteCloserError, rd *bufio.Reader) (interface{}, error) {
  36. v := c.cache.Get(c.getCacheKey(c.repoPath, ref, entryPath))
  37. if vs, ok := v.(string); ok {
  38. log.Debug("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, vs)
  39. if commit, ok := c.commitCache[vs]; ok {
  40. log.Debug("LastCommitCache hit level 2: [%s:%s:%s]", ref, entryPath, vs)
  41. return commit, nil
  42. }
  43. id, err := c.repo.ConvertToSHA1(vs)
  44. if err != nil {
  45. return nil, err
  46. }
  47. if _, err := wr.Write([]byte(vs + "\n")); err != nil {
  48. return nil, err
  49. }
  50. commit, err := c.repo.getCommitFromBatchReader(rd, id)
  51. if err != nil {
  52. return nil, err
  53. }
  54. c.commitCache[vs] = commit
  55. return commit, nil
  56. }
  57. return nil, nil
  58. }
  59. // CacheCommit will cache the commit from the gitRepository
  60. func (c *LastCommitCache) CacheCommit(ctx context.Context, commit *Commit) error {
  61. return c.recursiveCache(ctx, commit, &commit.Tree, "", 1)
  62. }
  63. func (c *LastCommitCache) recursiveCache(ctx context.Context, commit *Commit, tree *Tree, treePath string, level int) error {
  64. if level == 0 {
  65. return nil
  66. }
  67. entries, err := tree.ListEntries()
  68. if err != nil {
  69. return err
  70. }
  71. entryPaths := make([]string, len(entries))
  72. entryMap := make(map[string]*TreeEntry)
  73. for i, entry := range entries {
  74. entryPaths[i] = entry.Name()
  75. entryMap[entry.Name()] = entry
  76. }
  77. commits, err := GetLastCommitForPaths(ctx, commit, treePath, entryPaths)
  78. if err != nil {
  79. return err
  80. }
  81. for entry, entryCommit := range commits {
  82. if err := c.Put(commit.ID.String(), path.Join(treePath, entry), entryCommit.ID.String()); err != nil {
  83. return err
  84. }
  85. // entryMap won't contain "" therefore skip this.
  86. if treeEntry := entryMap[entry]; treeEntry != nil && treeEntry.IsDir() {
  87. subTree, err := tree.SubTree(entry)
  88. if err != nil {
  89. return err
  90. }
  91. if err := c.recursiveCache(ctx, commit, subTree, entry, level-1); err != nil {
  92. return err
  93. }
  94. }
  95. }
  96. return nil
  97. }