github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/git/last_commit_cache_nogogit.go (about)

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