summaryrefslogtreecommitdiff
path: root/nex.go
blob: eab3def16610bf061646b8bbd5dd9928df3f7b4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package syw

import (
	"context"
	"text/template"

	"tildegit.org/tjp/sliderule"
	"tildegit.org/tjp/sliderule/nex"
)

// NexRouter builds a router that will handle requests into a directory of git repositories.
//
// The routes it defines are:
//
//	/                                     listing of the repositories in the directory
//	/:repository/                         overview of the repository
//	/:repository/branches/                list of branches/heads
//	/:repository/tags/                    listing of tags
//	/:repository/refs/:ref/               overview of a ref
//	/:repository/refs/:ref/tree/*path     listing of directories, raw files
//	/:repository/diffstat/:fromref/:toref diffstat between two refs
//	/:repository/diff/:fromref/:toref     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.nex.txt    at /
//	repo_home.nex.txt    at /:repository/
//	branch_list.nex.txt  at /:repository/branches
//	tag_list.nex.txt     at /:repository/tags
//	ref.nex.txt          at /:repository/refs/:ref/
//	tree.nex.txt         for directories requested under /:repository/refs/:ref/tree/*path
//	                     (file paths return the raw files without any template involved)
//	diffstat.nex.txt     the plaintext diffstat at /:repository/diffstat/:fromref/:toref
//	diff.nex.txt         the plaintext 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.nex.txt, which is rendered with an object containing a single name
// "Repos", a slice of the string repository names.
func NexRouter(repodir string, overrides *template.Template) *sliderule.Router {
	tmpl, err := addTemplates(nexTemplate, overrides)
	if err != nil {
		panic(err)
	}

	repoRouter := &sliderule.Router{}
	repoRouter.Use(assignRepo(repodir))
	repoRouter.Route("/", repoRouteHandler(nexProto, tmpl, "repo_home.nex.txt"))
	repoRouter.Route("/branches/", repoRouteHandler(nexProto, tmpl, "branch_list.nex.txt"))
	repoRouter.Route("/tags/", repoRouteHandler(nexProto, tmpl, "tag_list.nex.txt"))
	repoRouter.Route("/refs/:ref/", repoRouteHandler(nexProto, tmpl, "ref.nex.txt"))
	repoRouter.Route("/refs/:ref/tree/*path", treePathHandler(nexProto, tmpl, "tree.nex.txt"))
	repoRouter.Route("/diffstat/:fromref/:toref", repoRouteHandler(nexProto, tmpl, "diffstat.nex.txt"))
	repoRouter.Route("/diff/:fromref/:toref", repoRouteHandler(nexProto, tmpl, "diff.nex.txt"))

	router := &sliderule.Router{}
	router.Route("/", rootDirHandler(nexProto, repodir, tmpl, "repo_root.nex.txt"))
	router.Mount("/:"+reponamekey, repoRouter)

	return router
}

type nexProtocol struct{ sliderule.ServerProtocol }

func (nexProtocol) TemplateBaseData(_ context.Context, _ *sliderule.Request) map[string]any {
	return map[string]any{}
}

func (nexProtocol) 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 nexProto = nexProtocol{nex.ServerProtocol}