cerrado @ e3705f35c642e578625ce4574d189fa0b0869403

  1package git
  2
  3import (
  4	"errors"
  5	"fmt"
  6	"io"
  7
  8	"github.com/go-git/go-git/v5"
  9	"github.com/go-git/go-git/v5/plumbing"
 10	"github.com/go-git/go-git/v5/plumbing/object"
 11)
 12
 13var ()
 14
 15var (
 16	MissingRefErr = errors.New("Reference not found")
 17)
 18
 19type (
 20	GitRepository struct {
 21		path       string
 22		repository *git.Repository
 23
 24		ref plumbing.Hash
 25		// this is setRef when ref is setRef
 26		setRef bool
 27	}
 28)
 29
 30func OpenRepository(dir string) (*GitRepository, error) {
 31	g := &GitRepository{
 32		path: dir,
 33	}
 34
 35	repo, err := git.PlainOpen(dir)
 36	if err != nil {
 37		return nil, err
 38	}
 39	g.repository = repo
 40
 41	return g, nil
 42}
 43
 44func (g *GitRepository) SetRef(ref string) error {
 45	if ref == "" {
 46		head, err := g.repository.Head()
 47		if err != nil {
 48			return errors.Join(MissingRefErr, err)
 49		}
 50		g.ref = head.Hash()
 51	} else {
 52		hash, err := g.repository.ResolveRevision(plumbing.Revision(ref))
 53		if err != nil {
 54			return errors.Join(MissingRefErr, err)
 55		}
 56		g.ref = *hash
 57	}
 58	g.setRef = true
 59	return nil
 60}
 61
 62func (g *GitRepository) Path() string {
 63	return g.path
 64}
 65
 66func (g *GitRepository) LastCommit() (*object.Commit, error) {
 67	err := g.validateRef()
 68	if err != nil {
 69		return nil, err
 70	}
 71
 72	c, err := g.repository.CommitObject(g.ref)
 73	if err != nil {
 74		return nil, err
 75	}
 76	return c, nil
 77}
 78
 79func (g *GitRepository) Commits() ([]*object.Commit, error) {
 80	err := g.validateRef()
 81	if err != nil {
 82		return nil, err
 83	}
 84
 85	ci, err := g.repository.Log(&git.LogOptions{From: g.ref})
 86	if err != nil {
 87		return nil, fmt.Errorf("commits from ref: %w", err)
 88	}
 89
 90	commits := []*object.Commit{}
 91	// TODO: for now only load first 1000
 92	for x := 0; x < 1000; x++ {
 93		c, err := ci.Next()
 94		if err != nil && errors.Is(err, io.EOF) {
 95			break
 96		} else if err != nil {
 97			return nil, err
 98		}
 99		commits = append(commits, c)
100	}
101	if err != nil {
102		return nil, err
103	}
104
105	return commits, nil
106}
107
108func (g *GitRepository) Head() (*plumbing.Reference, error) {
109	return g.repository.Head()
110}
111
112func (g *GitRepository) Tags() ([]*object.Tag, error) {
113	ti, err := g.repository.TagObjects()
114	if err != nil {
115		return nil, err
116	}
117
118	tags := []*object.Tag{}
119	err = ti.ForEach(func(t *object.Tag) error {
120		tags = append(tags, t)
121		return nil
122	})
123	if err != nil {
124		return nil, err
125	}
126
127	return tags, nil
128}
129
130func (g *GitRepository) Branches() ([]*plumbing.Reference, error) {
131	bs, err := g.repository.Branches()
132	if err != nil {
133		return nil, err
134	}
135
136	branches := []*plumbing.Reference{}
137	err = bs.ForEach(func(ref *plumbing.Reference) error {
138		branches = append(branches, ref)
139		return nil
140	})
141	if err != nil {
142		return nil, err
143	}
144
145	return branches, nil
146}
147
148func (g *GitRepository) validateRef() error {
149	if !g.setRef {
150		return g.SetRef("")
151	}
152	return nil
153}