all repos — legit @ c14c33b9166614e77aaca735ca3d0eacf8c81a61

web frontend for git

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