cerrado @ 19839337ce0c74b67c5480b71e98d97a112aa104

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