8fa44044b4b4bca57db1df7f85ba529c0dfb6dec

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

fix: cache git trees and commits

Diff

This diff is truncated to protect this page.

  1diff --git a/internal/git/git.go b/internal/git/git.go
  2index fe21bc782178d12a2c7a1de240fe87a4d351fe1c..1e2b61021b8d996dada55072def58a9b4c481fcc 100644
  3--- a/internal/git/git.go
  4+++ b/internal/git/git.go
  5@@ -28,6 +28,8 @@ type Repo struct {
  6 	refCommits map[plumbing.Hash]gitypes.Commits
  7 	head       *plumbing.Reference
  8 	refs       []*plumbing.Reference
  9+	trees      map[plumbing.Hash]*object.Tree
 10+	commits    map[plumbing.Hash]*object.Commit
 11 }
 12 
 13 // GetName returns the name of the repository.
 14@@ -46,6 +48,7 @@ func (r *Repo) SetHEAD(ref *plumbing.Reference) error {
 15 	return nil
 16 }
 17 
 18+// GetReferences returns the references for a repository.
 19 func (r *Repo) GetReferences() []*plumbing.Reference {
 20 	return r.refs
 21 }
 22@@ -62,11 +65,11 @@ func (r *Repo) Tree(ref *plumbing.Reference, path string) (*object.Tree, error)
 23 	if err != nil {
 24 		return nil, err
 25 	}
 26-	c, err := r.repository.CommitObject(hash)
 27+	c, err := r.commitForHash(hash)
 28 	if err != nil {
 29 		return nil, err
 30 	}
 31-	t, err := c.Tree()
 32+	t, err := r.treeForHash(c.TreeHash)
 33 	if err != nil {
 34 		return nil, err
 35 	}
 36@@ -76,6 +79,32 @@ func (r *Repo) Tree(ref *plumbing.Reference, path string) (*object.Tree, error)
 37 	return t.Tree(path)
 38 }
 39 
 40+func (r *Repo) treeForHash(treeHash plumbing.Hash) (*object.Tree, error) {
 41+	var err error
 42+	t, ok := r.trees[treeHash]
 43+	if !ok {
 44+		t, err = r.repository.TreeObject(treeHash)
 45+		if err != nil {
 46+			return nil, err
 47+		}
 48+		r.trees[treeHash] = t
 49+	}
 50+	return t, nil
 51+}
 52+
 53+func (r *Repo) commitForHash(hash plumbing.Hash) (*object.Commit, error) {
 54+	var err error
 55+	co, ok := r.commits[hash]
 56+	if !ok {
 57+		co, err = r.repository.CommitObject(hash)
 58+		if err != nil {
 59+			return nil, err
 60+		}
 61+		r.commits[hash] = co
 62+	}
 63+	return co, nil
 64+}
 65+
 66 // GetCommits returns the commits for a repository.
 67 func (r *Repo) GetCommits(ref *plumbing.Reference) (gitypes.Commits, error) {
 68 	hash, err := r.targetHash(ref)
 69@@ -87,23 +116,19 @@ func (r *Repo) GetCommits(ref *plumbing.Reference) (gitypes.Commits, error) {
 70 	if ok {
 71 		return commits, nil
 72 	}
 73-	log.Printf("caching commits for %s/%s: %s", r.name, ref.Name(), ref.Hash())
 74 	commits = gitypes.Commits{}
 75-	co, err := r.repository.CommitObject(hash)
 76+	co, err := r.commitForHash(hash)
 77 	if err != nil {
 78 		return nil, err
 79 	}
 80 	// traverse the commit tree to get all commits
 81-	commits = append(commits, &gitypes.Commit{Commit: co})
 82-	for {
 83-		co, err = co.Parent(0)
 84+	commits = append(commits, co)
 85+	for co.NumParents() > 0 {
 86+		co, err = r.commitForHash(co.ParentHashes[0])
 87 		if err != nil {
 88-			if err == object.ErrParentNotFound {
 89-				err = nil
 90-			}
 91-			break
 92+			return nil, err
 93 		}
 94-		commits = append(commits, &gitypes.Commit{Commit: co})
 95+		commits = append(commits, co)
 96 	}
 97 	if err != nil {
 98 		return nil, err
 99@@ -136,31 +161,6 @@ func (r *Repo) targetHash(ref *plumbing.Reference) (plumbing.Hash, error) {
100 	return hash, nil
101 }
102 
103-// loadCommits loads the commits for a repository.
104-func (r *Repo) loadCommits(ref *plumbing.Reference) (gitypes.Commits, error) {