1diff --git a/pkg/ext/compression.go b/pkg/ext/compression.go
2index 92144b82132968aa7db6115aad78f37d71c8e354..57ad49ad64f6654f9ec39ea50af972f0739d5e44 100644
3--- a/pkg/ext/compression.go
4+++ b/pkg/ext/compression.go
5@@ -24,7 +24,7 @@ innerWriter http.ResponseWriter
6 compressWriter io.Writer
7 }
8
9-func Compress(next func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
10+func Compress(next http.HandlerFunc) http.HandlerFunc {
11 return func(w http.ResponseWriter, r *http.Request) {
12 if accept, ok := r.Header["Accept-Encoding"]; ok {
13 if compress, algo := GetCompressionWriter(u.FirstOrZero(accept), w); algo != "" {
14diff --git a/pkg/ext/log.go b/pkg/ext/log.go
15new file mode 100644
16index 0000000000000000000000000000000000000000..a9d26a9afd92ce2309d6f27653577a97a9b76c1e
17--- /dev/null
18+++ b/pkg/ext/log.go
19@@ -0,0 +1,53 @@
20+package ext
21+
22+import (
23+ "log/slog"
24+ "net/http"
25+ "time"
26+)
27+
28+type statusWraper struct {
29+ statusCode int
30+ innerWriter http.ResponseWriter
31+}
32+
33+func (s *statusWraper) Header() http.Header {
34+ return s.innerWriter.Header()
35+}
36+
37+func (s *statusWraper) Write(b []byte) (int, error) {
38+ return s.innerWriter.Write(b)
39+}
40+
41+func (s *statusWraper) WriteHeader(statusCode int) {
42+ s.statusCode = statusCode
43+ s.innerWriter.WriteHeader(statusCode)
44+}
45+
46+func (s *statusWraper) StatusCode() int {
47+ if s.statusCode == 0 {
48+ return 200
49+ }
50+ return s.statusCode
51+}
52+
53+func wrap(w http.ResponseWriter) *statusWraper {
54+ return &statusWraper{
55+ innerWriter: w,
56+ }
57+}
58+
59+func Log(next http.HandlerFunc) http.HandlerFunc {
60+ return func(w http.ResponseWriter, r *http.Request) {
61+ t := time.Now()
62+ s := wrap(w)
63+ next(s, r)
64+ slog.Info(
65+ "Http request",
66+ "method", r.Method,
67+ "code", s.StatusCode(),
68+ "path", r.URL,
69+ "elapsed", time.Since(t),
70+ )
71+ }
72+}
73diff --git a/pkg/ext/router.go b/pkg/ext/router.go
74new file mode 100644
75index 0000000000000000000000000000000000000000..5d22814e9d53c5a65f4f72c6cdf67be9f929bcbb
76--- /dev/null
77+++ b/pkg/ext/router.go
78@@ -0,0 +1,72 @@
79+package ext
80+
81+import (
82+ "errors"
83+ "fmt"
84+ "net/http"
85+
86+ "git.gabrielgio.me/cerrado/pkg/service"
87+ "git.gabrielgio.me/cerrado/templates"
88+)
89+
90+type (
91+ Router struct {
92+ middlewares []Middleware
93+ router *http.ServeMux
94+ }
95+ Middleware func(next http.HandlerFunc) http.HandlerFunc
96+ ErrorRequestHandler func(w http.ResponseWriter, r *http.Request) error
97+)
98+
99+func NewRouter() *Router {
100+ return &Router{
101+ router: http.NewServeMux(),
102+ }
103+}
104+func (r *Router) Handler() http.Handler {
105+ return r.router
106+}
107+
108+func (r *Router) AddMiddleware(middleware Middleware) {
109+ r.middlewares = append(r.middlewares, middleware)
110+}
111+
112+func wrapError(next ErrorRequestHandler) http.HandlerFunc {
113+ return func(w http.ResponseWriter, r *http.Request) {
114+ if err := next(w, r); err != nil {
115+ if errors.Is(err, service.RepositoryNotFoundErr) {
116+ NotFound(w)
117+ } else {
118+ InternalServerError(w, err)
119+ }
120+ }
121+ }
122+}
123+
124+func (r *Router) run(next ErrorRequestHandler) http.HandlerFunc {
125+ return func(w http.ResponseWriter, re *http.Request) {
126+ req := wrapError(next)
127+ for _, r := range r.middlewares {
128+ req = r(req)
129+ }
130+ req(w, re)
131+ }
132+}
133+
134+func (r *Router) HandleFunc(path string, handler ErrorRequestHandler) {
135+ r.router.HandleFunc(path, r.run(handler))
136+}
137+
138+func NotFound(w http.ResponseWriter) {
139+ w.WriteHeader(http.StatusNotFound)
140+ templates.WritePageTemplate(w, &templates.ErrorPage{
141+ Message: "Not Found",
142+ })
143+}
144+
145+func InternalServerError(w http.ResponseWriter, err error) {
146+ w.WriteHeader(http.StatusInternalServerError)
147+ templates.WritePageTemplate(w, &templates.ErrorPage{
148+ Message: fmt.Sprintf("Internal Server Error:\n%s", err.Error()),
149+ })
150+}
151diff --git a/pkg/git/git.go b/pkg/git/git.go
152index 6a7b91fcba4060e8c2462a6ff03cf9fd309218d4..ad5d3bca28fe075da5da0ea6ae72cb87bd09861a 100644
153--- a/pkg/git/git.go
154+++ b/pkg/git/git.go
155@@ -99,9 +99,6 @@ return nil, err
156 }
157 commits = append(commits, c)
158 }
159- if err != nil {
160- return nil, err
161- }
162
163 return commits, nil
164 }
165diff --git a/pkg/handler/about/handler.go b/pkg/handler/about/handler.go
166index 1acde601c7aa036550ab6e73253f7c820646e1e6..ac3d31417836e98121bd03807b2993fa2dbf27cb 100644
167--- a/pkg/handler/about/handler.go
168+++ b/pkg/handler/about/handler.go
169@@ -2,7 +2,6 @@ package about
170
171 import (
172 "io"
173- "log/slog"
174 "net/http"
175 "os"
176
177@@ -27,17 +26,15 @@ func NewAboutHandler(configRepo configurationRepository) *AboutHandler {
178 return &AboutHandler{configRepo.GetRootReadme()}
179 }
180
181-func (g *AboutHandler) About(w http.ResponseWriter, _ *http.Request) {
182+func (g *AboutHandler) About(w http.ResponseWriter, _ *http.Request) error {
183 f, err := os.Open(g.readmePath)
184 if err != nil {
185- slog.Error("Error loading readme file", "error", err)
186- return
187+ return err
188 }
189
190 bs, err := io.ReadAll(f)
191 if err != nil {
192- slog.Error("Error reading readme file bytes", "error", err)
193- return
194+ return err
195 }
196
197 extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
198@@ -54,4 +51,5 @@ gitList := &templates.AboutPage{
199 Body: bs,
200 }
201 templates.WritePageTemplate(w, gitList)
202+ return nil
203 }
204diff --git a/pkg/handler/config/handler.go b/pkg/handler/config/handler.go
205index 30f428383db9ada7b0337c2400b983a7d1a4b8c2..c43b54d621d0aed6441a8f2ba85564c0be3da6fe 100644
206--- a/pkg/handler/config/handler.go
207+++ b/pkg/handler/config/handler.go
208@@ -3,7 +3,6 @@
209 import (
210 "bytes"
211 "encoding/json"
212- "log/slog"
213 "net/http"
214
215 "github.com/alecthomas/chroma/v2/formatters/html"
216@@ -11,6 +10,7 @@ "github.com/alecthomas/chroma/v2/lexers"
217 "github.com/alecthomas/chroma/v2/styles"
218
219 "git.gabrielgio.me/cerrado/pkg/config"
220+ "git.gabrielgio.me/cerrado/pkg/ext"
221 "git.gabrielgio.me/cerrado/templates"
222 )
223
224@@ -21,8 +21,8 @@ List() []*config.GitRepositoryConfiguration
225 }
226 )
227
228-func ConfigFile(configRepo configurationRepository) func(http.ResponseWriter, *http.Request) {
229- return func(w http.ResponseWriter, _ *http.Request) {
230+func ConfigFile(configRepo configurationRepository) ext.ErrorRequestHandler {
231+ return func(w http.ResponseWriter, _ *http.Request) error {
232
233 config := struct {
234 RootReadme string
235@@ -34,8 +34,7 @@ }
236
237 b, err := json.MarshalIndent(config, "", " ")
238 if err != nil {
239- slog.Error("Error parsing json", "error", err)
240- return
241+ return err
242 }
243
244 lexer := lexers.Get("json")
245@@ -45,15 +44,13 @@ html.WithLineNumbers(true),
246 )
247 iterator, err := lexer.Tokenise(nil, string(b))
248 if err != nil {
249- slog.Error("Error tokenise", "error", err)
250- return
251+ return err
252 }
253
254 var code bytes.Buffer
255 err = formatter.Format(&code, style, iterator)
256 if err != nil {
257- slog.Error("Error format", "error", err)
258- return
259+ return err
260 }
261
262 hello := &templates.ConfigPage{
263@@ -61,5 +58,6 @@ Body: code.Bytes(),
264 }
265
266 templates.WritePageTemplate(w, hello)
267+ return nil
268 }
269 }
270diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
271index 7bdf3729016402aa7f8f1e462d9b34c209109835..d952fef3bc513240d3f602426e7572fa84033a9e 100644
272--- a/pkg/handler/git/handler.go
273+++ b/pkg/handler/git/handler.go
274@@ -3,7 +3,6 @@
275 import (
276 "bytes"
277 "io"
278- "log/slog"
279 "net/http"
280 "os"
281 "path/filepath"
282@@ -50,23 +49,20 @@ readmePath: confRepo.GetRootReadme(),
283 }
284 }
285
286-func (g *GitHandler) List(w http.ResponseWriter, _ *http.Request) {
287+func (g *GitHandler) List(w http.ResponseWriter, _ *http.Request) error {
288 repos, err := g.gitService.ListRepositories()
289 if err != nil {
290- slog.Error("Error listing repo", "error", err)
291- return
292+ return err
293 }
294
295 f, err := os.Open(g.readmePath)
296 if err != nil {
297- slog.Error("Error loading readme file", "error", err)
298- return
299+ return err
300 }
301
302 bs, err := io.ReadAll(f)
303 if err != nil {
304- slog.Error("Error reading readme file bytes", "error", err)
305- return
306+ return err
307 }
308
309 extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
310@@ -84,15 +80,15 @@ Respositories: repos,
311 About: bs,
312 }
313 templates.WritePageTemplate(w, gitList)
314+ return nil
315 }
316
317-func (g *GitHandler) Summary(w http.ResponseWriter, r *http.Request) {
318+func (g *GitHandler) Summary(w http.ResponseWriter, r *http.Request) error {
319 ext.SetHTML(w)
320 name := r.PathValue("name")
321 ref, err := g.gitService.GetHead(name)
322 if err != nil {
323- slog.Error("Error loading head", "error", err)
324- return
325+ return err
326 }
327
328 gitList := &templates.GitItemPage{
329@@ -101,15 +97,15 @@ Ref: ref.Name().Short(),
330 GitItemBase: &templates.GitItemSummaryPage{},
331 }
332 templates.WritePageTemplate(w, gitList)
333+ return nil
334 }
335
336-func (g *GitHandler) About(w http.ResponseWriter, r *http.Request) {
337+func (g *GitHandler) About(w http.ResponseWriter, r *http.Request) error {
338 ext.SetHTML(w)
339 name := r.PathValue("name")
340 ref, err := g.gitService.GetHead(name)
341 if err != nil {
342- slog.Error("Error loading head", "error", err)
343- return
344+ return err
345 }
346 gitList := &templates.GitItemPage{
347 Name: name,
348@@ -117,28 +113,26 @@ Ref: ref.Name().Short(),
349 GitItemBase: &templates.GitItemAboutPage{},
350 }
351 templates.WritePageTemplate(w, gitList)
352+ return nil
353 }
354
355-func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) {
356+func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) error {
357 ext.SetHTML(w)
358 name := r.PathValue("name")
359
360 tags, err := g.gitService.ListTags(name)
361 if err != nil {
362- slog.Error("Error loading tags", "error", err)
363- return
364+ return err
365 }
366
367 branches, err := g.gitService.ListBranches(name)
368 if err != nil {
369- slog.Error("Error loading branches", "error", err)
370- return
371+ return err
372 }
373
374 ref, err := g.gitService.GetHead(name)
375 if err != nil {
376- slog.Error("Error loading head", "error", err)
377- return
378+ return err
379 }
380
381 gitList := &templates.GitItemPage{
382@@ -150,9 +144,10 @@ Branches: branches,
383 },
384 }
385 templates.WritePageTemplate(w, gitList)
386+ return nil
387 }
388
389-func (g *GitHandler) Tree(w http.ResponseWriter, r *http.Request) {
390+func (g *GitHandler) Tree(w http.ResponseWriter, r *http.Request) error {
391 ext.SetHTML(w)
392 name := r.PathValue("name")
393 ref := r.PathValue("ref")
394@@ -160,8 +155,7 @@ rest := r.PathValue("rest")
395
396 tree, err := g.gitService.GetTree(name, ref, rest)
397 if err != nil {
398- slog.Error("Error loading tree", "error", err)
399- return
400+ return err
401 }
402
403 gitList := &templates.GitItemPage{
404@@ -175,9 +169,10 @@ Name: name,
405 },
406 }
407 templates.WritePageTemplate(w, gitList)
408+ return nil
409 }
410
411-func (g *GitHandler) Blob(w http.ResponseWriter, r *http.Request) {
412+func (g *GitHandler) Blob(w http.ResponseWriter, r *http.Request) error {
413 ext.SetHTML(w)
414 name := r.PathValue("name")
415 ref := r.PathValue("ref")
416@@ -185,8 +180,7 @@ rest := r.PathValue("rest")
417
418 file, err := g.gitService.GetFileContent(name, ref, rest)
419 if err != nil {
420- slog.Error("Error loading blob", "error", err)
421- return
422+ return err
423 }
424
425 filename := filepath.Base(rest)
426@@ -197,15 +191,13 @@ html.WithLineNumbers(true),
427 )
428 iterator, err := lexer.Tokenise(nil, file)
429 if err != nil {
430- slog.Error("Error tokenise", "error", err)
431- return
432+ return err
433 }
434
435 var code bytes.Buffer
436 err = formatter.Format(&code, style, iterator)
437 if err != nil {
438- slog.Error("Error format", "error", err)
439- return
440+ return err
441 }
442
443 gitList := &templates.GitItemPage{
444@@ -217,17 +209,17 @@ Content: code.Bytes(),
445 },
446 }
447 templates.WritePageTemplate(w, gitList)
448+ return nil
449 }
450
451-func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) {
452+func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) error {
453 ext.SetHTML(w)
454 name := r.PathValue("name")
455 ref := r.PathValue("ref")
456
457 commits, err := g.gitService.ListCommits(name, ref)
458 if err != nil {
459- slog.Error("Error loading commits", "error", err)
460- return
461+ return err
462 }
463
464 gitList := &templates.GitItemPage{
465@@ -238,6 +230,7 @@ Commits: commits,
466 },
467 }
468 templates.WritePageTemplate(w, gitList)
469+ return nil
470 }
471
472 func GetLexers(filename string) chroma.Lexer {
473diff --git a/pkg/handler/router.go b/pkg/handler/router.go
474index bf13ad5f8821c8fa48e6c932afddacd8e2f964f6..3da812feb835f6d0e5ceed41bb688d45f34baae0 100644
475--- a/pkg/handler/router.go
476+++ b/pkg/handler/router.go
477@@ -20,9 +20,9 @@ gitService *service.GitService,
478 configRepo *serverconfig.ConfigurationRepository,
479 ) (http.Handler, error) {
480 var (
481- gitHandler = git.NewGitHandler(gitService, configRepo)
482- aboutHandler = about.NewAboutHandler(configRepo)
483- configHander = config.ConfigFile(configRepo)
484+ gitHandler = git.NewGitHandler(gitService, configRepo)
485+ aboutHandler = about.NewAboutHandler(configRepo)
486+ configHandler = config.ConfigFile(configRepo)
487 )
488
489 staticHandler, err := static.ServeStaticHandler()
490@@ -30,21 +30,19 @@ if err != nil {
491 return nil, err
492 }
493
494- mux := http.NewServeMux()
495-
496- mux.HandleFunc("/static/{file}", m(staticHandler))
497- mux.HandleFunc("/{name}/about/{$}", m(gitHandler.About))
498- mux.HandleFunc("/{name}", m(gitHandler.Summary))
499- mux.HandleFunc("/{name}/refs/{$}", m(gitHandler.Refs))
500- mux.HandleFunc("/{name}/tree/{ref}/{rest...}", m(gitHandler.Tree))
501- mux.HandleFunc("/{name}/blob/{ref}/{rest...}", m(gitHandler.Blob))
502- mux.HandleFunc("/{name}/log/{ref}", m(gitHandler.Log))
503- mux.HandleFunc("/config", m(configHander))
504- mux.HandleFunc("/about", m(aboutHandler.About))
505- mux.HandleFunc("/", m(gitHandler.List))
506- return mux, nil
507-}
508+ mux := ext.NewRouter()
509+ mux.AddMiddleware(ext.Compress)
510+ mux.AddMiddleware(ext.Log)
511
512-func m(next func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
513- return ext.Compress(next)
514+ mux.HandleFunc("/static/{file}", staticHandler)
515+ mux.HandleFunc("/{name}/about/{$}", gitHandler.About)
516+ mux.HandleFunc("/{name}", gitHandler.Summary)
517+ mux.HandleFunc("/{name}/refs/{$}", gitHandler.Refs)
518+ mux.HandleFunc("/{name}/tree/{ref}/{rest...}", gitHandler.Tree)
519+ mux.HandleFunc("/{name}/blob/{ref}/{rest...}", gitHandler.Blob)
520+ mux.HandleFunc("/{name}/log/{ref}", gitHandler.Log)
521+ mux.HandleFunc("/config", configHandler)
522+ mux.HandleFunc("/about", aboutHandler.About)
523+ mux.HandleFunc("/", gitHandler.List)
524+ return mux.Handler(), nil
525 }
526diff --git a/pkg/handler/static/handler.go b/pkg/handler/static/handler.go
527index 5155068306666b2303de7f129585108f32ea5dfa..0973d75ec8bf59c89111050112bb0f43368cb147 100644
528--- a/pkg/handler/static/handler.go
529+++ b/pkg/handler/static/handler.go
530@@ -10,19 +10,21 @@ "git.gabrielgio.me/cerrado/pkg/ext"
531 "git.gabrielgio.me/cerrado/static"
532 )
533
534-func ServeStaticHandler() (func(w http.ResponseWriter, r *http.Request), error) {
535+func ServeStaticHandler() (ext.ErrorRequestHandler, error) {
536 staticFs, err := fs.Sub(static.Static, ".")
537 if err != nil {
538 return nil, err
539 }
540
541- return func(w http.ResponseWriter, r *http.Request) {
542+ return func(w http.ResponseWriter, r *http.Request) error {
543 var (
544 f = r.PathValue("file")
545 e = filepath.Ext(f)
546 m = mime.TypeByExtension(e)
547 )
548 ext.SetMIME(w, m)
549+ w.Header().Add("Cache-Control", "immutable")
550 http.ServeFileFS(w, r, staticFs, f)
551+ return nil
552 }, nil
553 }
554diff --git a/pkg/service/git.go b/pkg/service/git.go
555index 31a1cbb47d7c74f552ce0ff097735481613a1aac..94e2adc5ab4433d9cc113f7a83d7c49aafd12787 100644
556--- a/pkg/service/git.go
557+++ b/pkg/service/git.go
558@@ -1,6 +1,7 @@
559 package service
560
561 import (
562+ "errors"
563 "log/slog"
564 "os"
565 "path"
566@@ -29,6 +30,10 @@ configurationRepository interface {
567 List() []*config.GitRepositoryConfiguration
568 GetByName(name string) *config.GitRepositoryConfiguration
569 }
570+)
571+
572+var (
573+ RepositoryNotFoundErr = errors.New("Repository not found")
574 )
575
576 // TODO: make it configurable
577@@ -84,8 +89,10 @@ return repos, nil
578 }
579
580 func (g *GitService) ListCommits(name, ref string) ([]*object.Commit, error) {
581- // TODO: handle nil
582 r := g.configRepo.GetByName(name)
583+ if r == nil {
584+ return nil, RepositoryNotFoundErr
585+ }
586
587 repo, err := git.OpenRepository(r.Path)
588 if err != nil {
589@@ -100,8 +107,10 @@ return repo.Commits()
590 }
591
592 func (g *GitService) GetTree(name, ref, path string) (*object.Tree, error) {
593- // TODO: handle nil
594 r := g.configRepo.GetByName(name)
595+ if r == nil {
596+ return nil, RepositoryNotFoundErr
597+ }
598
599 repo, err := git.OpenRepository(r.Path)
600 if err != nil {
601@@ -116,8 +125,10 @@ return repo.Tree(path)
602 }
603
604 func (g *GitService) GetFileContent(name, ref, path string) (string, error) {
605- // TODO: handle nil
606 r := g.configRepo.GetByName(name)
607+ if r == nil {
608+ return "", RepositoryNotFoundErr
609+ }
610
611 repo, err := git.OpenRepository(r.Path)
612 if err != nil {
613@@ -132,8 +143,10 @@ return repo.FileContent(path)
614 }
615
616 func (g *GitService) ListTags(name string) ([]*object.Tag, error) {
617- // TODO: handle nil
618 r := g.configRepo.GetByName(name)
619+ if r == nil {
620+ return nil, RepositoryNotFoundErr
621+ }
622
623 repo, err := git.OpenRepository(r.Path)
624 if err != nil {
625@@ -143,8 +156,10 @@ return repo.Tags()
626 }
627
628 func (g *GitService) ListBranches(name string) ([]*plumbing.Reference, error) {
629- // TODO: handle nil
630 r := g.configRepo.GetByName(name)
631+ if r == nil {
632+ return nil, RepositoryNotFoundErr
633+ }
634
635 repo, err := git.OpenRepository(r.Path)
636 if err != nil {
637@@ -154,8 +169,10 @@ return repo.Branches()
638 }
639
640 func (g *GitService) GetHead(name string) (*plumbing.Reference, error) {
641- // TODO: handle nil
642 r := g.configRepo.GetByName(name)
643+ if r == nil {
644+ return nil, RepositoryNotFoundErr
645+ }
646
647 repo, err := git.OpenRepository(r.Path)
648 if err != nil {
649diff --git a/templates/error.qtpl b/templates/error.qtpl
650new file mode 100644
651index 0000000000000000000000000000000000000000..771d5333f95ee509b2e1680de168003bf24b2b32
652--- /dev/null
653+++ b/templates/error.qtpl
654@@ -0,0 +1,16 @@
655+{% code
656+type ErrorPage struct {
657+ Message string
658+}
659+%}
660+
661+{% func (p *ErrorPage) Title() %}Error{% endfunc %}
662+
663+{% func (p *ErrorPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
664+
665+{% func (p *ErrorPage) Content() %}
666+{%s p.Message %}
667+{% endfunc %}
668+
669+{% func (p *ErrorPage) Script() %}
670+{% endfunc %}
671diff --git a/templates/error.qtpl.go b/templates/error.qtpl.go
672new file mode 100644
673index 0000000000000000000000000000000000000000..099395f076a3fea1744d060bf5d96617e3c3bc21
674--- /dev/null
675+++ b/templates/error.qtpl.go
676@@ -0,0 +1,162 @@
677+// Code generated by qtc from "error.qtpl". DO NOT EDIT.
678+// See https://github.com/valyala/quicktemplate for details.
679+
680+//line error.qtpl:1
681+package templates
682+
683+//line error.qtpl:1
684+import (
685+ qtio422016 "io"
686+
687+ qt422016 "github.com/valyala/quicktemplate"
688+)
689+
690+//line error.qtpl:1
691+var (
692+ _ = qtio422016.Copy
693+ _ = qt422016.AcquireByteBuffer
694+)
695+
696+//line error.qtpl:2
697+type ErrorPage struct {
698+ Message string
699+}
700+
701+//line error.qtpl:7
702+func (p *ErrorPage) StreamTitle(qw422016 *qt422016.Writer) {
703+//line error.qtpl:7
704+ qw422016.N().S(`Error`)
705+//line error.qtpl:7
706+}
707+
708+//line error.qtpl:7
709+func (p *ErrorPage) WriteTitle(qq422016 qtio422016.Writer) {
710+//line error.qtpl:7
711+ qw422016 := qt422016.AcquireWriter(qq422016)
712+//line error.qtpl:7
713+ p.StreamTitle(qw422016)
714+//line error.qtpl:7
715+ qt422016.ReleaseWriter(qw422016)
716+//line error.qtpl:7
717+}
718+
719+//line error.qtpl:7
720+func (p *ErrorPage) Title() string {
721+//line error.qtpl:7
722+ qb422016 := qt422016.AcquireByteBuffer()
723+//line error.qtpl:7
724+ p.WriteTitle(qb422016)
725+//line error.qtpl:7
726+ qs422016 := string(qb422016.B)
727+//line error.qtpl:7
728+ qt422016.ReleaseByteBuffer(qb422016)
729+//line error.qtpl:7
730+ return qs422016
731+//line error.qtpl:7
732+}
733+
734+//line error.qtpl:9
735+func (p *ErrorPage) StreamNavbar(qw422016 *qt422016.Writer) {
736+//line error.qtpl:9
737+ StreamNavbar(qw422016, Git)
738+//line error.qtpl:9
739+}
740+
741+//line error.qtpl:9
742+func (p *ErrorPage) WriteNavbar(qq422016 qtio422016.Writer) {
743+//line error.qtpl:9
744+ qw422016 := qt422016.AcquireWriter(qq422016)
745+//line error.qtpl:9
746+ p.StreamNavbar(qw422016)
747+//line error.qtpl:9
748+ qt422016.ReleaseWriter(qw422016)
749+//line error.qtpl:9
750+}
751+
752+//line error.qtpl:9
753+func (p *ErrorPage) Navbar() string {
754+//line error.qtpl:9
755+ qb422016 := qt422016.AcquireByteBuffer()
756+//line error.qtpl:9
757+ p.WriteNavbar(qb422016)
758+//line error.qtpl:9
759+ qs422016 := string(qb422016.B)
760+//line error.qtpl:9
761+ qt422016.ReleaseByteBuffer(qb422016)
762+//line error.qtpl:9
763+ return qs422016
764+//line error.qtpl:9
765+}
766+
767+//line error.qtpl:11
768+func (p *ErrorPage) StreamContent(qw422016 *qt422016.Writer) {
769+//line error.qtpl:11
770+ qw422016.N().S(`
771+`)
772+//line error.qtpl:12
773+ qw422016.E().S(p.Message)
774+//line error.qtpl:12
775+ qw422016.N().S(`
776+`)
777+//line error.qtpl:13
778+}
779+
780+//line error.qtpl:13
781+func (p *ErrorPage) WriteContent(qq422016 qtio422016.Writer) {
782+//line error.qtpl:13
783+ qw422016 := qt422016.AcquireWriter(qq422016)
784+//line error.qtpl:13
785+ p.StreamContent(qw422016)
786+//line error.qtpl:13
787+ qt422016.ReleaseWriter(qw422016)
788+//line error.qtpl:13
789+}
790+
791+//line error.qtpl:13
792+func (p *ErrorPage) Content() string {
793+//line error.qtpl:13
794+ qb422016 := qt422016.AcquireByteBuffer()
795+//line error.qtpl:13
796+ p.WriteContent(qb422016)
797+//line error.qtpl:13
798+ qs422016 := string(qb422016.B)
799+//line error.qtpl:13
800+ qt422016.ReleaseByteBuffer(qb422016)
801+//line error.qtpl:13
802+ return qs422016
803+//line error.qtpl:13
804+}
805+
806+//line error.qtpl:15
807+func (p *ErrorPage) StreamScript(qw422016 *qt422016.Writer) {
808+//line error.qtpl:15
809+ qw422016.N().S(`
810+`)
811+//line error.qtpl:16
812+}
813+
814+//line error.qtpl:16
815+func (p *ErrorPage) WriteScript(qq422016 qtio422016.Writer) {
816+//line error.qtpl:16
817+ qw422016 := qt422016.AcquireWriter(qq422016)
818+//line error.qtpl:16
819+ p.StreamScript(qw422016)
820+//line error.qtpl:16
821+ qt422016.ReleaseWriter(qw422016)
822+//line error.qtpl:16
823+}
824+
825+//line error.qtpl:16
826+func (p *ErrorPage) Script() string {
827+//line error.qtpl:16
828+ qb422016 := qt422016.AcquireByteBuffer()
829+//line error.qtpl:16
830+ p.WriteScript(qb422016)
831+//line error.qtpl:16
832+ qs422016 := string(qb422016.B)
833+//line error.qtpl:16
834+ qt422016.ReleaseByteBuffer(qb422016)
835+//line error.qtpl:16
836+ return qs422016
837+//line error.qtpl:16
838+}
839diff --git a/templates/gititem.qtpl b/templates/gititem.qtpl
840index 3e2dd4e543265ca86fbe8832a7001b392edb0b7b..d6957820865ed335415da36d5fc0d240039d0350 100644
841--- a/templates/gititem.qtpl
842+++ b/templates/gititem.qtpl
843@@ -13,7 +13,7 @@ GitItemBase
844 }
845 %}
846
847-{% func (p *GitItemPage) Title() %}Git | List{% endfunc %}
848+{% func (p *GitItemPage) Title() %}Git | {%s p.Name %}{% endfunc %}
849
850 {% func (p *GitItemPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
851
852diff --git a/templates/gititem.qtpl.go b/templates/gititem.qtpl.go
853index 2c4610465d702fd2ceab108977a1dff00576ab68..a7ed65941e2355817c95d8429afe3a34d0a91fe9 100644
854--- a/templates/gititem.qtpl.go
855+++ b/templates/gititem.qtpl.go
856@@ -44,7 +44,9 @@
857 //line gititem.qtpl:16
858 func (p *GitItemPage) StreamTitle(qw422016 *qt422016.Writer) {
859 //line gititem.qtpl:16
860- qw422016.N().S(`Git | List`)
861+ qw422016.N().S(`Git | `)
862+//line gititem.qtpl:16
863+ qw422016.E().S(p.Name)
864 //line gititem.qtpl:16
865 }
866