Monorepo for Tangled tangled.org

add repo-tree template

Changed files
+116 -54
appview
pages
templates
state
knotserver
types
+10
appview/pages/pages.go
··· 175 175 func (p *Pages) RepoCommit(w io.Writer, params RepoCommitParams) error { 176 176 return p.execute("repo/commit", w, params) 177 177 } 178 + 179 + type RepoTreeParams struct { 180 + LoggedInUser *auth.User 181 + RepoInfo RepoInfo 182 + types.RepoTreeResponse 183 + } 184 + 185 + func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error { 186 + return p.execute("repo/tree", w, params) 187 + }
+2 -2
appview/pages/templates/repo/index.html
··· 1 - {{define "title"}} {{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }} {{end}} 1 + {{define "title"}} {{ .RepoInfo.FullName }} {{end}} 2 2 3 3 {{define "content"}} 4 4 5 5 <h1> 6 - {{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }} 6 + {{ .RepoInfo.FullName }} 7 7 </h1> 8 8 <main> 9 9 {{- if .IsEmpty }}
+21 -26
appview/pages/templates/repo/tree.html
··· 1 - <html> 1 + {{define "title"}} {{ .RepoInfo.FullName }} {{end}} 2 2 3 - {{ template "layouts/head" . }} 3 + {{define "content"}} 4 4 5 - {{ template "layouts/repo-header" . }} 6 - <body> 7 - {{ template "layouts/nav" . }} 5 + <h1> 6 + {{ .RepoInfo.FullName }} 7 + </h1> 8 8 <main> 9 - {{ $repo := .name }} 10 - {{ $ref := .ref }} 11 - {{ $parent := .parent }} 12 - 13 9 <div class="tree"> 14 - {{ if $parent }} 10 + 11 + {{ if .Parent }} 15 12 <div></div> 16 13 <div></div> 17 - <div><a href="/{{ $repo }}/tree/{{ $ref }}/{{ .dotdot }}">..</a></div> 14 + <div><a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}/{{ .DotDot }}">..</a></div> 18 15 {{ end }} 19 - {{ range .files }} 16 + 17 + {{ range .Files }} 20 18 {{ if not .IsFile }} 21 19 <div class="mode">{{ .Mode }}</div> 22 20 <div class="size">{{ .Size }}</div> 23 21 <div> 24 - {{ if $parent }} 25 - <a href="/{{ $repo }}/tree/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}/</a> 22 + {{ if $.Parent }} 23 + <a href="/{{ .RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ $.Parent }}/{{ .Name }}">{{ .Name }}/</a> 26 24 {{ else }} 27 - <a href="/{{ $repo }}/tree/{{ $ref }}/{{ .Name }}">{{ .Name }}/</a> 25 + <a href="/{{ .RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ .Name }}">{{ .Name }}/</a> 28 26 {{ end }} 29 27 </div> 28 + <hr /> 30 29 {{ end }} 31 30 {{ end }} 32 - {{ range .files }} 31 + 32 + {{ range .Files }} 33 33 {{ if .IsFile }} 34 34 <div class="mode">{{ .Mode }}</div> 35 35 <div class="size">{{ .Size }}</div> 36 36 <div> 37 - {{ if $parent }} 38 - <a href="/{{ $repo }}/blob/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}</a> 37 + {{ if $.Parent }} 38 + <a href="/{{ $.RepoInfo.FullName }}/blob/{{ $.Ref }}/{{ $.Parent }}/{{ .Name }}">{{ .Name }}</a> 39 39 {{ else }} 40 - <a href="/{{ $repo }}/blob/{{ $ref }}/{{ .Name }}">{{ .Name }}</a> 40 + <a href="/{{ $.RepoInfo.FullName }}/blob/{{ $.Ref }}/{{ .Name }}">{{ .Name }}</a> 41 41 {{ end }} 42 42 </div> 43 + <hr /> 43 44 {{ end }} 44 45 {{ end }} 45 46 </div> 46 - <article> 47 - <pre> 48 - {{- if .readme }}{{ .readme }}{{- end -}} 49 - </pre> 50 - </article> 51 47 </main> 52 - </body> 53 - </html> 48 + {{end}}
+42
appview/state/repo.go
··· 133 133 return 134 134 } 135 135 136 + func (s *State) RepoTree(w http.ResponseWriter, r *http.Request) { 137 + repoName, knot, id, err := repoKnotAndId(r) 138 + if err != nil { 139 + log.Println("failed to get repo and knot", err) 140 + return 141 + } 142 + 143 + ref := chi.URLParam(r, "ref") 144 + treePath := chi.URLParam(r, "*") 145 + resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/tree/%s/%s", knot, id.DID.String(), repoName, ref, treePath)) 146 + if err != nil { 147 + log.Println("failed to reach knotserver", err) 148 + return 149 + } 150 + 151 + body, err := io.ReadAll(resp.Body) 152 + if err != nil { 153 + log.Fatalf("Error reading response body: %v", err) 154 + return 155 + } 156 + 157 + var result types.RepoTreeResponse 158 + err = json.Unmarshal(body, &result) 159 + if err != nil { 160 + log.Println("failed to parse response:", err) 161 + return 162 + } 163 + 164 + log.Println(result) 165 + 166 + s.pages.RepoTree(w, pages.RepoTreeParams{ 167 + LoggedInUser: s.auth.GetUser(r), 168 + RepoInfo: pages.RepoInfo{ 169 + OwnerDid: id.DID.String(), 170 + OwnerHandle: id.Handle.String(), 171 + Name: repoName, 172 + }, 173 + RepoTreeResponse: result, 174 + }) 175 + return 176 + } 177 + 136 178 func repoKnotAndId(r *http.Request) (string, string, identity.Identity, error) { 137 179 repoName := chi.URLParam(r, "repo") 138 180 knot, ok := r.Context().Value("knot").(string)
+3
appview/state/state.go
··· 602 602 r.With(ResolveRepoKnot(s)).Route("/{repo}", func(r chi.Router) { 603 603 r.Get("/", s.RepoIndex) 604 604 r.Get("/log/{ref}", s.RepoLog) 605 + r.Route("/tree/{ref}", func(r chi.Router) { 606 + r.Get("/*", s.RepoTree) 607 + }) 605 608 r.Get("/commit/{ref}", s.RepoCommit) 606 609 607 610 // These routes get proxied to the knot
+6 -14
knotserver/git/tree.go
··· 4 4 "fmt" 5 5 6 6 "github.com/go-git/go-git/v5/plumbing/object" 7 + "github.com/sotangled/tangled/types" 7 8 ) 8 9 9 - func (g *GitRepo) FileTree(path string) ([]NiceTree, error) { 10 + func (g *GitRepo) FileTree(path string) ([]types.NiceTree, error) { 10 11 c, err := g.r.CommitObject(g.h) 11 12 if err != nil { 12 13 return nil, fmt.Errorf("commit object: %w", err) 13 14 } 14 15 15 - files := []NiceTree{} 16 + files := []types.NiceTree{} 16 17 tree, err := c.Tree() 17 18 if err != nil { 18 19 return nil, fmt.Errorf("file tree: %w", err) ··· 39 40 return files, nil 40 41 } 41 42 42 - // A nicer git tree representation. 43 - type NiceTree struct { 44 - Name string 45 - Mode string 46 - Size int64 47 - IsFile bool 48 - IsSubtree bool 49 - } 50 - 51 - func makeNiceTree(t *object.Tree) []NiceTree { 52 - nts := []NiceTree{} 43 + func makeNiceTree(t *object.Tree) []types.NiceTree { 44 + nts := []types.NiceTree{} 53 45 54 46 for _, e := range t.Entries { 55 47 mode, _ := e.Mode.ToOSFileMode() 56 48 sz, _ := t.Size(e.Name) 57 - nts = append(nts, NiceTree{ 49 + nts = append(nts, types.NiceTree{ 58 50 Name: e.Name, 59 51 Mode: mode.String(), 60 52 IsFile: e.Mode.IsFile(),
+14 -6
knotserver/routes.go
··· 122 122 return 123 123 } 124 124 125 - data := make(map[string]any) 126 - data["ref"] = ref 127 - data["parent"] = treePath 128 - data["desc"] = getDescription(path) 129 - data["dotdot"] = filepath.Dir(treePath) 125 + resp := types.RepoTreeResponse{ 126 + Ref: ref, 127 + Parent: treePath, 128 + Description: getDescription(path), 129 + DotDot: filepath.Dir(treePath), 130 + Files: files, 131 + } 132 + // data := make(map[string]any) 133 + // data["ref"] = ref 134 + // data["parent"] = treePath 135 + // data["desc"] = getDescription(path) 136 + // data["dotdot"] = filepath.Dir(treePath) 130 137 131 - h.listFiles(files, data, w) 138 + writeJSON(w, resp) 139 + // h.listFiles(files, data, w) 132 140 return 133 141 } 134 142
+8 -6
types/repo.go
··· 24 24 PerPage int `json:"per_page,omitempty"` 25 25 } 26 26 27 - // data["commit"] = diff.Commit 28 - // 29 - // data["stat"] = diff.Stat 30 - // data["diff"] = diff.Diff 31 - // data["ref"] = ref 32 - // data["desc"] = getDescription(path) 33 27 type RepoCommitResponse struct { 34 28 Ref string `json:"ref,omitempty"` 35 29 Diff *NiceDiff `json:"diff,omitempty"` 36 30 } 31 + 32 + type RepoTreeResponse struct { 33 + Ref string `json:"ref,omitempty"` 34 + Parent string `json:"parent,omitempty"` 35 + Description string `json:"description,omitempty"` 36 + DotDot string `json:"dotdot,omitempty"` 37 + Files []NiceTree `json:"files,omitempty"` 38 + }
+10
types/tree.go
··· 1 + package types 2 + 3 + // A nicer git tree representation. 4 + type NiceTree struct { 5 + Name string 6 + Mode string 7 + Size int64 8 + IsFile bool 9 + IsSubtree bool 10 + }