1package git
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7
8 "github.com/charmbracelet/soft-serve/git"
9 "github.com/gobwas/glob"
10)
11
12type gitRepo struct {
13 repo *git.Repository
14 desc string
15 rm string
16 rp string
17}
18
19// NewRepo returns a new git repository that conforms to the GitRepo interface.
20func NewRepo(path string) (GitRepo, error) {
21 repo, err := git.Open(path)
22 if err != nil {
23 return nil, err
24 }
25 return &gitRepo{repo: repo}, nil
26}
27
28func (r *gitRepo) Name() string {
29 return r.repo.Name()
30}
31
32func (r *gitRepo) Repo() string {
33 return r.repo.Name()
34}
35
36func (r *gitRepo) Description() string {
37 if r.desc != "" {
38 return r.desc
39 }
40 gd, err := r.repo.RevParse("--git-dir")
41 if err != nil {
42 return ""
43 }
44 gp := filepath.Join(r.repo.Path, gd, "description")
45 desc, err := os.ReadFile(gp)
46 if err != nil {
47 return ""
48 }
49 r.desc = strings.TrimSpace(string(desc))
50 return r.desc
51}
52
53func (r *gitRepo) IsPrivate() bool {
54 return false
55}
56
57func (r *gitRepo) Readme() (string, string) {
58 if r.rm != "" && r.rp != "" {
59 return r.rm, r.rp
60 }
61 pattern := "README*"
62 g := glob.MustCompile(pattern)
63 dir := filepath.Dir(pattern)
64 head, err := r.HEAD()
65 if err != nil {
66 return "", ""
67 }
68 t, err := r.repo.TreePath(head, dir)
69 if err != nil {
70 return "", ""
71 }
72 ents, err := t.Entries()
73 if err != nil {
74 return "", ""
75 }
76 for _, e := range ents {
77 fp := filepath.Join(dir, e.Name())
78 if e.IsTree() {
79 continue
80 }
81 if g.Match(fp) {
82 bts, err := e.Contents()
83 if err != nil {
84 return "", ""
85 }
86 r.rm = string(bts)
87 r.rp = fp
88 return r.rm, r.rp
89 }
90 }
91 return "", ""
92}
93
94func (r *gitRepo) Tree(ref *git.Reference, path string) (*git.Tree, error) {
95 return r.repo.TreePath(ref, path)
96}
97
98func (r *gitRepo) CommitsByPage(ref *git.Reference, page, size int) (git.Commits, error) {
99 return r.repo.CommitsByPage(ref, page, size)
100}
101
102func (r *gitRepo) CountCommits(ref *git.Reference) (int64, error) {
103 tc, err := r.repo.CountCommits(ref)
104 if err != nil {
105 return 0, err
106 }
107 return tc, nil
108}
109
110func (r *gitRepo) Diff(commit *git.Commit) (*git.Diff, error) {
111 diff, err := r.repo.Diff(commit)
112 if err != nil {
113 return nil, err
114 }
115 return diff, nil
116}
117
118func (r *gitRepo) HEAD() (*git.Reference, error) {
119 h, err := r.repo.HEAD()
120 if err != nil {
121 return nil, err
122 }
123 return h, nil
124}
125
126func (r *gitRepo) References() ([]*git.Reference, error) {
127 return r.repo.References()
128}