bidet

commit 585be7e7e1255e44cef779b4eeab47ee22ff35f7

tree

parent:
27221edbb187c64e1acc43018bf0e09ee1ac1193

nmyk <nick@nmyk.io>

2026-02-16T12:18:28-05:00

add refs page

diff --git a/main.go b/main.go
index 324555e0c08b19a42c7eb98c65160bc629b863fb..964d71f48ad6a6c9be499a03a3ae68dd94670ebb 100644
--- a/main.go
+++ b/main.go
@@ -37,6 +37,7 @@ func router() *http.ServeMux {
 	mux := http.NewServeMux()
 	mux.HandleFunc("GET /", listRepos)
 	mux.HandleFunc("GET /{name}", repoIndex)
+	mux.HandleFunc("GET /{name}/refs", refs)
 	mux.HandleFunc("GET /{name}/tree/{ref}", repoTree)
 	mux.HandleFunc("GET /{name}/tree/{ref}/{rest...}", repoTree)
 	mux.HandleFunc("GET /{name}/blob/{ref}/{rest...}", blob)
@@ -94,6 +95,45 @@ 	reader.Read(content)
 	return string(content), nil
 }
 
+type BranchMeta struct {
+	Name string
+}
+
+type RefsData struct {
+	Repo     string
+	Branches []BranchMeta
+}
+
+func refs(w http.ResponseWriter, r *http.Request) {
+	repoName := r.PathValue("name")
+	if _, err := os.Stat(repoName + DOT_GIT); os.IsNotExist(err) {
+		http.NotFound(w, r)
+		return
+	}
+	repo, err := git.PlainOpen(repoName + DOT_GIT)
+	if err != nil {
+		http.Error(w, err.Error(), 500)
+		return
+	}
+	iter, err := repo.Branches()
+	if err != nil {
+		http.Error(w, err.Error(), 500)
+	}
+	var branches []BranchMeta
+	err = iter.ForEach(func(ref *plumbing.Reference) error {
+		branches = append(branches, BranchMeta{ref.Name().Short()})
+		return nil
+	})
+	if err != nil {
+		http.Error(w, err.Error(), 500)
+	}
+	data := RefsData{
+		Repo:     repoName,
+		Branches: branches,
+	}
+	serve(w, "refs", data)
+}
+
 func blob(w http.ResponseWriter, r *http.Request) {
 	repoName := r.PathValue("name")
 	if _, err := os.Stat(repoName + DOT_GIT); os.IsNotExist(err) {
@@ -151,6 +191,7 @@
 type TreeData struct {
 	Repo       string
 	Ref        string
+	HeadRef    string
 	Base       string
 	Crumbs     []Crumb
 	Entries    []EntryMeta
@@ -159,9 +200,7 @@ 	Readme     string
 }
 
 type EntryMeta struct {
-	Repo  string
 	Name  string
-	Ref   string
 	Path  string
 	IsDir bool
 }
@@ -178,6 +217,16 @@ 		http.Error(w, err.Error(), 500)
 		return
 	}
 	refName := r.PathValue("ref")
+	head, err := repo.Head()
+	if err != nil {
+		http.Error(w, "Cannot resolve HEAD state", 500)
+	}
+	headRef := head.Name().Short()
+	treePath := r.PathValue("rest")
+	if refName == headRef && treePath == "" {
+		repoIndex(w, r)
+		return
+	}
 	branch := path.Join("refs", "heads", refName)
 	ref, err := repo.Reference(plumbing.ReferenceName(branch), true)
 	if err != nil {
@@ -194,7 +243,6 @@ 	if err != nil {
 		http.Error(w, err.Error(), 500)
 		return
 	}
-	treePath := r.PathValue("rest")
 	var tree *object.Tree
 	if treePath != "" {
 		treeEntry, err := rootTree.FindEntry(treePath)
@@ -213,9 +261,7 @@ 	var entries []EntryMeta
 	if treePath != "" {
 		entries = []EntryMeta{
 			{
-				Repo:  repoName,
 				Name:  "..",
-				Ref:   refName,
 				Path:  path.Dir(treePath),
 				IsDir: true,
 			},
@@ -225,9 +271,7 @@ 	var readme, readmeName string
 	for _, e := range tree.Entries {
 		fullPath := path.Join(treePath, e.Name)
 		em := EntryMeta{
-			Repo:  repoName,
 			Name:  e.Name,
-			Ref:   refName,
 			Path:  fullPath,
 			IsDir: e.Mode == filemode.Dir,
 		}
@@ -244,6 +288,7 @@ 	}
 	data := TreeData{
 		Repo:       repoName,
 		Ref:        refName,
+		HeadRef:    headRef,
 		Base:       treePath,
 		Crumbs:     breadcrumbs(repoName, refName, treePath),
 		Entries:    entries,
@@ -315,9 +360,7 @@ 	var entries []EntryMeta
 	var readme, readmeName string
 	for _, e := range tree.Entries {
 		em := EntryMeta{
-			Repo:  repoName,
 			Name:  e.Name,
-			Ref:   refName,
 			Path:  e.Name,
 			IsDir: e.Mode == filemode.Dir,
 		}
@@ -338,5 +381,5 @@ 		Entries:    entries,
 		ReadmeName: readmeName,
 		Readme:     readme,
 	}
-	serve(w, "tree", data)
+	serve(w, "repo", data)
 }
diff --git a/templates/refs.tmpl b/templates/refs.tmpl
new file mode 100644
index 0000000000000000000000000000000000000000..69cce1f4c73c8d5c7fcec8b65f7bc774312af99c
--- /dev/null
+++ b/templates/refs.tmpl
@@ -0,0 +1,14 @@
+{{define "title"}}{{.Repo}}{{end}}
+{{define "content"}}
+<h1><a href="/{{.Repo}}">{{.Repo}}</a></h1>
+<h2>branches</h2>
+<ul>
+{{range .Branches}}
+<li><a href="/{{$.Repo}}/tree/{{.Name}}">{{.Name}}</a></li>
+{{end}}
+</ul>
+{{end}}
+
+{{define "refs"}}
+{{template "base" .}}
+{{end}}
\ No newline at end of file
diff --git a/templates/repo.tmpl b/templates/repo.tmpl
new file mode 100644
index 0000000000000000000000000000000000000000..1768d39091f2ff5a2f9830dab58e806846c10df9
--- /dev/null
+++ b/templates/repo.tmpl
@@ -0,0 +1,28 @@
+{{define "title"}}{{.Repo}}/{{.Base}}{{end}}
+{{define "content"}}
+<h1>{{.Repo}}</h1>
+<p>@ {{.Ref}}</p>
+<p><a href="/">&lt;-- back</a> | <a href="/{{.Repo}}/refs">refs</a></p>
+<ul>
+{{range .Entries}}
+<li>
+    {{- if .IsDir -}}
+        📁 <a href="/{{$.Repo}}/tree/{{$.Ref}}/{{.Path}}">{{.Name}}</a>
+    {{- else -}}
+        📄 <a href="/{{$.Repo}}/blob/{{$.Ref}}/{{.Path}}">{{.Name}}</a>
+    {{- end -}}
+</li>
+{{end}}
+</ul>
+{{- if ne .Readme "" -}}
+<hr>
+<h2>{{.ReadmeName}}</h2>
+<pre>
+{{.Readme}}
+</pre>
+{{- end -}}
+{{end}}
+
+{{define "repo"}}
+{{template "base" .}}
+{{end}}
\ No newline at end of file
diff --git a/templates/tree.tmpl b/templates/tree.tmpl
index e492f157d050594093357fdc0a8a1fc32905804c..74bf3fd312b0bb754d610f28df06fcdcbbdb6640 100644
--- a/templates/tree.tmpl
+++ b/templates/tree.tmpl
@@ -1,6 +1,9 @@
 {{define "title"}}{{.Repo}}/{{.Base}}{{end}}
 {{define "content"}}
-<h1>{{if eq .Base ""}}{{.Repo}}{{else}}<a href="/{{.Repo}}/tree/{{.Ref}}">{{.Repo}}</a> /{{end}}
+<h1>{{if ne .Base ""}}<a href="/{{.Repo}}/tree/{{.Ref}}">{{.Repo}}</a> /
+{{else}}
+<a href="/{{.Repo}}/tree/{{.HeadRef}}">{{.Repo}}</a> /
+{{end}}
 {{range $i, $c := .Crumbs}}
   {{if $i}} / {{end}}
   {{if $c.IsLast}}
@@ -9,14 +12,14 @@   {{else}}
     <a href="/{{$c.URL}}">{{$c.Name}}</a>
   {{end}}
 {{end}}</h1>
-{{if eq .Base ""}}<p><a href="/">&lt;-- back</a></p>{{end}}
+<p>@ {{.Ref}}</p>
 <ul>
 {{range .Entries}}
 <li>
     {{- if .IsDir -}}
-        📁 <a href="/{{.Repo}}/tree/{{.Ref}}/{{.Path}}">{{.Name}}</a>
+        📁 <a href="/{{$.Repo}}/tree/{{$.Ref}}/{{.Path}}">{{.Name}}</a>
     {{- else -}}
-        📄 <a href="/{{.Repo}}/blob/{{.Ref}}/{{.Path}}">{{.Name}}</a>
+        📄 <a href="/{{$.Repo}}/blob/{{$.Ref}}/{{.Path}}">{{.Name}}</a>
     {{- end -}}
 </li>
 {{end}}