Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview: repo file content

+108 -85
+24 -1
appview/pages/pages.go
··· 22 22 t map[string]*template.Template 23 23 } 24 24 25 + func funcMap() template.FuncMap { 26 + return template.FuncMap{ 27 + "split": func(s string) []string { 28 + return strings.Split(s, "\n") 29 + }, 30 + "add": func(a, b int) int { 31 + return a + b 32 + }, 33 + } 34 + } 35 + 25 36 func NewPages() *Pages { 26 37 templates := make(map[string]*template.Template) 27 38 ··· 48 37 49 38 if !strings.HasPrefix(path, "templates/layouts/") { 50 39 // Add the page template on top of the base 51 - tmpl, err := template.New(name).ParseFS(files, "templates/layouts/*.html", path) 40 + tmpl, err := template.New(name). 41 + Funcs(funcMap()). 42 + ParseFS(files, "templates/layouts/*.html", path) 52 43 if err != nil { 53 44 return fmt.Errorf("setting up template: %w", err) 54 45 } ··· 227 214 228 215 func (p *Pages) RepoTags(w io.Writer, params RepoTagsParams) error { 229 216 return p.executeRepo("repo/tags", w, params) 217 + } 218 + 219 + type RepoBlobParams struct { 220 + LoggedInUser *auth.User 221 + RepoInfo RepoInfo 222 + types.RepoBlobResponse 223 + } 224 + 225 + func (p *Pages) RepoBlob(w io.Writer, params RepoBlobParams) error { 226 + return p.executeRepo("repo/blob", w, params) 230 227 }
+12
appview/pages/templates/repo/blob.html
··· 1 + {{ define "repoContent" }} 2 + <table> 3 + <tbody><tr> 4 + <td class="line-numbers"> 5 + {{ range $i, $x := split .Contents }} 6 + {{ add $i 1 }} {{ $x }} <br> 7 + {{ end }} 8 + </td> 9 + <td class="file-content"></td> 10 + </tbody></tr> 11 + </table> 12 + {{end}}
-34
appview/pages/templates/repo/file.html
··· 1 - <html> 2 - {{ template "layouts/head" . }} 3 - {{ template "layouts/repo-header" . }} 4 - <body> 5 - {{ template "layouts/nav" . }} 6 - <main> 7 - <p>{{ .path }} (<a style="color: gray" href="?raw=true">view raw</a>)</p> 8 - {{if .chroma }} 9 - <div class="chroma-file-wrapper"> 10 - {{ .content }} 11 - </div> 12 - {{else}} 13 - <div class="file-wrapper"> 14 - <table> 15 - <tbody><tr> 16 - <td class="line-numbers"> 17 - <pre> 18 - {{- range .linecount }} 19 - <a id="L{{ . }}" href="#L{{ . }}">{{ . }}</a> 20 - {{- end -}} 21 - </pre> 22 - </td> 23 - <td class="file-content"> 24 - <pre> 25 - {{- .content -}} 26 - </pre> 27 - </td> 28 - </tbody></tr> 29 - </table> 30 - </div> 31 - {{end}} 32 - </main> 33 - </body> 34 - </html>
+40 -3
appview/state/repo.go
··· 48 48 OwnerDid: id.DID.String(), 49 49 OwnerHandle: id.Handle.String(), 50 50 Name: repoName, 51 - Description: result.Description, 52 51 }, 53 52 RepoIndexResponse: result, 54 53 }) ··· 88 89 OwnerDid: id.DID.String(), 89 90 OwnerHandle: id.Handle.String(), 90 91 Name: repoName, 91 - Description: result.Description, 92 92 }, 93 93 RepoLogResponse: result, 94 94 }) ··· 169 171 OwnerDid: id.DID.String(), 170 172 OwnerHandle: id.Handle.String(), 171 173 Name: repoName, 172 - Description: result.Description, 173 174 }, 174 175 RepoTreeResponse: result, 175 176 }) ··· 247 250 Name: repoName, 248 251 }, 249 252 RepoBranchesResponse: result, 253 + }) 254 + return 255 + } 256 + 257 + func (s *State) RepoBlob(w http.ResponseWriter, r *http.Request) { 258 + repoName, knot, id, err := repoKnotAndId(r) 259 + if err != nil { 260 + log.Println("failed to get repo and knot", err) 261 + return 262 + } 263 + 264 + ref := chi.URLParam(r, "ref") 265 + filePath := chi.URLParam(r, "*") 266 + resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/blob/%s/%s", knot, id.DID.String(), repoName, ref, filePath)) 267 + if err != nil { 268 + log.Println("failed to reach knotserver", err) 269 + return 270 + } 271 + 272 + body, err := io.ReadAll(resp.Body) 273 + if err != nil { 274 + log.Fatalf("Error reading response body: %v", err) 275 + return 276 + } 277 + 278 + var result types.RepoBlobResponse 279 + err = json.Unmarshal(body, &result) 280 + if err != nil { 281 + log.Println("failed to parse response:", err) 282 + return 283 + } 284 + 285 + s.pages.RepoBlob(w, pages.RepoBlobParams{ 286 + LoggedInUser: s.auth.GetUser(r), 287 + RepoInfo: pages.RepoInfo{ 288 + OwnerDid: id.DID.String(), 289 + OwnerHandle: id.Handle.String(), 290 + Name: repoName, 291 + }, 292 + RepoBlobResponse: result, 250 293 }) 251 294 return 252 295 }
+1
appview/state/state.go
··· 617 617 r.Get("/commit/{ref}", s.RepoCommit) 618 618 r.Get("/branches", s.RepoBranches) 619 619 r.Get("/tags", s.RepoTags) 620 + r.Get("/blob/{ref}/*", s.RepoBlob) 620 621 621 622 // These routes get proxied to the knot 622 623 r.Get("/info/refs", s.InfoRefs)
+4 -20
knotserver/file.go
··· 43 43 } 44 44 } 45 45 46 - func (h *Handle) showFile(content string, data map[string]any, w http.ResponseWriter, l *slog.Logger) { 47 - lc, err := countLines(strings.NewReader(content)) 46 + func (h *Handle) showFile(resp types.RepoBlobResponse, w http.ResponseWriter, l *slog.Logger) { 47 + lc, err := countLines(strings.NewReader(resp.Contents)) 48 48 if err != nil { 49 49 // Non-fatal, we'll just skip showing line numbers in the template. 50 50 l.Warn("counting lines", "error", err) 51 51 } 52 52 53 - lines := make([]int, lc) 54 - if lc > 0 { 55 - for i := range lines { 56 - lines[i] = i + 1 57 - } 58 - } 59 - 60 - data["linecount"] = lines 61 - data["content"] = content 62 - 63 - writeJSON(w, data) 64 - return 65 - } 66 - 67 - func (h *Handle) showRaw(content string, w http.ResponseWriter) { 68 - w.WriteHeader(http.StatusOK) 69 - w.Header().Set("Content-Type", "text/plain") 70 - w.Write([]byte(content)) 53 + resp.Lines = lc 54 + writeJSON(w, resp) 71 55 return 72 56 }
+1 -1
knotserver/handler.go
··· 78 78 }) 79 79 80 80 r.Route("/blob/{ref}", func(r chi.Router) { 81 - r.Get("/*", h.FileContent) 81 + r.Get("/*", h.Blob) 82 82 }) 83 83 84 84 r.Get("/log/{ref}", h.Log)
+13 -21
knotserver/routes.go
··· 129 129 DotDot: filepath.Dir(treePath), 130 130 Files: files, 131 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) 137 132 138 133 writeJSON(w, resp) 139 - // h.listFiles(files, data, w) 140 134 return 141 135 } 142 136 143 - func (h *Handle) FileContent(w http.ResponseWriter, r *http.Request) { 144 - var raw bool 145 - if rawParam, err := strconv.ParseBool(r.URL.Query().Get("raw")); err == nil { 146 - raw = rawParam 147 - } 148 - 137 + func (h *Handle) Blob(w http.ResponseWriter, r *http.Request) { 149 138 treePath := chi.URLParam(r, "*") 150 139 ref := chi.URLParam(r, "ref") 151 140 ··· 152 163 writeError(w, err.Error(), http.StatusInternalServerError) 153 164 return 154 165 } 155 - data := make(map[string]any) 156 - data["ref"] = ref 157 - data["desc"] = getDescription(path) 158 - data["path"] = treePath 159 166 160 - safe := sanitize([]byte(contents)) 167 + safe := string(sanitize([]byte(contents))) 161 168 162 - if raw { 163 - h.showRaw(string(safe), w) 164 - } else { 165 - h.showFile(string(safe), data, w, l) 169 + resp := types.RepoBlobResponse{ 170 + Ref: ref, 171 + Contents: string(safe), 172 + Path: treePath, 166 173 } 174 + 175 + h.showFile(resp, w, l) 167 176 } 168 177 169 178 func (h *Handle) Archive(w http.ResponseWriter, r *http.Request) { ··· 328 341 }, 329 342 Tag: tag.TagObject(), 330 343 } 344 + 345 + if tag.Message() != "" { 346 + tr.Message = tag.Message() 347 + } 348 + 331 349 rtags = append(rtags, &tr) 332 350 } 333 351
+8
types/repo.go
··· 59 59 type RepoBranchesResponse struct { 60 60 Branches []Branch `json:"branches,omitempty"` 61 61 } 62 + 63 + type RepoBlobResponse struct { 64 + Contents string `json:"contents,omitempty"` 65 + Ref string `json:"ref,omitempty"` 66 + Path string `json:"path,omitempty"` 67 + 68 + Lines int `json:"lines,omitempty"` 69 + }
+5 -5
types/tree.go
··· 2 2 3 3 // A nicer git tree representation. 4 4 type NiceTree struct { 5 - Name string 6 - Mode string 7 - Size int64 8 - IsFile bool 9 - IsSubtree bool 5 + Name string `json:"name"` 6 + Mode string `json:"mode"` 7 + Size int64 `json:"size"` 8 + IsFile bool `json:"is_file"` 9 + IsSubtree bool `json:"is_subtree"` 10 10 }