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}