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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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)
})
}
|