all repos — legit @ 30c0f3eea0b2148902c4f4e94c6fa6a63251b665

web frontend for git, written in go

git/git.go (view raw)

  1package git
  2
  3import (
  4	"fmt"
  5	"sort"
  6
  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 GitRepo struct {
 13	r *git.Repository
 14	h plumbing.Hash
 15}
 16
 17type TagList []*object.Tag
 18
 19func (self TagList) Len() int {
 20	return len(self)
 21}
 22
 23func (self TagList) Swap(i, j int) {
 24	self[i], self[j] = self[j], self[i]
 25}
 26
 27// sorting tags in reverse chronological order
 28func (self TagList) Less(i, j int) bool {
 29	return self[i].Tagger.When.After(self[j].Tagger.When)
 30}
 31
 32func Open(path string, ref string) (*GitRepo, error) {
 33	var err error
 34	g := GitRepo{}
 35	g.r, err = git.PlainOpen(path)
 36	if err != nil {
 37		return nil, fmt.Errorf("opening %s: %w", path, err)
 38	}
 39
 40	if ref == "" {
 41		head, err := g.r.Head()
 42		if err != nil {
 43			return nil, fmt.Errorf("getting head of %s: %w", path, err)
 44		}
 45		g.h = head.Hash()
 46	} else {
 47		hash, err := g.r.ResolveRevision(plumbing.Revision(ref))
 48		if err != nil {
 49			return nil, fmt.Errorf("resolving rev %s for %s: %w", ref, path, err)
 50		}
 51		g.h = *hash
 52	}
 53	return &g, nil
 54}
 55
 56func (g *GitRepo) Commits() ([]*object.Commit, error) {
 57	ci, err := g.r.Log(&git.LogOptions{From: g.h})
 58	if err != nil {
 59		return nil, fmt.Errorf("commits from ref: %w", err)
 60	}
 61
 62	commits := []*object.Commit{}
 63	ci.ForEach(func(c *object.Commit) error {
 64		commits = append(commits, c)
 65		return nil
 66	})
 67
 68	return commits, nil
 69}
 70
 71func (g *GitRepo) LastCommit() (*object.Commit, error) {
 72	c, err := g.r.CommitObject(g.h)
 73	if err != nil {
 74		return nil, fmt.Errorf("last commit: %w", err)
 75	}
 76	return c, nil
 77}
 78
 79func (g *GitRepo) FileContent(path string) (string, error) {
 80	c, err := g.r.CommitObject(g.h)
 81	if err != nil {
 82		return "", fmt.Errorf("commit object: %w", err)
 83	}
 84
 85	tree, err := c.Tree()
 86	if err != nil {
 87		return "", fmt.Errorf("file tree: %w", err)
 88	}
 89
 90	file, err := tree.File(path)
 91	if err != nil {
 92		return "", err
 93	}
 94
 95	isbin, _ := file.IsBinary()
 96
 97	if !isbin {
 98		return file.Contents()
 99	} else {
100		return "Not displaying binary file", nil
101	}
102}
103
104func (g *GitRepo) Tags() ([]*object.Tag, error) {
105	ti, err := g.r.TagObjects()
106	if err != nil {
107		return nil, fmt.Errorf("tag objects: %w", err)
108	}
109
110	tags := []*object.Tag{}
111
112	_ = ti.ForEach(func(t *object.Tag) error {
113		for i, existing := range tags {
114			if existing.Name == t.Name {
115				if t.Tagger.When.After(existing.Tagger.When) {
116					tags[i] = t
117				}
118				return nil
119			}
120		}
121		tags = append(tags, t)
122		return nil
123	})
124
125	var tagList TagList
126	tagList = tags
127	sort.Sort(tagList)
128
129	return tags, nil
130}
131
132func (g *GitRepo) Branches() ([]*plumbing.Reference, error) {
133	bi, err := g.r.Branches()
134	if err != nil {
135		return nil, fmt.Errorf("branchs: %w", err)
136	}
137
138	branches := []*plumbing.Reference{}
139
140	_ = bi.ForEach(func(ref *plumbing.Reference) error {
141		branches = append(branches, ref)
142		return nil
143	})
144
145	return branches, nil
146}
147
148func (g *GitRepo) FindMainBranch(branches []string) (string, error) {
149	for _, b := range branches {
150		_, err := g.r.ResolveRevision(plumbing.Revision(b))
151		if err == nil {
152			return b, nil
153		}
154	}
155	return "", fmt.Errorf("unable to find main branch")
156}