support for nex protocol

This commit is contained in:
tjp 2023-11-14 21:53:09 -07:00
parent 8c6db5a684
commit 77725e02cc
12 changed files with 203 additions and 3 deletions

2
go.mod
View File

@ -2,7 +2,7 @@ module tildegit.org/tjp/syw
go 1.21.0
require tildegit.org/tjp/sliderule v1.6.0
require tildegit.org/tjp/sliderule v1.6.1
require (
github.com/go-kit/log v0.2.1 // indirect

4
go.sum
View File

@ -10,5 +10,5 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
tildegit.org/tjp/sliderule v1.6.0 h1:/dROwqvbwUOf7qem88/m83og0Tr5PczvuAUzGj5JCVw=
tildegit.org/tjp/sliderule v1.6.0/go.mod h1:opdo8E25iS9X9pNismM8U7pCH8XO0PdRIIhdADn8Uik=
tildegit.org/tjp/sliderule v1.6.1 h1:/w0fiD17wS5NnNmpxWdLu9hOX8/CmhjMV1vMwMBMuao=
tildegit.org/tjp/sliderule v1.6.1/go.mod h1:opdo8E25iS9X9pNismM8U7pCH8XO0PdRIIhdADn8Uik=

83
nex.go Normal file
View File

@ -0,0 +1,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}

View File

@ -17,6 +17,15 @@ var (
))
)
var (
//go:embed templates/*.nex.txt
nexTemplateFS embed.FS
nexTemplate = template.Must(template.ParseFS(
nexTemplateFS,
"templates/*.nex.txt",
))
)
var (
//go:embed templates/*.gph templates/*.gph.txt
gopherTemplateFS embed.FS

View File

@ -0,0 +1,8 @@
{{.Repo.Name}} Branches ⌥
{{range .Repo.NameBytes}}-{{end}}-----------
{{ range .Repo.Refs .Ctx -}}
{{ if .IsBranch -}}
=> ../refs/{{.Hash}}/ {{.ShortName}}
{{ end -}}
{{ end -}}

1
templates/diff.nex.txt Normal file
View File

@ -0,0 +1 @@
{{.Repo.Diff .Ctx .Params.fromref .Params.toref}}

View File

@ -0,0 +1 @@
{{.Repo.Diffstat .Ctx .Params.fromref .Params.toref}}

48
templates/ref.nex.txt Normal file
View File

@ -0,0 +1,48 @@
{{ with .Repo.Commit .Ctx .Params.ref -}}
{{.Repo.Name}} {{slice .Hash 0 8}}
{{ range .Repo.NameBytes }}-{{end}}---------
{{.ShortMessage}}
{{ with .RestOfMessage -}}
{{ if ne . "" -}}
{{.}}
{{ end -}}
{{ end -}}
=> ../../ 🗂️ Repository
=> ./tree/ 📄 Files
{{ if ne .Parents nil -}}
=> ../../diff/{{.Hash}}^/{{.Hash}} 🔩 Full Diff
{{ else -}}
=> ../../diff/4b825dc642cb6eb9a060e54bf8d69288fbee4904/{{.Hash}} 🔩 Full Diff
{{ end -}}
{{ range .Parents -}}
=> ../{{.}}/ 👤 Parent {{slice . 0 8}}
{{ end -}}
{{ range .Repo.Refs $.Ctx -}}
{{ if .IsTag -}}
{{ if eq $.Params.ref .Hash -}}
=> ../{{.Hash}}/ 🏷️ {{.ShortName}}
{{ end -}}
{{ end -}}
{{ end }}
Authored
--------
{{.AuthorName}}<{{.AuthorEmail}}>
{{.AuthorDate.Format "Mon Jan _2 15:04:05 MST 2006"}}
Committed
---------
{{.CommitterName}}<{{.CommitterEmail}}>
{{.CommitDate.Format "Mon Jan _2 15:04:05 MST 2006"}}
{{ if eq .Parents nil -}}
{{$.Repo.Diffstat $.Ctx "4b825dc642cb6eb9a060e54bf8d69288fbee4904" $.Params.ref}}
{{ else -}}
{{ with index .Parents 0 -}}
{{$.Repo.Diffstat $.Ctx . $.Params.ref}}
{{ end -}}
{{ end -}}
{{ end -}}

View File

@ -0,0 +1,28 @@
{{.Repo.Name}}
{{ range .Repo.NameBytes }}={{end}}
{{.Repo.Description}}
=> ./branches/ ⌥ Branches
=> ./tags/ 🏷Tags
=> ./refs/HEAD/tree/ 📄 Files
Latest Commits
--------------
{{ with .Repo.Commits .Ctx "HEAD" 5 -}}
{{ range . -}}
=> ./refs/{{.Hash}}/ {{.ShortMessage}}
{{ end -}}
{{ if len . | eq 0 -}}
(no commits to show)
{{ end -}}
{{ end }}
{{ with .Repo.Readme .Ctx "HEAD" -}}
{{ if len .RawContents | ne 0 -}}
== {{.Filename}} ==
{{.RawContents}}
{{ end -}}
{{ end }}

View File

@ -0,0 +1,6 @@
Repositories
============
{{ range .Repos -}}
=> ./{{.}}/
{{ end }}

View File

@ -0,0 +1,8 @@
{{.Repo.Name}} Tags 🏷️
{{range .Repo.NameBytes}}-{{end}}-------
{{ range .Repo.Refs .Ctx -}}
{{ if .IsTag -}}
=> ../refs/{{.Hash}}/ {{.ShortName}}
{{ end -}}
{{ end -}}

8
templates/tree.nex.txt Normal file
View File

@ -0,0 +1,8 @@
{{ with .Repo.Commit .Ctx .Params.ref -}}
{{slice .Hash 0 8}}:{{ if ne $.Params.path "" }}{{$.Params.path}}{{ else }}/{{ end }}
{{ end -}}
=> ../ {{ if ne .Params.path "" }}../{{ else }}Commit{{ end }}
{{ range .Repo.Tree .Ctx .Params.ref .Params.path -}}
=> ./{{.Path}}{{if eq .Type "tree"}}/{{end}} {{if eq .Type "blob"}}📄{{else if eq .Type "tree"}}📂{{end}} {{.Path}}
{{ end -}}