fix: cache repo references

Ayman Bagabas created

Change summary

internal/git/git.go                      | 25 ++++++++++++++++++++-----
internal/tui/bubbles/git/about/bubble.go |  2 +-
internal/tui/bubbles/git/bubble.go       |  2 +-
internal/tui/bubbles/git/log/bubble.go   |  2 +-
internal/tui/bubbles/git/refs/bubble.go  | 24 +++++++++---------------
internal/tui/bubbles/git/tree/bubble.go  |  4 ++--
internal/tui/bubbles/git/types/git.go    |  5 +++--
7 files changed, 37 insertions(+), 27 deletions(-)

Detailed changes

internal/git/git.go 🔗

@@ -29,6 +29,7 @@ type Repo struct {
 	LastUpdated *time.Time
 	refCommits  map[plumbing.Hash]gitypes.Commits
 	ref         *plumbing.Reference
+	refs        []*plumbing.Reference
 }
 
 // GetName returns the name of the repository.
@@ -36,17 +37,21 @@ func (r *Repo) GetName() string {
 	return r.Name
 }
 
-// GetReference returns the reference for a repository.
-func (r *Repo) GetReference() *plumbing.Reference {
+// GetHEAD returns the reference for a repository.
+func (r *Repo) GetHEAD() *plumbing.Reference {
 	return r.ref
 }
 
-// SetReference sets the repository head reference.
-func (r *Repo) SetReference(ref *plumbing.Reference) error {
+// SetHEAD sets the repository head reference.
+func (r *Repo) SetHEAD(ref *plumbing.Reference) error {
 	r.ref = ref
 	return nil
 }
 
+func (r *Repo) GetReferences() []*plumbing.Reference {
+	return r.refs
+}
+
 // GetRepository returns the underlying go-git repository object.
 func (r *Repo) GetRepository() *git.Repository {
 	return r.Repository
@@ -273,13 +278,23 @@ func (rs *RepoSource) loadRepo(name string, rg *git.Repository) (*Repo, error) {
 		return nil, err
 	}
 	r.Readme = rm
+	refs := make([]*plumbing.Reference, 0)
+	ri, err := rg.References()
+	if err != nil {
+		return nil, err
+	}
+	ri.ForEach(func(r *plumbing.Reference) error {
+		refs = append(refs, r)
+		return nil
+	})
+	r.refs = refs
 	return r, nil
 }
 
 // LatestFile returns the latest file at the specified path in the repository.
 func (r *Repo) LatestFile(path string) (string, error) {
 	lg, err := r.Repository.Log(&git.LogOptions{
-		From: r.GetReference().Hash(),
+		From: r.GetHEAD().Hash(),
 	})
 	if err != nil {
 		return "", err

internal/tui/bubbles/git/about/bubble.go 🔗

@@ -30,7 +30,7 @@ func NewBubble(repo types.Repo, styles *style.Styles, width, wm, height, hm int)
 		styles:       styles,
 		widthMargin:  wm,
 		heightMargin: hm,
-		ref:          repo.GetReference(),
+		ref:          repo.GetHEAD(),
 	}
 	b.SetSize(width, height)
 	return b

internal/tui/bubbles/git/bubble.go 🔗

@@ -47,7 +47,7 @@ func NewBubble(repo types.Repo, styles *style.Styles, width, wm, height, hm int)
 		heightMargin: hm,
 		style:        styles,
 		boxes:        make([]tea.Model, 4),
-		ref:          repo.GetReference(),
+		ref:          repo.GetHEAD(),
 	}
 	heightMargin := hm + lipgloss.Height(b.headerView())
 	b.boxes[aboutPage] = about.NewBubble(repo, b.style, b.width, wm, b.height, heightMargin)

internal/tui/bubbles/git/log/bubble.go 🔗

@@ -125,7 +125,7 @@ func NewBubble(repo types.Repo, styles *style.Styles, width, widthMargin, height
 		height:       height,
 		heightMargin: heightMargin,
 		list:         l,
-		ref:          repo.GetReference(),
+		ref:          repo.GetHEAD(),
 	}
 	b.SetSize(width, height)
 	return b

internal/tui/bubbles/git/refs/bubble.go 🔗

@@ -93,7 +93,7 @@ func NewBubble(repo types.Repo, styles *style.Styles, width, widthMargin, height
 		widthMargin:  widthMargin,
 		heightMargin: heightMargin,
 		list:         l,
-		ref:          repo.GetReference(),
+		ref:          repo.GetHEAD(),
 	}
 	b.SetSize(width, height)
 	return b
@@ -123,21 +123,15 @@ func (b *Bubble) Help() []types.HelpEntry {
 func (b *Bubble) updateItems() tea.Cmd {
 	its := make(items, 0)
 	tags := make(items, 0)
-	ri, err := b.repo.GetRepository().References()
-	if err != nil {
-		return nil
-	}
-	if err = ri.ForEach(func(r *plumbing.Reference) error {
-		if r.Type() == plumbing.HashReference {
-			if r.Name().IsTag() {
-				tags = append(tags, item{r})
-			} else {
-				its = append(its, item{r})
-			}
+	for _, r := range b.repo.GetReferences() {
+		if r.Type() != plumbing.HashReference {
+			continue
+		}
+		if r.Name().IsTag() {
+			tags = append(tags, item{r})
+		} else {
+			its = append(its, item{r})
 		}
-		return nil
-	}); err != nil {
-		return nil
 	}
 	sort.Sort(its)
 	sort.Sort(tags)

internal/tui/bubbles/git/tree/bubble.go 🔗

@@ -154,7 +154,7 @@ func NewBubble(repo types.Repo, styles *style.Styles, width, widthMargin, height
 		heightMargin: heightMargin,
 		list:         l,
 		state:        treeState,
-		ref:          repo.GetReference(),
+		ref:          repo.GetHEAD(),
 	}
 	b.SetSize(width, height)
 	return b
@@ -222,7 +222,7 @@ func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 
 	case tea.KeyMsg:
 		if b.state == errorState {
-			ref := b.repo.GetReference()
+			ref := b.repo.GetHEAD()
 			b.ref = ref
 			return b, tea.Batch(b.reset(), func() tea.Msg {
 				return ref

internal/tui/bubbles/git/types/git.go 🔗

@@ -8,8 +8,9 @@ import (
 
 type Repo interface {
 	GetName() string
-	GetReference() *plumbing.Reference
-	SetReference(*plumbing.Reference) error
+	GetHEAD() *plumbing.Reference
+	SetHEAD(*plumbing.Reference) error
+	GetReferences() []*plumbing.Reference
 	GetReadme() string
 	GetCommits(*plumbing.Reference) (Commits, error)
 	GetRepository() *git.Repository