1package tui
  2
  3import (
  4	"path/filepath"
  5
  6	gitypes "github.com/charmbracelet/soft-serve/internal/tui/bubbles/git/types"
  7	"github.com/go-git/go-git/v5"
  8	"github.com/go-git/go-git/v5/plumbing"
  9	"github.com/go-git/go-git/v5/plumbing/object"
 10)
 11
 12type Repo struct {
 13	name   string
 14	repo   *git.Repository
 15	readme string
 16	ref    *plumbing.Reference
 17}
 18
 19func (r *Repo) Name() string {
 20	return r.name
 21}
 22
 23func (r *Repo) GetReference() *plumbing.Reference {
 24	return r.ref
 25}
 26
 27func (r *Repo) SetReference(ref *plumbing.Reference) error {
 28	r.ref = ref
 29	return nil
 30}
 31
 32func (r *Repo) Repository() *git.Repository {
 33	return r.repo
 34}
 35
 36func (r *Repo) Tree(path string) (*object.Tree, error) {
 37	path = filepath.Clean(path)
 38	c, err := r.repo.CommitObject(r.ref.Hash())
 39	if err != nil {
 40		return nil, err
 41	}
 42	t, err := c.Tree()
 43	if err != nil {
 44		return nil, err
 45	}
 46	if path == "." {
 47		return t, nil
 48	}
 49	return t.Tree(path)
 50}
 51
 52func (r *Repo) GetCommits(limit int) (gitypes.Commits, error) {
 53	commits := gitypes.Commits{}
 54	l, err := r.repo.Log(&git.LogOptions{
 55		Order: git.LogOrderCommitterTime,
 56		From:  r.ref.Hash(),
 57	})
 58	if err != nil {
 59		return nil, err
 60	}
 61	err = l.ForEach(func(c *object.Commit) error {
 62		commits = append(commits, &gitypes.Commit{c})
 63		return nil
 64	})
 65	if err != nil {
 66		return nil, err
 67	}
 68	if limit <= 0 || limit > len(commits) {
 69		limit = len(commits)
 70	}
 71	return commits[:limit], nil
 72}
 73
 74func (r *Repo) GetReadme() string {
 75	if r.readme != "" {
 76		return r.readme
 77	}
 78	md, err := r.readFile("README.md")
 79	if err != nil {
 80		return ""
 81	}
 82	return md
 83}
 84
 85func (r *Repo) readFile(path string) (string, error) {
 86	lg, err := r.repo.Log(&git.LogOptions{
 87		From: r.ref.Hash(),
 88	})
 89	if err != nil {
 90		return "", err
 91	}
 92	c, err := lg.Next()
 93	if err != nil {
 94		return "", err
 95	}
 96	f, err := c.File(path)
 97	if err != nil {
 98		return "", err
 99	}
100	content, err := f.Contents()
101	if err != nil {
102		return "", err
103	}
104	return content, nil
105}