cerrado @ 18aa098f50e2a2c7db01dd4d04dde460fd40f5d5

  1package git
  2
  3import (
  4	"bytes"
  5	"log/slog"
  6	"net/http"
  7	"path/filepath"
  8
  9	"git.gabrielgio.me/cerrado/pkg/service"
 10	"git.gabrielgio.me/cerrado/templates"
 11	"github.com/alecthomas/chroma/v2"
 12	"github.com/alecthomas/chroma/v2/formatters/html"
 13	"github.com/alecthomas/chroma/v2/lexers"
 14	"github.com/alecthomas/chroma/v2/styles"
 15	"github.com/go-git/go-git/v5/plumbing"
 16	"github.com/go-git/go-git/v5/plumbing/object"
 17)
 18
 19type (
 20	GitHandler struct {
 21		gitService gitService
 22	}
 23
 24	gitService interface {
 25		ListRepositories() ([]*service.Repository, error)
 26		ListCommits(name string, ref string) ([]*object.Commit, error)
 27		GetHead(name string) (*plumbing.Reference, error)
 28		GetTree(name, ref, path string) (*object.Tree, error)
 29		GetFileContent(name, ref, path string) (string, error)
 30		ListTags(name string) ([]*object.Tag, error)
 31		ListBranches(name string) ([]*plumbing.Reference, error)
 32	}
 33)
 34
 35func NewGitHandler(gitService gitService) *GitHandler {
 36	return &GitHandler{
 37		gitService: gitService,
 38	}
 39}
 40
 41func (g *GitHandler) List(w http.ResponseWriter, _ *http.Request) {
 42	repos, err := g.gitService.ListRepositories()
 43	if err != nil {
 44		slog.Error("Error listing repo", "error", err)
 45		return
 46	}
 47
 48	gitList := &templates.GitListPage{repos}
 49	templates.WritePageTemplate(w, gitList)
 50}
 51
 52func (g *GitHandler) Summary(w http.ResponseWriter, r *http.Request) {
 53	name := r.PathValue("name")
 54	ref, err := g.gitService.GetHead(name)
 55	if err != nil {
 56		slog.Error("Error loading head", "error", err)
 57		return
 58	}
 59
 60	gitList := &templates.GitItemPage{
 61		Name:        name,
 62		Ref:         ref.Name().Short(),
 63		GitItemBase: &templates.GitItemSummaryPage{},
 64	}
 65	templates.WritePageTemplate(w, gitList)
 66}
 67
 68func (g *GitHandler) About(w http.ResponseWriter, r *http.Request) {
 69	name := r.PathValue("name")
 70	ref, err := g.gitService.GetHead(name)
 71	if err != nil {
 72		slog.Error("Error loading head", "error", err)
 73		return
 74	}
 75	gitList := &templates.GitItemPage{
 76		Name:        name,
 77		Ref:         ref.Name().Short(),
 78		GitItemBase: &templates.GitItemAboutPage{},
 79	}
 80	templates.WritePageTemplate(w, gitList)
 81}
 82
 83func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) {
 84	name := r.PathValue("name")
 85
 86	tags, err := g.gitService.ListTags(name)
 87	if err != nil {
 88		slog.Error("Error loading tags", "error", err)
 89		return
 90	}
 91
 92	branches, err := g.gitService.ListBranches(name)
 93	if err != nil {
 94		slog.Error("Error loading branches", "error", err)
 95		return
 96	}
 97
 98	ref, err := g.gitService.GetHead(name)
 99	if err != nil {
100		slog.Error("Error loading head", "error", err)
101		return
102	}
103
104	gitList := &templates.GitItemPage{
105		Name: name,
106		Ref:  ref.Name().Short(),
107		GitItemBase: &templates.GitItemRefsPage{
108			Tags:     tags,
109			Branches: branches,
110		},
111	}
112	templates.WritePageTemplate(w, gitList)
113}
114
115func (g *GitHandler) Tree(w http.ResponseWriter, r *http.Request) {
116	name := r.PathValue("name")
117	ref := r.PathValue("ref")
118	rest := r.PathValue("rest")
119
120	tree, err := g.gitService.GetTree(name, ref, rest)
121	if err != nil {
122		slog.Error("Error loading tree", "error", err)
123		return
124	}
125
126	gitList := &templates.GitItemPage{
127		Name: name,
128		Ref:  ref,
129		GitItemBase: &templates.GitItemTreePage{
130			CurrentPath: rest,
131			Tree:        tree,
132			Ref:         ref,
133			Name:        name,
134		},
135	}
136	templates.WritePageTemplate(w, gitList)
137}
138
139func (g *GitHandler) Blob(w http.ResponseWriter, r *http.Request) {
140	name := r.PathValue("name")
141	ref := r.PathValue("ref")
142	rest := r.PathValue("rest")
143
144	file, err := g.gitService.GetFileContent(name, ref, rest)
145	if err != nil {
146		slog.Error("Error loading blob", "error", err)
147		return
148	}
149
150	filename := filepath.Base(rest)
151	lexer := GetLexers(filename)
152	style := styles.Get("xcode")
153	formatter := html.New(
154		html.WithLineNumbers(true),
155	)
156	iterator, err := lexer.Tokenise(nil, file)
157	if err != nil {
158		slog.Error("Error tokenise", "error", err)
159		return
160	}
161
162	var code bytes.Buffer
163	err = formatter.Format(&code, style, iterator)
164	if err != nil {
165		slog.Error("Error format", "error", err)
166		return
167	}
168
169	gitList := &templates.GitItemPage{
170		Name: name,
171		Ref:  ref,
172		GitItemBase: &templates.GitItemBlobPage{
173			File:    rest,
174			Content: code.Bytes(),
175		},
176	}
177	templates.WritePageTemplate(w, gitList)
178}
179
180func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) {
181	name := r.PathValue("name")
182	ref := r.PathValue("ref")
183
184	commits, err := g.gitService.ListCommits(name, ref)
185	if err != nil {
186		slog.Error("Error loading commits", "error", err)
187		return
188	}
189
190	gitList := &templates.GitItemPage{
191		Name: name,
192		Ref:  ref,
193		GitItemBase: &templates.GitItemLogPage{
194			Commits: commits,
195		},
196	}
197	templates.WritePageTemplate(w, gitList)
198}
199
200func GetLexers(filename string) chroma.Lexer {
201	if filename == "APKBUILD" {
202		return lexers.Get("sh")
203	}
204
205	lexer := lexers.Get(filename)
206
207	if lexer == nil {
208		lexer = lexers.Get("txt")
209	}
210	return lexer
211}