cerrado @ b71c6c0e5b8dd00d44e40ac0551902a23cbe19d5

  1package git
  2
  3import (
  4	"bytes"
  5	"io"
  6	"net/http"
  7	"os"
  8	"path/filepath"
  9
 10	"git.gabrielgio.me/cerrado/pkg/ext"
 11	"git.gabrielgio.me/cerrado/pkg/service"
 12	"git.gabrielgio.me/cerrado/templates"
 13	"github.com/alecthomas/chroma/v2"
 14	"github.com/alecthomas/chroma/v2/formatters/html"
 15	"github.com/alecthomas/chroma/v2/lexers"
 16	"github.com/alecthomas/chroma/v2/styles"
 17	"github.com/go-git/go-git/v5/plumbing"
 18	"github.com/go-git/go-git/v5/plumbing/object"
 19	"github.com/gomarkdown/markdown"
 20	markdownhtml "github.com/gomarkdown/markdown/html"
 21	"github.com/gomarkdown/markdown/parser"
 22)
 23
 24type (
 25	GitHandler struct {
 26		gitService gitService
 27		readmePath string
 28	}
 29
 30	gitService interface {
 31		ListRepositories() ([]*service.Repository, error)
 32		ListCommits(name string, ref string, count int) ([]*object.Commit, error)
 33		GetHead(name string) (*plumbing.Reference, error)
 34		GetTree(name, ref, path string) (*object.Tree, error)
 35		GetFileContent(name, ref, path string) (string, error)
 36		ListTags(name string) ([]*plumbing.Reference, error)
 37		ListBranches(name string) ([]*plumbing.Reference, error)
 38	}
 39
 40	configurationRepository interface {
 41		GetRootReadme() string
 42	}
 43)
 44
 45func NewGitHandler(gitService gitService, confRepo configurationRepository) *GitHandler {
 46	return &GitHandler{
 47		gitService: gitService,
 48		readmePath: confRepo.GetRootReadme(),
 49	}
 50}
 51
 52func (g *GitHandler) List(w http.ResponseWriter, _ *http.Request) error {
 53	repos, err := g.gitService.ListRepositories()
 54	if err != nil {
 55		return err
 56	}
 57
 58	f, err := os.Open(g.readmePath)
 59	if err != nil {
 60		return err
 61	}
 62
 63	bs, err := io.ReadAll(f)
 64	if err != nil {
 65		return err
 66	}
 67
 68	extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
 69	p := parser.NewWithExtensions(extensions)
 70	doc := p.Parse(bs)
 71
 72	htmlFlag := markdownhtml.CommonFlags | markdownhtml.HrefTargetBlank
 73	opts := markdownhtml.RendererOptions{Flags: htmlFlag}
 74	renderer := markdownhtml.NewRenderer(opts)
 75
 76	bs = markdown.Render(doc, renderer)
 77
 78	gitList := &templates.GitListPage{
 79		Respositories: repos,
 80		About:         bs,
 81	}
 82	templates.WritePageTemplate(w, gitList)
 83	return nil
 84}
 85
 86func (g *GitHandler) Summary(w http.ResponseWriter, r *http.Request) error {
 87	ext.SetHTML(w)
 88	name := r.PathValue("name")
 89	ref, err := g.gitService.GetHead(name)
 90	if err != nil {
 91		return err
 92	}
 93
 94	tags, err := g.gitService.ListTags(name)
 95	if err != nil {
 96		return err
 97	}
 98
 99	branches, err := g.gitService.ListBranches(name)
100	if err != nil {
101		return err
102	}
103
104	commits, err := g.gitService.ListCommits(name, "", 10)
105	if err != nil {
106		return err
107	}
108
109	gitList := &templates.GitItemPage{
110		Name: name,
111		Ref:  ref.Name().Short(),
112		GitItemBase: &templates.GitItemSummaryPage{
113			Tags:     tags,
114			Branches: branches,
115			Commits:  commits,
116		},
117	}
118	templates.WritePageTemplate(w, gitList)
119	return nil
120}
121
122func (g *GitHandler) About(w http.ResponseWriter, r *http.Request) error {
123	ext.SetHTML(w)
124	name := r.PathValue("name")
125	ref, err := g.gitService.GetHead(name)
126	if err != nil {
127		return err
128	}
129	gitList := &templates.GitItemPage{
130		Name:        name,
131		Ref:         ref.Name().Short(),
132		GitItemBase: &templates.GitItemAboutPage{},
133	}
134	templates.WritePageTemplate(w, gitList)
135	return nil
136}
137
138func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) error {
139	ext.SetHTML(w)
140	name := r.PathValue("name")
141
142	tags, err := g.gitService.ListTags(name)
143	if err != nil {
144		return err
145	}
146
147	branches, err := g.gitService.ListBranches(name)
148	if err != nil {
149		return err
150	}
151
152	ref, err := g.gitService.GetHead(name)
153	if err != nil {
154		return err
155	}
156
157	gitList := &templates.GitItemPage{
158		Name: name,
159		Ref:  ref.Name().Short(),
160		GitItemBase: &templates.GitItemRefsPage{
161			Tags:     tags,
162			Branches: branches,
163		},
164	}
165	templates.WritePageTemplate(w, gitList)
166	return nil
167}
168
169func (g *GitHandler) Tree(w http.ResponseWriter, r *http.Request) error {
170	ext.SetHTML(w)
171	name := r.PathValue("name")
172	ref := r.PathValue("ref")
173	rest := r.PathValue("rest")
174
175	tree, err := g.gitService.GetTree(name, ref, rest)
176	if err != nil {
177		return err
178	}
179
180	gitList := &templates.GitItemPage{
181		Name: name,
182		Ref:  ref,
183		GitItemBase: &templates.GitItemTreePage{
184			CurrentPath: rest,
185			Tree:        tree,
186		},
187	}
188	templates.WritePageTemplate(w, gitList)
189	return nil
190}
191
192func (g *GitHandler) Blob(w http.ResponseWriter, r *http.Request) error {
193	ext.SetHTML(w)
194	name := r.PathValue("name")
195	ref := r.PathValue("ref")
196	rest := r.PathValue("rest")
197
198	file, err := g.gitService.GetFileContent(name, ref, rest)
199	if err != nil {
200		return err
201	}
202
203	filename := filepath.Base(rest)
204	lexer := GetLexers(filename)
205	style := styles.Get("xcode")
206	formatter := html.New(
207		html.WithLineNumbers(true),
208	)
209	iterator, err := lexer.Tokenise(nil, file)
210	if err != nil {
211		return err
212	}
213
214	var code bytes.Buffer
215	err = formatter.Format(&code, style, iterator)
216	if err != nil {
217		return err
218	}
219
220	gitList := &templates.GitItemPage{
221		Name: name,
222		Ref:  ref,
223		GitItemBase: &templates.GitItemBlobPage{
224			File:    rest,
225			Content: code.Bytes(),
226		},
227	}
228	templates.WritePageTemplate(w, gitList)
229	return nil
230}
231
232func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) error {
233	ext.SetHTML(w)
234	name := r.PathValue("name")
235	ref := r.PathValue("ref")
236
237	commits, err := g.gitService.ListCommits(name, ref, 1000)
238	if err != nil {
239		return err
240	}
241
242	gitList := &templates.GitItemPage{
243		Name: name,
244		Ref:  ref,
245		GitItemBase: &templates.GitItemLogPage{
246			Commits: commits,
247		},
248	}
249	templates.WritePageTemplate(w, gitList)
250	return nil
251}
252
253func GetLexers(filename string) chroma.Lexer {
254	if filename == "APKBUILD" {
255		return lexers.Get("sh")
256	}
257
258	lexer := lexers.Get(filename)
259
260	if lexer == nil {
261		lexer = lexers.Get("txt")
262	}
263	return lexer
264}