forked from tangled.org/core
this repo has no description

appview: repo file content

anirudh.fi f17f72d0 a0941c5b

verified
Changed files
+108 -85
appview
pages
templates
state
knotserver
types
+24 -1
appview/pages/pages.go
···
t map[string]*template.Template
}
func NewPages() *Pages {
templates := make(map[string]*template.Template)
···
if !strings.HasPrefix(path, "templates/layouts/") {
// Add the page template on top of the base
-
tmpl, err := template.New(name).ParseFS(files, "templates/layouts/*.html", path)
if err != nil {
return fmt.Errorf("setting up template: %w", err)
}
···
func (p *Pages) RepoTags(w io.Writer, params RepoTagsParams) error {
return p.executeRepo("repo/tags", w, params)
}
···
t map[string]*template.Template
}
+
func funcMap() template.FuncMap {
+
return template.FuncMap{
+
"split": func(s string) []string {
+
return strings.Split(s, "\n")
+
},
+
"add": func(a, b int) int {
+
return a + b
+
},
+
}
+
}
+
func NewPages() *Pages {
templates := make(map[string]*template.Template)
···
if !strings.HasPrefix(path, "templates/layouts/") {
// Add the page template on top of the base
+
tmpl, err := template.New(name).
+
Funcs(funcMap()).
+
ParseFS(files, "templates/layouts/*.html", path)
if err != nil {
return fmt.Errorf("setting up template: %w", err)
}
···
func (p *Pages) RepoTags(w io.Writer, params RepoTagsParams) error {
return p.executeRepo("repo/tags", w, params)
}
+
+
type RepoBlobParams struct {
+
LoggedInUser *auth.User
+
RepoInfo RepoInfo
+
types.RepoBlobResponse
+
}
+
+
func (p *Pages) RepoBlob(w io.Writer, params RepoBlobParams) error {
+
return p.executeRepo("repo/blob", w, params)
+
}
+12
appview/pages/templates/repo/blob.html
···
···
+
{{ define "repoContent" }}
+
<table>
+
<tbody><tr>
+
<td class="line-numbers">
+
{{ range $i, $x := split .Contents }}
+
{{ add $i 1 }} {{ $x }} <br>
+
{{ end }}
+
</td>
+
<td class="file-content"></td>
+
</tbody></tr>
+
</table>
+
{{end}}
-34
appview/pages/templates/repo/file.html
···
-
<html>
-
{{ template "layouts/head" . }}
-
{{ template "layouts/repo-header" . }}
-
<body>
-
{{ template "layouts/nav" . }}
-
<main>
-
<p>{{ .path }} (<a style="color: gray" href="?raw=true">view raw</a>)</p>
-
{{if .chroma }}
-
<div class="chroma-file-wrapper">
-
{{ .content }}
-
</div>
-
{{else}}
-
<div class="file-wrapper">
-
<table>
-
<tbody><tr>
-
<td class="line-numbers">
-
<pre>
-
{{- range .linecount }}
-
<a id="L{{ . }}" href="#L{{ . }}">{{ . }}</a>
-
{{- end -}}
-
</pre>
-
</td>
-
<td class="file-content">
-
<pre>
-
{{- .content -}}
-
</pre>
-
</td>
-
</tbody></tr>
-
</table>
-
</div>
-
{{end}}
-
</main>
-
</body>
-
</html>
···
+40 -3
appview/state/repo.go
···
OwnerDid: id.DID.String(),
OwnerHandle: id.Handle.String(),
Name: repoName,
-
Description: result.Description,
},
RepoIndexResponse: result,
})
···
OwnerDid: id.DID.String(),
OwnerHandle: id.Handle.String(),
Name: repoName,
-
Description: result.Description,
},
RepoLogResponse: result,
})
···
OwnerDid: id.DID.String(),
OwnerHandle: id.Handle.String(),
Name: repoName,
-
Description: result.Description,
},
RepoTreeResponse: result,
})
···
Name: repoName,
},
RepoBranchesResponse: result,
})
return
}
···
OwnerDid: id.DID.String(),
OwnerHandle: id.Handle.String(),
Name: repoName,
},
RepoIndexResponse: result,
})
···
OwnerDid: id.DID.String(),
OwnerHandle: id.Handle.String(),
Name: repoName,
},
RepoLogResponse: result,
})
···
OwnerDid: id.DID.String(),
OwnerHandle: id.Handle.String(),
Name: repoName,
},
RepoTreeResponse: result,
})
···
Name: repoName,
},
RepoBranchesResponse: result,
+
})
+
return
+
}
+
+
func (s *State) RepoBlob(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
+
}
+
+
ref := chi.URLParam(r, "ref")
+
filePath := chi.URLParam(r, "*")
+
resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/blob/%s/%s", knot, id.DID.String(), repoName, ref, filePath))
+
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.RepoBlobResponse
+
err = json.Unmarshal(body, &result)
+
if err != nil {
+
log.Println("failed to parse response:", err)
+
return
+
}
+
+
s.pages.RepoBlob(w, pages.RepoBlobParams{
+
LoggedInUser: s.auth.GetUser(r),
+
RepoInfo: pages.RepoInfo{
+
OwnerDid: id.DID.String(),
+
OwnerHandle: id.Handle.String(),
+
Name: repoName,
+
},
+
RepoBlobResponse: result,
})
return
}
+1
appview/state/state.go
···
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)
···
r.Get("/commit/{ref}", s.RepoCommit)
r.Get("/branches", s.RepoBranches)
r.Get("/tags", s.RepoTags)
+
r.Get("/blob/{ref}/*", s.RepoBlob)
// These routes get proxied to the knot
r.Get("/info/refs", s.InfoRefs)
+4 -20
knotserver/file.go
···
}
}
-
func (h *Handle) showFile(content string, data map[string]any, w http.ResponseWriter, l *slog.Logger) {
-
lc, err := countLines(strings.NewReader(content))
if err != nil {
// Non-fatal, we'll just skip showing line numbers in the template.
l.Warn("counting lines", "error", err)
}
-
lines := make([]int, lc)
-
if lc > 0 {
-
for i := range lines {
-
lines[i] = i + 1
-
}
-
}
-
-
data["linecount"] = lines
-
data["content"] = content
-
-
writeJSON(w, data)
-
return
-
}
-
-
func (h *Handle) showRaw(content string, w http.ResponseWriter) {
-
w.WriteHeader(http.StatusOK)
-
w.Header().Set("Content-Type", "text/plain")
-
w.Write([]byte(content))
return
}
···
}
}
+
func (h *Handle) showFile(resp types.RepoBlobResponse, w http.ResponseWriter, l *slog.Logger) {
+
lc, err := countLines(strings.NewReader(resp.Contents))
if err != nil {
// Non-fatal, we'll just skip showing line numbers in the template.
l.Warn("counting lines", "error", err)
}
+
resp.Lines = lc
+
writeJSON(w, resp)
return
}
+1 -1
knotserver/handler.go
···
})
r.Route("/blob/{ref}", func(r chi.Router) {
-
r.Get("/*", h.FileContent)
})
r.Get("/log/{ref}", h.Log)
···
})
r.Route("/blob/{ref}", func(r chi.Router) {
+
r.Get("/*", h.Blob)
})
r.Get("/log/{ref}", h.Log)
+13 -21
knotserver/routes.go
···
DotDot: filepath.Dir(treePath),
Files: files,
}
-
// data := make(map[string]any)
-
// data["ref"] = ref
-
// data["parent"] = treePath
-
// data["desc"] = getDescription(path)
-
// data["dotdot"] = filepath.Dir(treePath)
writeJSON(w, resp)
-
// h.listFiles(files, data, w)
return
}
-
func (h *Handle) FileContent(w http.ResponseWriter, r *http.Request) {
-
var raw bool
-
if rawParam, err := strconv.ParseBool(r.URL.Query().Get("raw")); err == nil {
-
raw = rawParam
-
}
-
treePath := chi.URLParam(r, "*")
ref := chi.URLParam(r, "ref")
···
writeError(w, err.Error(), http.StatusInternalServerError)
return
}
-
data := make(map[string]any)
-
data["ref"] = ref
-
data["desc"] = getDescription(path)
-
data["path"] = treePath
-
safe := sanitize([]byte(contents))
-
if raw {
-
h.showRaw(string(safe), w)
-
} else {
-
h.showFile(string(safe), data, w, l)
}
}
func (h *Handle) Archive(w http.ResponseWriter, r *http.Request) {
···
},
Tag: tag.TagObject(),
}
rtags = append(rtags, &tr)
}
···
DotDot: filepath.Dir(treePath),
Files: files,
}
writeJSON(w, resp)
return
}
+
func (h *Handle) Blob(w http.ResponseWriter, r *http.Request) {
treePath := chi.URLParam(r, "*")
ref := chi.URLParam(r, "ref")
···
writeError(w, err.Error(), http.StatusInternalServerError)
return
}
+
safe := string(sanitize([]byte(contents)))
+
resp := types.RepoBlobResponse{
+
Ref: ref,
+
Contents: string(safe),
+
Path: treePath,
}
+
+
h.showFile(resp, w, l)
}
func (h *Handle) Archive(w http.ResponseWriter, r *http.Request) {
···
},
Tag: tag.TagObject(),
}
+
+
if tag.Message() != "" {
+
tr.Message = tag.Message()
+
}
+
rtags = append(rtags, &tr)
}
+8
types/repo.go
···
type RepoBranchesResponse struct {
Branches []Branch `json:"branches,omitempty"`
}
···
type RepoBranchesResponse struct {
Branches []Branch `json:"branches,omitempty"`
}
+
+
type RepoBlobResponse struct {
+
Contents string `json:"contents,omitempty"`
+
Ref string `json:"ref,omitempty"`
+
Path string `json:"path,omitempty"`
+
+
Lines int `json:"lines,omitempty"`
+
}
+5 -5
types/tree.go
···
// A nicer git tree representation.
type NiceTree struct {
-
Name string
-
Mode string
-
Size int64
-
IsFile bool
-
IsSubtree bool
}
···
// A nicer git tree representation.
type NiceTree struct {
+
Name string `json:"name"`
+
Mode string `json:"mode"`
+
Size int64 `json:"size"`
+
IsFile bool `json:"is_file"`
+
IsSubtree bool `json:"is_subtree"`
}