From 7d3fed52adb19e535569da2720969eb8b15ee378 Mon Sep 17 00:00:00 2001 From: Derek Stevens Date: Tue, 31 Jan 2023 16:27:22 -0700 Subject: [PATCH] add raw file routes and allow readme to reference relative repo paths --- git/git.go | 4 ++-- routes/handler.go | 1 + routes/routes.go | 42 ++++++++++++++++++++++++++++++++---------- routes/util.go | 11 ++++++++++- static/style.css | 1 + templates/file.html | 2 +- 6 files changed, 47 insertions(+), 14 deletions(-) diff --git a/git/git.go b/git/git.go index 34e8a80..806a02a 100644 --- a/git/git.go +++ b/git/git.go @@ -60,7 +60,7 @@ func (g *GitRepo) LastCommit() (*object.Commit, error) { 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 @@ func (g *GitRepo) FileContent(path string) (string, error) { isbin, _ := file.IsBinary() - if !isbin { + if showBinary || !isbin { return file.Contents() } else { return "Not displaying binary file", nil diff --git a/routes/handler.go b/routes/handler.go index a0e7832..52d6e4e 100644 --- a/routes/handler.go +++ b/routes/handler.go @@ -41,6 +41,7 @@ func Handlers(c *config.Config) *flow.Mux { 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") diff --git a/routes/routes.go b/routes/routes.go index 4d99ab0..a16f0de 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -1,6 +1,7 @@ package routes import ( + "bytes" "fmt" "html/template" "log" @@ -97,6 +98,13 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { 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 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { 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 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { 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(`
%s
`, content), @@ -130,13 +138,6 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { 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, "*") t := template.Must(template.ParseGlob(tpath)) @@ -212,12 +213,13 @@ func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) { 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 @@ -346,6 +348,26 @@ func (d *deps) Refs(w http.ResponseWriter, r *http.Request) { } } +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) { f := flow.Param(r.Context(), "file") f = filepath.Clean(filepath.Join(d.c.Dirs.Static, f)) diff --git a/routes/util.go b/routes/util.go index e6a6267..3536946 100644 --- a/routes/util.go +++ b/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 } @@ -22,6 +24,13 @@ func getDescription(path string) (desc string) { 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 { for _, i := range d.c.Repo.Ignore { if name == i { diff --git a/static/style.css b/static/style.css index 19c0891..3f2640c 100644 --- a/static/style.css +++ b/static/style.css @@ -247,6 +247,7 @@ a:hover { gap: 1rem; padding: 0.5rem; background: var(--light-gray); + margin-top: 0.5rem; } .file-content { diff --git a/templates/file.html b/templates/file.html index ab432d3..699b1b1 100644 --- a/templates/file.html +++ b/templates/file.html @@ -7,7 +7,7 @@ {{ template "nav" . }}
-

{{ .path }}

+

{{ .path }} (raw)

{{- range .linecount }}