diff --git a/appview/pages/pages.go b/appview/pages/pages.go
index 5b9fe993..471f1262 100644
--- a/appview/pages/pages.go
+++ b/appview/pages/pages.go
@@ -185,3 +185,23 @@ type RepoTreeParams struct {
func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
return p.execute("repo/tree", w, params)
}
+
+type RepoBranchesParams struct {
+ LoggedInUser *auth.User
+ RepoInfo RepoInfo
+ types.RepoBranchesResponse
+}
+
+func (p *Pages) RepoBranches(w io.Writer, params RepoBranchesParams) error {
+ return p.execute("repo/branches", w, params)
+}
+
+type RepoTagsParams struct {
+ LoggedInUser *auth.User
+ RepoInfo RepoInfo
+ types.RepoTagsResponse
+}
+
+func (p *Pages) RepoTags(w io.Writer, params RepoTagsParams) error {
+ return p.execute("repo/tags", w, params)
+}
diff --git a/appview/pages/templates/repo/branches.html b/appview/pages/templates/repo/branches.html
new file mode 100644
index 00000000..89b880e5
--- /dev/null
+++ b/appview/pages/templates/repo/branches.html
@@ -0,0 +1,18 @@
+{{ define "title" }}
+ branches | {{ .RepoInfo.OwnerWithAt }} /
+ {{ .RepoInfo.Name }}
+{{ end }}
+
+{{ define "content" }}
+ {{ $name := .RepoInfo.Name }}
+
branches
+
+ {{ range .Branches }}
+
+ {{ end }}
+
+{{ end }}
diff --git a/appview/pages/templates/repo/empty.html b/appview/pages/templates/repo/empty.html
index 27332203..0ba2a347 100644
--- a/appview/pages/templates/repo/empty.html
+++ b/appview/pages/templates/repo/empty.html
@@ -1,9 +1,7 @@
-
- {{ template "layouts/head" . }}
+{{ define "title" }}{{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }}{{ end }}
-
-
- This is an empty Git repository. Push some commits here.
-
-
-
+{{ define "content" }}
+
+ This is an empty Git repository. Push some commits here.
+
+{{ end }}
diff --git a/appview/pages/templates/repo/refs.html b/appview/pages/templates/repo/refs.html
deleted file mode 100644
index cb24aeb0..00000000
--- a/appview/pages/templates/repo/refs.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-{{ template "layouts/head" . }}
-
- {{ template "layouts/repo-header" . }}
-
- {{ template "layouts/nav" . }}
-
- {{ $name := .name }}
- branches
-
- {{ range .branches }}
-
- {{ end }}
-
- {{ if .tags }}
- tags
-
- {{ range .tags }}
-
-
{{ .Name }}
-
browse
-
log
-
tar.gz
- {{ if .Message }}
-
{{ .Message }}
-
- {{ end }}
- {{ end }}
-
- {{ end }}
-
-
-
\ No newline at end of file
diff --git a/appview/pages/templates/repo/tags.html b/appview/pages/templates/repo/tags.html
new file mode 100644
index 00000000..3200dc7a
--- /dev/null
+++ b/appview/pages/templates/repo/tags.html
@@ -0,0 +1,22 @@
+{{ define "title" }}
+ tags | {{ .RepoInfo.OwnerWithAt }} /
+ {{ .RepoInfo.Name }}
+{{ end }}
+
+{{ define "content" }}
+ {{ $name := .RepoInfo.Name }}
+ tags
+
+ {{ range .Tags }}
+
+
{{ .Ref.Name }}
+
browse
+
log
+
tar.gz
+ {{ if .Message }}
+
{{ .Message }}
+ {{ end }}
+
+ {{ end }}
+
+{{ end }}
diff --git a/appview/state/repo.go b/appview/state/repo.go
index 9d8458f5..a6a77300 100644
--- a/appview/state/repo.go
+++ b/appview/state/repo.go
@@ -175,6 +175,82 @@ func (s *State) RepoTree(w http.ResponseWriter, r *http.Request) {
return
}
+func (s *State) RepoTags(w http.ResponseWriter, r *http.Request) {
+ repoName, knot, id, err := repoKnotAndId(r)
+ if err != nil {
+ log.Println("failed to get repo and knot", err)
+ return
+ }
+
+ resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/tags", knot, id.DID.String(), repoName))
+ if err != nil {
+ log.Println("failed to reach knotserver", err)
+ return
+ }
+
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ log.Fatalf("Error reading response body: %v", err)
+ return
+ }
+
+ var result types.RepoTagsResponse
+ err = json.Unmarshal(body, &result)
+ if err != nil {
+ log.Println("failed to parse response:", err)
+ return
+ }
+
+ s.pages.RepoTags(w, pages.RepoTagsParams{
+ LoggedInUser: s.auth.GetUser(r),
+ RepoInfo: pages.RepoInfo{
+ OwnerDid: id.DID.String(),
+ OwnerHandle: id.Handle.String(),
+ Name: repoName,
+ },
+ RepoTagsResponse: result,
+ })
+ return
+}
+
+func (s *State) RepoBranches(w http.ResponseWriter, r *http.Request) {
+ repoName, knot, id, err := repoKnotAndId(r)
+ if err != nil {
+ log.Println("failed to get repo and knot", err)
+ return
+ }
+
+ resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/branches", knot, id.DID.String(), repoName))
+ if err != nil {
+ log.Println("failed to reach knotserver", err)
+ return
+ }
+
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ log.Fatalf("Error reading response body: %v", err)
+ return
+ }
+
+ var result types.RepoBranchesResponse
+ err = json.Unmarshal(body, &result)
+ if err != nil {
+ log.Println("failed to parse response:", err)
+ return
+ }
+
+ s.pages.RepoBranches(w, pages.RepoBranchesParams{
+ LoggedInUser: s.auth.GetUser(r),
+ RepoInfo: pages.RepoInfo{
+ OwnerDid: id.DID.String(),
+ OwnerHandle: id.Handle.String(),
+ Name: repoName,
+ },
+ RepoBranchesResponse: result,
+ })
+ return
+}
+
func repoKnotAndId(r *http.Request) (string, string, identity.Identity, error) {
repoName := chi.URLParam(r, "repo")
knot, ok := r.Context().Value("knot").(string)
diff --git a/appview/state/state.go b/appview/state/state.go
index e3b57d94..c92d4dd7 100644
--- a/appview/state/state.go
+++ b/appview/state/state.go
@@ -614,6 +614,8 @@ func (s *State) UserRouter() http.Handler {
r.Get("/*", s.RepoTree)
})
r.Get("/commit/{ref}", s.RepoCommit)
+ r.Get("/branches", s.RepoBranches)
+ r.Get("/tags", s.RepoTags)
// These routes get proxied to the knot
r.Get("/info/refs", s.InfoRefs)
diff --git a/knotserver/git/git.go b/knotserver/git/git.go
index ecd9ddaa..acfa32e8 100644
--- a/knotserver/git/git.go
+++ b/knotserver/git/git.go
@@ -347,3 +347,11 @@ func (t *TagReference) Message() string {
}
return ""
}
+
+func (t *TagReference) TagObject() *object.Tag {
+ return t.tag
+}
+
+func (t *TagReference) Hash() plumbing.Hash {
+ return t.ref.Hash()
+}
diff --git a/knotserver/handler.go b/knotserver/handler.go
index 5322275b..cce5669f 100644
--- a/knotserver/handler.go
+++ b/knotserver/handler.go
@@ -84,7 +84,8 @@ func Setup(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, l
r.Get("/log/{ref}", h.Log)
r.Get("/archive/{file}", h.Archive)
r.Get("/commit/{ref}", h.Diff)
- r.Get("/refs/", h.Refs)
+ r.Get("/tags", h.Tags)
+ r.Get("/branches", h.Branches)
})
})
diff --git a/knotserver/routes.go b/knotserver/routes.go
index a6612ab9..52a3209b 100644
--- a/knotserver/routes.go
+++ b/knotserver/routes.go
@@ -316,7 +316,7 @@ func (h *Handle) Diff(w http.ResponseWriter, r *http.Request) {
return
}
-func (h *Handle) Refs(w http.ResponseWriter, r *http.Request) {
+func (h *Handle) Tags(w http.ResponseWriter, r *http.Request) {
path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
l := h.l.With("handler", "Refs")
@@ -329,7 +329,37 @@ func (h *Handle) Refs(w http.ResponseWriter, r *http.Request) {
tags, err := gr.Tags()
if err != nil {
// Non-fatal, we *should* have at least one branch to show.
- l.Error("getting tags", "error", err.Error())
+ l.Warn("getting tags", "error", err.Error())
+ }
+
+ rtags := []*types.TagReference{}
+ for _, tag := range tags {
+ tr := types.TagReference{
+ Ref: types.Reference{
+ Name: tag.Name(),
+ Hash: tag.Hash().String(),
+ },
+ Tag: tag.TagObject(),
+ }
+ rtags = append(rtags, &tr)
+ }
+
+ resp := types.RepoTagsResponse{
+ Tags: rtags,
+ }
+
+ writeJSON(w, resp)
+ return
+}
+
+func (h *Handle) Branches(w http.ResponseWriter, r *http.Request) {
+ path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
+ l := h.l.With("handler", "Branches")
+
+ gr, err := git.Open(path, "")
+ if err != nil {
+ notFound(w)
+ return
}
branches, err := gr.Branches()
@@ -339,13 +369,19 @@ func (h *Handle) Refs(w http.ResponseWriter, r *http.Request) {
return
}
- data := make(map[string]interface{})
+ bs := []types.Branch{}
+ for _, branch := range branches {
+ b := types.Branch{}
+ b.Hash = branch.Hash().String()
+ b.Name = branch.Name().Short()
+ bs = append(bs, b)
+ }
- data["branches"] = branches
- data["tags"] = tags
- data["desc"] = getDescription(path)
+ resp := types.RepoBranchesResponse{
+ Branches: bs,
+ }
- writeJSON(w, data)
+ writeJSON(w, resp)
return
}
diff --git a/types/repo.go b/types/repo.go
index e2fccf63..904138bf 100644
--- a/types/repo.go
+++ b/types/repo.go
@@ -36,3 +36,26 @@ type RepoTreeResponse struct {
DotDot string `json:"dotdot,omitempty"`
Files []NiceTree `json:"files,omitempty"`
}
+
+type TagReference struct {
+ Ref Reference `json:"ref,omitempty"`
+ Tag *object.Tag `json:"tag,omitempty"`
+ Message string `json:"message,omitempty"`
+}
+
+type Reference struct {
+ Name string `json:"name"`
+ Hash string `json:"hash"`
+}
+
+type Branch struct {
+ Reference `json:"reference"`
+}
+
+type RepoTagsResponse struct {
+ Tags []*TagReference `json:"tags,omitempty"`
+}
+
+type RepoBranchesResponse struct {
+ Branches []Branch `json:"branches,omitempty"`
+}