git/git.go (view raw)
1package git
2
3import (
4 "fmt"
5
6 "github.com/go-git/go-git/v5"
7 "github.com/go-git/go-git/v5/plumbing"
8 "github.com/go-git/go-git/v5/plumbing/object"
9)
10
11type GitRepo struct {
12 r *git.Repository
13 h plumbing.Hash
14}
15
16func Open(path string, ref string) (*GitRepo, error) {
17 var err error
18 g := GitRepo{}
19 g.r, err = git.PlainOpen(path)
20 if err != nil {
21 return nil, fmt.Errorf("opening %s: %w", path, err)
22 }
23
24 if ref == "" {
25 head, err := g.r.Head()
26 if err != nil {
27 return nil, fmt.Errorf("getting head of %s: %w", path, err)
28 }
29 g.h = head.Hash()
30 } else {
31 hash, err := g.r.ResolveRevision(plumbing.Revision(ref))
32 if err != nil {
33 return nil, fmt.Errorf("resolving rev %s for %s: %w", ref, path, err)
34 }
35 g.h = *hash
36 }
37 return &g, nil
38}
39
40func (g *GitRepo) Commits() ([]*object.Commit, error) {
41 ci, err := g.r.Log(&git.LogOptions{From: g.h})
42 if err != nil {
43 return nil, fmt.Errorf("commits from ref: %w", err)
44 }
45
46 commits := []*object.Commit{}
47 ci.ForEach(func(c *object.Commit) error {
48 commits = append(commits, c)
49 return nil
50 })
51
52 return commits, nil
53}
54
55func (g *GitRepo) LastCommit() (*object.Commit, error) {
56 c, err := g.r.CommitObject(g.h)
57 if err != nil {
58 return nil, fmt.Errorf("last commit: %w", err)
59 }
60 return c, nil
61}
62
63func (g *GitRepo) FileContent(path string) (string, error) {
64 c, err := g.r.CommitObject(g.h)
65 if err != nil {
66 return "", fmt.Errorf("commit object: %w", err)
67 }
68
69 tree, err := c.Tree()
70 if err != nil {
71 return "", fmt.Errorf("file tree: %w", err)
72 }
73
74 file, err := tree.File(path)
75 if err != nil {
76 return "", err
77 }
78
79 return file.Contents()
80}
81
82func (g *GitRepo) Tags() ([]*object.Tag, error) {
83 ti, err := g.r.TagObjects()
84 if err != nil {
85 return nil, fmt.Errorf("tag objects: %w", err)
86 }
87
88 tags := []*object.Tag{}
89
90 _ = ti.ForEach(func(t *object.Tag) error {
91 tags = append(tags, t)
92 return nil
93 })
94
95 return tags, nil
96}
97
98func (g *GitRepo) Branches() ([]*plumbing.Reference, error) {
99 bi, err := g.r.Branches()
100 if err != nil {
101 return nil, fmt.Errorf("branchs: %w", err)
102 }
103
104 branches := []*plumbing.Reference{}
105
106 _ = bi.ForEach(func(ref *plumbing.Reference) error {
107 branches = append(branches, ref)
108 return nil
109 })
110
111 return branches, nil
112}
113
114func (g *GitRepo) FindMainBranch(branches []string) (string, error) {
115 for _, b := range branches {
116 _, err := g.r.ResolveRevision(plumbing.Revision(b))
117 if err == nil {
118 return b, nil
119 }
120 }
121 return "", fmt.Errorf("unable to find main branch")
122}