cerrado @ 6079b1d963f34ada5c4b25363f2319901e283936

  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) ([]*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) ([]*object.Tag, 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	gitList := &templates.GitItemPage{
 95		Name:        name,
 96		Ref:         ref.Name().Short(),
 97		GitItemBase: &templates.GitItemSummaryPage{},
 98	}
 99	templates.WritePageTemplate(w, gitList)
100	return nil
101}
102
103func (g *GitHandler) About(w http.ResponseWriter, r *http.Request) error {
104	ext.SetHTML(w)
105	name := r.PathValue("name")
106	ref, err := g.gitService.GetHead(name)
107	if err != nil {
108		return err
109	}
110	gitList := &templates.GitItemPage{
111		Name:        name,
112		Ref:         ref.Name().Short(),
113		GitItemBase: &templates.GitItemAboutPage{},
114	}
115	templates.WritePageTemplate(w, gitList)
116	return nil
117}
118
119func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) error {
120	ext.SetHTML(w)
121	name := r.PathValue("name")
122
123	tags, err := g.gitService.ListTags(name)
124	if err != nil {
125		return err
126	}
127
128	branches, err := g.gitService.ListBranches(name)
129	if err != nil {
130		return err
131	}
132
133	ref, err := g.gitService.GetHead(name)
134	if err != nil {
135		return err
136	}
137
138	gitList := &templates.GitItemPage{
139		Name: name,
140		Ref:  ref.Name().Short(),
141		GitItemBase: &templates.GitItemRefsPage{
142			Tags:     tags,
143			Branches: branches,
144		},
145	}
146	templates.WritePageTemplate(w, gitList)
147	return nil
148}
149
150func (g *GitHandler) Tree(w http.ResponseWriter, r *http.Request) error {
151	ext.SetHTML(w)
152	name := r.PathValue("name")
153	ref := r.PathValue("ref")
154	rest := r.PathValue("rest")
155
156	tree, err := g.gitService.GetTree(name, ref, rest)
157	if err != nil {
158		return err
159	}
160
161	gitList := &templates.GitItemPage{
162		Name: name,
163		Ref:  ref,
164		GitItemBase: &templates.GitItemTreePage{
165			CurrentPath: rest,
166			Tree:        tree,
167			Ref:         ref,
168			Name:        name,
169		},
170	}
171	templates.WritePageTemplate(w, gitList)
172	return nil
173}
174
175func (g *GitHandler) Blob(w http.ResponseWriter, r *http.Request) error {
176	ext.SetHTML(w)
177	name := r.PathValue("name")
178	ref := r.PathValue("ref")
179	rest := r.PathValue("rest")
180
181	file, err := g.gitService.GetFileContent(name, ref, rest)
182	if err != nil {
183		return err
184	}
185
186	filename := filepath.Base(rest)
187	lexer := GetLexers(filename)
188	style := styles.Get("xcode")
189	formatter := html.New(
190		html.WithLineNumbers(true),
191	)
192	iterator, err := lexer.Tokenise(nil, file)
193	if err != nil {
194		return err
195	}
196
197	var code bytes.Buffer
198	err = formatter.Format(&code, style, iterator)
199	if err != nil {
200		return err
201	}
202
203	gitList := &templates.GitItemPage{
204		Name: name,
205		Ref:  ref,
206		GitItemBase: &templates.GitItemBlobPage{
207			File:    rest,
208			Content: code.Bytes(),
209		},
210	}
211	templates.WritePageTemplate(w, gitList)
212	return nil
213}
214
215func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) error {
216	ext.SetHTML(w)
217	name := r.PathValue("name")
218	ref := r.PathValue("ref")
219
220	commits, err := g.gitService.ListCommits(name, ref)
221	if err != nil {
222		return err
223	}
224
225	gitList := &templates.GitItemPage{
226		Name: name,
227		Ref:  ref,
228		GitItemBase: &templates.GitItemLogPage{
229			Commits: commits,
230		},
231	}
232	templates.WritePageTemplate(w, gitList)
233	return nil
234}
235
236func GetLexers(filename string) chroma.Lexer {
237	if filename == "APKBUILD" {
238		return lexers.Get("sh")
239	}
240
241	lexer := lexers.Get(filename)
242
243	if lexer == nil {
244		lexer = lexers.Get("txt")
245	}
246	return lexer
247}