forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

appview: tags and branches pages

Changed files
+220 -54
appview
knotserver
types
+20
appview/pages/pages.go
···
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)
+
}
+18
appview/pages/templates/repo/branches.html
···
+
{{ define "title" }}
+
branches | {{ .RepoInfo.OwnerWithAt }} /
+
{{ .RepoInfo.Name }}
+
{{ end }}
+
+
{{ define "content" }}
+
{{ $name := .RepoInfo.Name }}
+
<h3>branches</h3>
+
<div class="refs">
+
{{ range .Branches }}
+
<div>
+
<strong>{{ .Name }}</strong>
+
<a href="/{{ $name }}/tree/{{ .Name }}/">browse</a>
+
<a href="/{{ $name }}/log/{{ .Name }}">log</a>
+
</div>
+
{{ end }}
+
</div>
+
{{ end }}
+6 -8
appview/pages/templates/repo/empty.html
···
-
<html>
-
{{ template "layouts/head" . }}
+
{{ define "title" }}{{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }}{{ end }}
-
<body>
-
<main></main>
-
<p>This is an empty Git repository. Push some commits here.</p>
-
</main>
-
</body>
-
</html>
+
{{ define "content" }}
+
<main>
+
<p>This is an empty Git repository. Push some commits here.</p>
+
</main>
+
{{ end }}
-38
appview/pages/templates/repo/refs.html
···
-
<html>
-
{{ template "layouts/head" . }}
-
-
{{ template "layouts/repo-header" . }}
-
<body>
-
{{ template "layouts/nav" . }}
-
<main>
-
{{ $name := .name }}
-
<h3>branches</h3>
-
<div class="refs">
-
{{ range .branches }}
-
<div>
-
<strong>{{ .Name.Short }}</strong>
-
<a href="/{{ $name }}/tree/{{ .Name.Short }}/">browse</a>
-
<a href="/{{ $name }}/log/{{ .Name.Short }}">log</a>
-
<a href="/{{ $name }}/archive/{{ .Name.Short }}.tar.gz">tar.gz</a>
-
</div>
-
{{ end }}
-
</div>
-
{{ if .tags }}
-
<h3>tags</h3>
-
<div class="refs">
-
{{ range .tags }}
-
<div>
-
<strong>{{ .Name }}</strong>
-
<a href="/{{ $name }}/tree/{{ .Name }}/">browse</a>
-
<a href="/{{ $name }}/log/{{ .Name }}">log</a>
-
<a href="/{{ $name }}/archive/{{ .Name }}.tar.gz">tar.gz</a>
-
{{ if .Message }}
-
<pre>{{ .Message }}</pre>
-
</div>
-
{{ end }}
-
{{ end }}
-
</div>
-
{{ end }}
-
</main>
-
</body>
-
</html>
+22
appview/pages/templates/repo/tags.html
···
+
{{ define "title" }}
+
tags | {{ .RepoInfo.OwnerWithAt }} /
+
{{ .RepoInfo.Name }}
+
{{ end }}
+
+
{{ define "content" }}
+
{{ $name := .RepoInfo.Name }}
+
<h3>tags</h3>
+
<div class="refs">
+
{{ range .Tags }}
+
<div>
+
<strong>{{ .Ref.Name }}</strong>
+
<a href="/{{ $name }}/tree/{{ .Ref.Name }}/">browse</a>
+
<a href="/{{ $name }}/log/{{ .Ref.Name }}">log</a>
+
<a href="/{{ $name }}/archive/{{ .Ref.Name }}.tar.gz">tar.gz</a>
+
{{ if .Message }}
+
<pre>{{ .Message }}</pre>
+
{{ end }}
+
</div>
+
{{ end }}
+
</div>
+
{{ end }}
+76
appview/state/repo.go
···
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)
+2
appview/state/state.go
···
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)
+8
knotserver/git/git.go
···
}
return ""
}
+
+
func (t *TagReference) TagObject() *object.Tag {
+
return t.tag
+
}
+
+
func (t *TagReference) Hash() plumbing.Hash {
+
return t.ref.Hash()
+
}
+2 -1
knotserver/handler.go
···
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)
})
})
+43 -7
knotserver/routes.go
···
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")
···
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()
···
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
}
+23
types/repo.go
···
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"`
+
}