add raw file routes and allow readme to reference relative repo paths
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmPZo9oACgkQO3+8IhRO Y5jW/Q/+M740eWMsKRYBaHdtRSzgCYPYG9wpTc3CklDIVpKhsXLy3vNpJlIjmXrb CPA7U3wlWVYXe5jPeeDCME21++98HsEULgldZI2HMWFN7jy+x9S4mEjkrkJHDnFc pJL5LqlKayIxsH150bHoUKKFQ8xk6DlbYSgoNqk/wCWz7EADnRsREJh2ZFTRLd3K nVb1G8ZS/yTeeXA7acz1mhwgUlIKy1TrsDLbnPHzwJW7ipJyB2wykl6kC477z5lt buWJmbG4jdFZqr3pVXf7h0VUasTet5e2RTNqLupIP/O6hv6g2jfQKFRTwzhYFJ3n Pmu1UdF2+MKP8AnDnvy8nHE8PG0GQM5RdfDVu2pqxy8dE7FuEt1RMGve16oDVfgE rFaO9RpWBqlqS5rBWwd5hCcj7cuRUPFE7RrPHKysaHyJjoKjw7CGEBQNDPtj4tZI Nm0tQ4hP7VlmBsT7IcktKXRt+LHblhglKElgVdmJNw0gjlJPrz88cBhleuBK6ZYq g9omxttBMidvUQawYtAzSva8hhiQV+A/FbNbSDL9/LunVqDdHs1R4p3xT8MYmZPv yJS+RSS+dPObkzMTXHgjv9alTvgk3nbY3TzyyLZx035HlkXFu+aOUyNmF+76GLsh 2korFNOf/J5phEgcv1O55pyb8ZaCatM6/u8eHHQUuoVaEwT8qAM= =rJ6S -----END PGP SIGNATURE-----
6 files changed,
47 insertions(+),
14 deletions(-)
M
git/git.go
→
git/git.go
@@ -60,7 +60,7 @@ }
return c, nil } -func (g *GitRepo) FileContent(path string) (string, error) { +func (g *GitRepo) FileContent(path string, showBinary bool) (string, error) { c, err := g.r.CommitObject(g.h) if err != nil { return "", fmt.Errorf("commit object: %w", err)@@ -78,7 +78,7 @@ }
isbin, _ := file.IsBinary() - if !isbin { + if showBinary || !isbin { return file.Contents() } else { return "Not displaying binary file", nil
M
routes/handler.go
→
routes/handler.go
@@ -41,6 +41,7 @@ mux.HandleFunc("/", d.Index, "GET")
mux.HandleFunc("/static/:file", d.ServeStatic, "GET") mux.HandleFunc("/:name", d.Multiplex, "GET", "POST") mux.HandleFunc("/:name/tree/:ref/...", d.RepoTree, "GET") + mux.HandleFunc("/:name/blob/raw/:ref/...", d.ServeStaticInRepo, "GET") mux.HandleFunc("/:name/blob/:ref/...", d.FileContent, "GET") mux.HandleFunc("/:name/log/:ref", d.Log, "GET") mux.HandleFunc("/:name/commit/:ref", d.Diff, "GET")
M
routes/routes.go
→
routes/routes.go
@@ -1,6 +1,7 @@
package routes import ( + "bytes" "fmt" "html/template" "log"@@ -97,6 +98,13 @@ d.Write404(w)
return } + mainBranch, err := gr.FindMainBranch(d.c.Repo.MainBranch) + if err != nil { + d.Write500(w) + log.Println(err) + return + } + commits, err := gr.Commits() if err != nil { d.Write500(w)@@ -107,7 +115,7 @@
var readmeContent template.HTML for _, readme := range d.c.Repo.Readme { ext := filepath.Ext(readme) - content, _ := gr.FileContent(readme) + content, _ := gr.FileContent(readme, false) if len(content) > 0 { switch ext { case ".md", ".mkd", ".markdown":@@ -116,7 +124,7 @@ []byte(content),
blackfriday.WithExtensions(blackfriday.CommonExtensions), ) html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) - readmeContent = template.HTML(html) + readmeContent = template.HTML(transformRelativeURLs(string(html), name, mainBranch)) default: readmeContent = template.HTML( fmt.Sprintf(`<pre>%s</pre>`, content),@@ -128,13 +136,6 @@ }
if readmeContent == "" { log.Printf("no readme found for %s", name) - } - - mainBranch, err := gr.FindMainBranch(d.c.Repo.MainBranch) - if err != nil { - d.Write500(w) - log.Println(err) - return } tpath := filepath.Join(d.c.Dirs.Templates, "*")@@ -212,12 +213,13 @@ d.Write404(w)
return } - contents, err := gr.FileContent(treePath) + contents, err := gr.FileContent(treePath, false) data := make(map[string]any) data["name"] = name data["ref"] = ref data["desc"] = getDescription(path) data["path"] = treePath + data["raw"] = fmt.Sprintf("/%s/blob/raw/%s/%s", name, ref, treePath) d.showFile(contents, data, w) return@@ -344,6 +346,26 @@ if err := t.ExecuteTemplate(w, "refs", data); err != nil {
log.Println(err) return } +} + +func (d *deps) ServeStaticInRepo(w http.ResponseWriter, r *http.Request) { + f := flow.Param(r.Context(), "...") + p := flow.Param(r.Context(), "name") + ref := flow.Param(r.Context(), "ref") + + repoPath := filepath.Clean(filepath.Join(d.c.Repo.ScanPath, p)) + gr, err := git.Open(repoPath, ref) + if err != nil { + d.Write500(w) + return + } + + contents, err := gr.FileContent(f, true) + if err != nil { + d.Write500(w) + return + } + http.ServeContent(w, r, filepath.Base(f), time.Unix(0, 0), bytes.NewReader([]byte(contents))) } func (d *deps) ServeStatic(w http.ResponseWriter, r *http.Request) {
M
routes/util.go
→
routes/util.go
@@ -1,14 +1,16 @@
package routes import ( + "fmt" "os" "path/filepath" + "strings" "git.icyphox.sh/legit/git" ) func isGoModule(gr *git.GitRepo) bool { - _, err := gr.FileContent("go.mod") + _, err := gr.FileContent("go.mod", false) return err == nil }@@ -20,6 +22,13 @@ } else {
desc = "" } return +} + +func transformRelativeURLs(html, repoName, mainBranch string) string { + return strings.ReplaceAll( + html, + "=\"./", + fmt.Sprintf("=\"/%s/blob/raw/%s/", repoName, mainBranch)) } func (d *deps) isIgnored(name string) bool {
M
static/style.css
→
static/style.css
@@ -247,6 +247,7 @@ grid-template-columns: 1rem minmax(0, 1fr);
gap: 1rem; padding: 0.5rem; background: var(--light-gray); + margin-top: 0.5rem; } .file-content {
M
templates/file.html
→
templates/file.html
@@ -7,7 +7,7 @@ {{ template "repoheader" . }}
<body> {{ template "nav" . }} <main> - <p>{{ .path }}</p> + <p>{{ .path }} (<a href="{{ .raw }}">raw</a>)</p> <div class="file-wrapper"> <div class="line-numbers"> {{- range .linecount }}