84 lines
3.5 KiB
Go
84 lines
3.5 KiB
Go
package syw
|
|
|
|
import (
|
|
"context"
|
|
"text/template"
|
|
|
|
"tildegit.org/tjp/sliderule"
|
|
"tildegit.org/tjp/sliderule/spartan"
|
|
)
|
|
|
|
// SpartanRouter builds a router that will handle requests into a directory of git repositories.
|
|
//
|
|
// The routes it defines are:
|
|
//
|
|
// / gemtext listing of the repositories in the directory
|
|
// /:repository/ gemtext overview of the repository
|
|
// /:repository/branches gemtext list of branches/heads
|
|
// /:repository/tags gemtext listing of tags
|
|
// /:repository/refs/:ref/ gemtext overview of a ref
|
|
// /:repository/refs/:ref/tree/*path gemtext listing of directories, raw files
|
|
// /:repository/diffstat/:fromref/:toref text/plain diffstat between two refs
|
|
// /:repository/diff/:fromref/:toref text/x-diff between two refs
|
|
//
|
|
// The overrides argument can provide templates to define the behavior of nearly all of the above
|
|
// routes. All of them have default implementations so the argument can even be nil, but otherwise
|
|
// the template names used are:
|
|
//
|
|
// repo_root.gmi gemtext at /
|
|
// repo_home.gmi gemtext at /:repository/
|
|
// branch_list.gmi gemtext at /:repository/branches
|
|
// tag_list.gmi gemtext at /:repository/tags
|
|
// ref.gmi gemtext at /:repository/refs/:ref/
|
|
// tree.gmi gemtext for directories requested under /:repository/refs/:ref/tree/*path
|
|
// (file paths return the raw files without any template involved)
|
|
// diffstat.gmi.txt the plaintext diffstat at /:repository/diffstat/:fromref/:toref
|
|
// diff.gmi.txt the text/x-diff at /:repository/diff/:fromref/:toref
|
|
//
|
|
// Most of the templates above are rendered with an object with 3 fields:
|
|
//
|
|
// Ctx: the context.Context from the request
|
|
// Repo: a *syw.Repository object corresponding to <repodir>/:repository
|
|
// Params: a map[string]string of the route parameters
|
|
//
|
|
// The only exception is repo_root.gmi, which is rendered with an object containing a single name
|
|
// "Repos", a slice of the string repository names.
|
|
func SpartanRouter(repodir string, overrides *template.Template) *sliderule.Router {
|
|
tmpl, err := addTemplates(geminiTemplate, overrides)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
repoRouter := &sliderule.Router{}
|
|
repoRouter.Use(assignRepo(repodir))
|
|
repoRouter.Route("/", repoRouteHandler(spartanProto, tmpl, "repo_home.gmi"))
|
|
repoRouter.Route("/branches", repoRouteHandler(spartanProto, tmpl, "branch_list.gmi"))
|
|
repoRouter.Route("/tags", repoRouteHandler(spartanProto, tmpl, "tag_list.gmi"))
|
|
repoRouter.Route("/refs/:ref/", repoRouteHandler(spartanProto, tmpl, "ref.gmi"))
|
|
repoRouter.Route("/refs/:ref/tree/*path", treePathHandler(spartanProto, tmpl, "tree.gmi"))
|
|
repoRouter.Route("/diffstat/:fromref/:toref", repoRouteHandler(spartanProto, tmpl, "diffstat.gmi.txt"))
|
|
repoRouter.Route("/diff/:fromref/:toref", repoRouteHandler(spartanProto, tmpl, "diff.gmi.txt"))
|
|
|
|
router := &sliderule.Router{}
|
|
router.Route("/", rootDirHandler(spartanProto, repodir, tmpl, "repo_root.gmi"))
|
|
router.Mount("/:"+reponamekey, repoRouter)
|
|
|
|
return router
|
|
}
|
|
|
|
type spartanProtocol struct{ sliderule.ServerProtocol }
|
|
|
|
func (spartanProtocol) TemplateBaseData(_ context.Context, _ *sliderule.Request) map[string]any {
|
|
return map[string]any{}
|
|
}
|
|
|
|
func (spartanProtocol) TemplateRepoData(ctx context.Context, request *sliderule.Request) map[string]any {
|
|
return map[string]any{
|
|
"Ctx": ctx,
|
|
"Repo": ctx.Value(repokey),
|
|
"Params": sliderule.RouteParams(ctx),
|
|
}
|
|
}
|
|
|
|
var spartanProto = spartanProtocol{spartan.ServerProtocol}
|