summaryrefslogtreecommitdiff
path: root/gopher.go
diff options
context:
space:
mode:
Diffstat (limited to 'gopher.go')
-rw-r--r--gopher.go129
1 files changed, 129 insertions, 0 deletions
diff --git a/gopher.go b/gopher.go
new file mode 100644
index 0000000..c725d68
--- /dev/null
+++ b/gopher.go
@@ -0,0 +1,129 @@
+package syw
+
+import (
+ "bytes"
+ "context"
+ "mime"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "text/template"
+
+ "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/gopher"
+)
+
+func GopherRouter(repodir string, overrides *template.Template) *sliderule.Router {
+ tmpl, err := addTemplates(gopherTemplate, overrides)
+ if err != nil {
+ panic(err)
+ }
+
+ repoRouter := &sliderule.Router{}
+ repoRouter.Use(assignRepo(repodir))
+ repoRouter.Route("/branches", runGopherTemplate(tmpl, "branch_list.gophermap", gopher.MenuType))
+ repoRouter.Route("/tags", runGopherTemplate(tmpl, "tag_list.gophermap", gopher.MenuType))
+ repoRouter.Route("/refs/:ref", runGopherTemplate(tmpl, "ref.gophermap", gopher.MenuType))
+ repoRouter.Route("/refs/:ref/tree", gopherTreePath(tmpl, false))
+ repoRouter.Route("/refs/:ref/tree/*path", gopherTreePath(tmpl, true))
+ repoRouter.Route("/diffstat/:fromref/:toref", runGopherTemplate(tmpl, "diffstat.gophertext", gopher.TextFileType))
+ repoRouter.Route("/diff/:fromref/:toref", runGopherTemplate(tmpl, "diff.gophertext", gopher.TextFileType))
+
+ router := &sliderule.Router{}
+ router.Route("/", gopherRoot(repodir, tmpl))
+ router.Route("/:"+reponamekey, assignRepo(repodir)(runGopherTemplate(tmpl, "repo_home.gophermap", gopher.MenuType)))
+ router.Mount("/:"+reponamekey, repoRouter)
+
+ return router
+}
+
+func gopherRoot(repodir string, tmpl *template.Template) sliderule.Handler {
+ return sliderule.HandlerFunc(func(ctx context.Context, request *sliderule.Request) *sliderule.Response {
+ entries, err := os.ReadDir(repodir)
+ if err != nil {
+ return gopher.Error(err).Response()
+ }
+
+ names := []string{}
+ for _, item := range entries {
+ if Open(filepath.Join(repodir, item.Name())) != nil {
+ names = append(names, item.Name())
+ }
+ }
+
+ buf := &bytes.Buffer{}
+ obj := map[string]any{
+ "Repos": names,
+ "Host": request.Hostname(),
+ "Port": request.Port(),
+ "Selector": request.Path,
+ }
+ if err := tmpl.ExecuteTemplate(buf, "repo_root.gophermap", obj); err != nil {
+ return gopher.Error(err).Response()
+ }
+
+ return gopher.File(gopher.MenuType, buf)
+ })
+}
+
+func gopherTreePath(tmpl *template.Template, haspath bool) sliderule.Handler {
+ return sliderule.HandlerFunc(func(ctx context.Context, request *sliderule.Request) *sliderule.Response {
+ repo := ctx.Value(repokey).(*Repository)
+ params := sliderule.RouteParams(ctx)
+
+ t := "tree"
+ if haspath {
+ var err error
+ t, err = repo.Type(ctx, params["ref"] + ":" + params["path"])
+ if err != nil {
+ return gopher.Error(err).Response()
+ }
+ }
+
+ if t != "blob" {
+ if !haspath {
+ params["path"] = ""
+ }
+ return runGopherTemplate(tmpl, "tree.gophermap", gopher.MenuType).Handle(ctx, request)
+ }
+
+ body, err := repo.Blob(ctx, params["ref"], params["path"])
+ if err != nil {
+ return gopher.Error(err).Response()
+ }
+
+ filetype := gopher.MenuType
+ ext := path.Ext(params["path"])
+ if ext != ".gophermap" && params["path"] != "gophermap" {
+ mtype := mime.TypeByExtension(ext)
+ if strings.HasPrefix(mtype, "text/") {
+ filetype = gopher.TextFileType
+ } else {
+ filetype = gopher.BinaryFileType
+ }
+ }
+
+ return gopher.File(filetype, bytes.NewBuffer(body))
+ })
+}
+
+func runGopherTemplate(tmpl *template.Template, name string, filetype sliderule.Status) sliderule.Handler {
+ return sliderule.HandlerFunc(func(ctx context.Context, request *sliderule.Request) *sliderule.Response {
+ obj := map[string]any{
+ "Ctx": ctx,
+ "Repo": ctx.Value(repokey),
+ "Params": sliderule.RouteParams(ctx),
+ "Host": request.Hostname(),
+ "Port": request.Port(),
+ "Selector": request.Path,
+ }
+ buf := &bytes.Buffer{}
+
+ if err := tmpl.ExecuteTemplate(buf, name, obj); err != nil {
+ return gopher.Error(err).Response()
+ }
+
+ return gopher.File(filetype, buf)
+ })
+}