routes, templates: tree and log views
This commit is contained in:
parent
e0f34796a3
commit
ce71721c6d
6 changed files with 110 additions and 37 deletions
|
@ -11,5 +11,6 @@ func Handlers(c *config.Config) *flow.Mux {
|
||||||
mux.HandleFunc("/:name", d.RepoIndex, "GET")
|
mux.HandleFunc("/:name", d.RepoIndex, "GET")
|
||||||
mux.HandleFunc("/:name/tree/:ref/...", d.RepoTree, "GET")
|
mux.HandleFunc("/:name/tree/:ref/...", d.RepoTree, "GET")
|
||||||
mux.HandleFunc("/:name/blob/:ref/...", d.FileContent, "GET")
|
mux.HandleFunc("/:name/blob/:ref/...", d.FileContent, "GET")
|
||||||
|
mux.HandleFunc("/:name/log/:ref", d.Log, "GET")
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/alexedwards/flow"
|
"github.com/alexedwards/flow"
|
||||||
gogit "github.com/go-git/go-git/v5"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
|
||||||
"icyphox.sh/legit/config"
|
"icyphox.sh/legit/config"
|
||||||
"icyphox.sh/legit/git"
|
"icyphox.sh/legit/git"
|
||||||
)
|
)
|
||||||
|
@ -21,27 +20,25 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) {
|
||||||
name = filepath.Clean(name)
|
name = filepath.Clean(name)
|
||||||
// TODO: remove .git
|
// TODO: remove .git
|
||||||
path := filepath.Join(d.c.Git.ScanPath, name+".git")
|
path := filepath.Join(d.c.Git.ScanPath, name+".git")
|
||||||
repo, err := gogit.PlainOpen(path)
|
gr, err := git.Open(path, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Write404(w, *d.c)
|
Write404(w, *d.c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
head, err := repo.Head()
|
files, err := gr.FileTree("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Write500(w, *d.c)
|
Write500(w, *d.c)
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := git.FilesAtRef(repo, head.Hash(), "")
|
data := make(map[string]any)
|
||||||
if err != nil {
|
data["name"] = name
|
||||||
Write500(w, *d.c)
|
// TODO: make this configurable
|
||||||
log.Println(err)
|
data["ref"] = "master"
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
d.listFiles(files, w)
|
d.listFiles(files, data, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,27 +50,25 @@ func (d *deps) RepoTree(w http.ResponseWriter, r *http.Request) {
|
||||||
name = filepath.Clean(name)
|
name = filepath.Clean(name)
|
||||||
// TODO: remove .git
|
// TODO: remove .git
|
||||||
path := filepath.Join(d.c.Git.ScanPath, name+".git")
|
path := filepath.Join(d.c.Git.ScanPath, name+".git")
|
||||||
repo, err := gogit.PlainOpen(path)
|
gr, err := git.Open(path, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Write404(w, *d.c)
|
Write404(w, *d.c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, err := repo.ResolveRevision(plumbing.Revision(ref))
|
files, err := gr.FileTree(treePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Write500(w, *d.c)
|
Write500(w, *d.c)
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := git.FilesAtRef(repo, *hash, treePath)
|
data := make(map[string]any)
|
||||||
if err != nil {
|
data["name"] = name
|
||||||
Write500(w, *d.c)
|
data["ref"] = ref
|
||||||
log.Println(err)
|
data["parent"] = treePath
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
d.listFiles(files, w)
|
d.listFiles(files, data, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,20 +80,50 @@ func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) {
|
||||||
name = filepath.Clean(name)
|
name = filepath.Clean(name)
|
||||||
// TODO: remove .git
|
// TODO: remove .git
|
||||||
path := filepath.Join(d.c.Git.ScanPath, name+".git")
|
path := filepath.Join(d.c.Git.ScanPath, name+".git")
|
||||||
repo, err := gogit.PlainOpen(path)
|
gr, err := git.Open(path, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Write404(w, *d.c)
|
Write404(w, *d.c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, err := repo.ResolveRevision(plumbing.Revision(ref))
|
contents, err := gr.FileContent(treePath)
|
||||||
|
data := make(map[string]any)
|
||||||
|
data["name"] = name
|
||||||
|
data["ref"] = ref
|
||||||
|
|
||||||
|
d.showFile(contents, data, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *deps) Log(w http.ResponseWriter, r *http.Request) {
|
||||||
|
name := flow.Param(r.Context(), "name")
|
||||||
|
ref := flow.Param(r.Context(), "ref")
|
||||||
|
|
||||||
|
path := filepath.Join(d.c.Git.ScanPath, name+".git")
|
||||||
|
gr, err := git.Open(path, ref)
|
||||||
|
if err != nil {
|
||||||
|
Write404(w, *d.c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
commits, err := gr.Commits()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Write500(w, *d.c)
|
Write500(w, *d.c)
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
contents, err := git.FileContentAtRef(repo, *hash, treePath)
|
tpath := filepath.Join(d.c.Template.Dir, "*")
|
||||||
d.showFile(contents, w)
|
t := template.Must(template.ParseGlob(tpath))
|
||||||
return
|
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["commits"] = commits
|
||||||
|
data["meta"] = d.c.Meta
|
||||||
|
data["name"] = name
|
||||||
|
data["ref"] = ref
|
||||||
|
|
||||||
|
if err := t.ExecuteTemplate(w, "log", data); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,31 +24,29 @@ func Write500(w http.ResponseWriter, c config.Config) {
|
||||||
t.Execute(w, nil)
|
t.Execute(w, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deps) listFiles(files []git.NiceTree, w http.ResponseWriter) {
|
func (d *deps) listFiles(files []git.NiceTree, data map[string]any, w http.ResponseWriter) {
|
||||||
tpath := filepath.Join(d.c.Template.Dir, "*")
|
tpath := filepath.Join(d.c.Template.Dir, "*")
|
||||||
t := template.Must(template.ParseGlob(tpath))
|
t := template.Must(template.ParseGlob(tpath))
|
||||||
|
|
||||||
data := make(map[string]interface{})
|
|
||||||
data["files"] = files
|
data["files"] = files
|
||||||
data["meta"] = d.c.Meta
|
data["meta"] = d.c.Meta
|
||||||
|
|
||||||
if err := t.ExecuteTemplate(w, "repo", data); err != nil {
|
if err := t.ExecuteTemplate(w, "repo", data); err != nil {
|
||||||
Write500(w, *d.c)
|
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deps) showFile(content string, w http.ResponseWriter) {
|
func (d *deps) showFile(content string, data map[string]any, w http.ResponseWriter) {
|
||||||
tpath := filepath.Join(d.c.Template.Dir, "*")
|
tpath := filepath.Join(d.c.Template.Dir, "*")
|
||||||
t := template.Must(template.ParseGlob(tpath))
|
t := template.Must(template.ParseGlob(tpath))
|
||||||
|
|
||||||
data := make(map[string]interface{})
|
// TODO: Process content here.
|
||||||
|
|
||||||
data["content"] = content
|
data["content"] = content
|
||||||
data["meta"] = d.c.Meta
|
data["meta"] = d.c.Meta
|
||||||
|
|
||||||
if err := t.ExecuteTemplate(w, "file", data); err != nil {
|
if err := t.ExecuteTemplate(w, "file", data); err != nil {
|
||||||
Write500(w, *d.c)
|
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
{{ template "nav" . }}
|
{{ template "nav" . }}
|
||||||
<main>
|
<main>
|
||||||
<pre>
|
<pre>
|
||||||
{{ .content }}
|
{{ .content }}
|
||||||
</pre>
|
</pre>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
|
21
templates/log.html
Normal file
21
templates/log.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{{ define "log" }}
|
||||||
|
<html>
|
||||||
|
{{ template "head" . }}
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<h1>{{ .meta.Title }}</h1>
|
||||||
|
<h2>{{ .meta.Description }}</h2>
|
||||||
|
</header>
|
||||||
|
<body>
|
||||||
|
{{ template "nav" . }}
|
||||||
|
<main>
|
||||||
|
{{ $repo := .name }}
|
||||||
|
{{ range .commits }}
|
||||||
|
<p><a href="/{{ $repo }}/commit/{{ .Hash.String }}">{{ slice .Hash.String 0 8 }}<a>
|
||||||
|
— {{ .Author.Name }}</p>
|
||||||
|
<p><pre>{{ .Message }}</pre></p>
|
||||||
|
{{ end }}
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{ end }}
|
|
@ -9,13 +9,41 @@
|
||||||
<body>
|
<body>
|
||||||
{{ template "nav" . }}
|
{{ template "nav" . }}
|
||||||
<main>
|
<main>
|
||||||
|
{{ $repo := .name }}
|
||||||
|
{{ $ref := .ref }}
|
||||||
|
{{ $parent := .parent }}
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><a href="../">..</a>
|
||||||
|
</tr>
|
||||||
{{ range .files }}
|
{{ range .files }}
|
||||||
{{ if .IsFile }}
|
{{ if .IsFile }}
|
||||||
<p>{{ .Mode }} {{ .Name }} {{ .Size }} </p>
|
<tr>
|
||||||
{{ else }}
|
<td><code>{{ .Mode }}</code></td>
|
||||||
<p>d-------- {{ .Name}}/</p>
|
<td>
|
||||||
{{ end }}
|
{{ if $parent }}
|
||||||
|
<a href="/{{ $repo }}/blob/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="/{{ $repo }}/blob/{{ $ref }}/{{ .Name }}">{{ .Name }}</a>
|
||||||
|
{{ end }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ else }}
|
||||||
|
<tr>
|
||||||
|
<td><code>{{ .Mode }}</code></td>
|
||||||
|
<td>
|
||||||
|
{{ if $parent }}
|
||||||
|
<a href="/{{ $repo }}/tree/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}/</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $repo }}/tree/{{ $ref }}/{{ .Name }}">{{ .Name }}/</a>
|
||||||
|
{{ end }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
</table>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue