all repos — elgit @ ce71721c6dc80db8af63f2098a1548308e2621b2

fork of legit: web frontend for git, written in go

routes, templates: tree and log views
Anirudh Oppiliappan x@icyphox.sh
Sun, 11 Dec 2022 21:17:04 +0530
commit

ce71721c6dc80db8af63f2098a1548308e2621b2

parent

e0f34796a37666058dce61277bc546add707fb2e

M routes/handler.goroutes/handler.go
@@ -11,5 +11,6 @@ d := deps{c} 	mux.HandleFunc("/:name", d.RepoIndex, "GET")
 	mux.HandleFunc("/:name/tree/:ref/...", d.RepoTree, "GET")
 	mux.HandleFunc("/:name/blob/:ref/...", d.FileContent, "GET")
+	mux.HandleFunc("/:name/log/:ref", d.Log, "GET")
 	return mux
 }
M routes/routes.goroutes/routes.go
@@ -1,13 +1,12 @@ package routes
 
 import (
+	"html/template"
 	"log"
 	"net/http"
 	"path/filepath"
 
 	"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/git"
 )
@@ -21,27 +20,25 @@ name := flow.Param(r.Context(), "name") 	name = filepath.Clean(name)
 	// TODO: remove .git
 	path := filepath.Join(d.c.Git.ScanPath, name+".git")
-	repo, err := gogit.PlainOpen(path)
+	gr, err := git.Open(path, "")
 	if err != nil {
 		Write404(w, *d.c)
 		return
 	}
 
-	head, err := repo.Head()
+	files, err := gr.FileTree("")
 	if err != nil {
 		Write500(w, *d.c)
 		log.Println(err)
 		return
 	}
 
-	files, err := git.FilesAtRef(repo, head.Hash(), "")
-	if err != nil {
-		Write500(w, *d.c)
-		log.Println(err)
-		return
-	}
+	data := make(map[string]any)
+	data["name"] = name
+	// TODO: make this configurable
+	data["ref"] = "master"
 
-	d.listFiles(files, w)
+	d.listFiles(files, data, w)
 	return
 }
 
@@ -53,27 +50,25 @@ 	name = filepath.Clean(name)
 	// TODO: remove .git
 	path := filepath.Join(d.c.Git.ScanPath, name+".git")
-	repo, err := gogit.PlainOpen(path)
+	gr, err := git.Open(path, ref)
 	if err != nil {
 		Write404(w, *d.c)
 		return
 	}
 
-	hash, err := repo.ResolveRevision(plumbing.Revision(ref))
+	files, err := gr.FileTree(treePath)
 	if err != nil {
 		Write500(w, *d.c)
 		log.Println(err)
 		return
 	}
 
-	files, err := git.FilesAtRef(repo, *hash, treePath)
-	if err != nil {
-		Write500(w, *d.c)
-		log.Println(err)
-		return
-	}
+	data := make(map[string]any)
+	data["name"] = name
+	data["ref"] = ref
+	data["parent"] = treePath
 
-	d.listFiles(files, w)
+	d.listFiles(files, data, w)
 	return
 }
 
@@ -85,20 +80,50 @@ 	name = filepath.Clean(name)
 	// TODO: remove .git
 	path := filepath.Join(d.c.Git.ScanPath, name+".git")
-	repo, err := gogit.PlainOpen(path)
+	gr, err := git.Open(path, ref)
+	if err != nil {
+		Write404(w, *d.c)
+		return
+	}
+
+	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
 	}
 
-	hash, err := repo.ResolveRevision(plumbing.Revision(ref))
+	commits, err := gr.Commits()
 	if err != nil {
 		Write500(w, *d.c)
 		log.Println(err)
 		return
 	}
 
-	contents, err := git.FileContentAtRef(repo, *hash, treePath)
-	d.showFile(contents, w)
-	return
+	tpath := filepath.Join(d.c.Template.Dir, "*")
+	t := template.Must(template.ParseGlob(tpath))
+
+	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
+	}
 }
M routes/template.goroutes/template.go
@@ -24,31 +24,29 @@ t := template.Must(template.ParseFiles(tpath)) 	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, "*")
 	t := template.Must(template.ParseGlob(tpath))
 
-	data := make(map[string]interface{})
 	data["files"] = files
 	data["meta"] = d.c.Meta
 
 	if err := t.ExecuteTemplate(w, "repo", data); err != nil {
-		Write500(w, *d.c)
 		log.Println(err)
 		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, "*")
 	t := template.Must(template.ParseGlob(tpath))
 
-	data := make(map[string]interface{})
+	// TODO: Process content here.
+
 	data["content"] = content
 	data["meta"] = d.c.Meta
 
 	if err := t.ExecuteTemplate(w, "file", data); err != nil {
-		Write500(w, *d.c)
 		log.Println(err)
 		return
 	}
M templates/file.htmltemplates/file.html
@@ -10,7 +10,7 @@ <body>     {{ template "nav" . }}
     <main>
       <pre>
-        {{ .content }}
+{{ .content }}
       </pre>
     </main>
   </body>
A templates/log.html
@@ -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>
+        &mdash; {{ .Author.Name }}</p>
+      <p><pre>{{ .Message }}</pre></p>
+      {{ end }}
+    </main>
+  </body>
+</html>
+{{ end }}
M templates/repo.htmltemplates/repo.html
@@ -9,13 +9,41 @@ </header>   <body>
     {{ template "nav" . }}
     <main>
+      {{ $repo := .name }}
+      {{ $ref := .ref }}
+      {{ $parent := .parent }}
+
+      <table>
+        <tr>
+          <td></td>
+          <td><a href="../">..</a>
+        </tr>
       {{ range .files }}
-      {{ if .IsFile }}
-      <p>{{ .Mode }} {{ .Name }} {{ .Size }} </p>
-      {{ else }}
-      <p>d-------- {{ .Name}}/</p>
-      {{ end }}
+        {{ if .IsFile }}
+        <tr>
+          <td><code>{{ .Mode }}</code></td>
+          <td>
+          {{ 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 }}
+      </table>
     </main>
   </body>
 </html>