Changes
4 changed files (+47/-463)
-
-
@@ -5,15 +5,46 @@... }: let legit-web = pkgs.legit-web.overrideAttrs (old: { src = pkgs.fetchFromGitHub { owner = "pocka"; repo = "legit"; rev = "master"; hash = "sha256-qykExM7lMLR0kg/vgcNrWBjZZAw6Sv6iraq9Iu7R4FI="; }; vendorHash = "sha256-qSnRQIuHnUQit21232SsMY0LQVvcy0PqBPQVPjsNJWA="; nativeCheckInputs = [ pkgs.git ]; postInstall = ""; }); # Don't use services.legit.settings because of its rigid schema legit-yaml = (pkgs.formats.yaml { }).generate "legit.yaml" { meta = { title = "Typeclass instance problem is stuck"; description = "It is often due to incompetence"; syntaxHighlight = true; }; repo = { mainBranch = [ "main" "master" ]; readme = [ "README.md" ]; scanPath = "/srv/git"; }; server = { name = "git.unnamed.website"; host = "localhost"; port = 5555; }; ui.footer.poweredBy = true; }; in { # Use lower IO priority for Nix so my server is still responsive while getting nix-copy-closured # Use lower IO priority for Nix so my server is still responsive while GCing nix.daemonIOSchedClass = "idle"; nixpkgs = { hostPlatform = "x86_64-linux"; # Overlays! Fixed points! overlays = [ (import ./overlays.nix) ]; }; nixpkgs.hostPlatform = "x86_64-linux"; # https://unnamed.website/posts/nixvm/ disko.devices.disk.main = {
-
@@ -152,24 +183,14 @@}; # Git server services.legit = { enable = true; settings = { meta = { title = "Typeclass instance problem is stuck"; description = "It is often due to incompetence"; }; repo = { readme = [ "README.md" ]; scanPath = "/srv/git"; }; server.name = "git.unnamed.website"; }; }; services.legit.enable = true; systemd = { # Fix error when git cloning services.legit.path = [ pkgs.git ]; services.legit = { # Fix error when git cloning path = [ pkgs.git ]; # Use custom config file serviceConfig.ExecStart = lib.mkForce "${legit-web}/bin/legit -config ${legit-yaml}"; }; # Update Git mirrors services.update-mirrors = { wantedBy = [ "multi-user.target" ];
-
-
Unnamed-Server/legit.patch (deleted)
-
@@ -1,416 +0,0 @@diff --git a/git/git.go b/git/git.go index d55460f..768966a 100644 --- a/git/git.go +++ b/git/git.go @@ -143,13 +143,7 @@ func (g *GitRepo) FileContent(path string) (string, error) { return "", err } - isbin, _ := file.IsBinary() - - if !isbin { - return file.Contents() - } else { - return "Not displaying binary file", nil - } + return file.Contents() } func (g *GitRepo) Tags() ([]*TagReference, error) { diff --git a/go.mod b/go.mod index 9491e43..bc6a398 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/pocka/legit -go 1.22.0 +go 1.25 require ( - github.com/alecthomas/chroma/v2 v2.14.0 + github.com/alecthomas/chroma/v2 v2.27.0 github.com/bluekeyes/go-gitdiff v0.8.0 github.com/cyphar/filepath-securejoin v0.4.1 github.com/dustin/go-humanize v1.0.1 @@ -20,7 +20,7 @@ require ( github.com/acomagu/bufpipe v1.0.4 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/cloudflare/circl v1.6.0 // indirect - github.com/dlclark/regexp2 v1.11.4 // indirect + github.com/dlclark/regexp2/v2 v2.2.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect diff --git a/go.sum b/go.sum index f8ba6ba..6a89c93 100644 --- a/go.sum +++ b/go.sum @@ -6,12 +6,12 @@ github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE= -github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E= -github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs= +github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8= +github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= +github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -30,8 +30,8 @@ github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGL github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= -github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2/v2 v2.2.1 h1:mf4KkFUj0gJuarK8P+LgiS+Lit7m9N1yAwEfPbee7R0= +github.com/dlclark/regexp2/v2 v2.2.1/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= diff --git a/routes/handler.go b/routes/handler.go index 5544767..2ecd2f8 100644 --- a/routes/handler.go +++ b/routes/handler.go @@ -1,7 +1,9 @@ package routes import ( + "html/template" "net/http" + "path/filepath" "github.com/pocka/legit/config" ) @@ -30,7 +32,11 @@ func (d *deps) Multiplex(w http.ResponseWriter, r *http.Request) { func Handlers(c *config.Config) *http.ServeMux { mux := http.NewServeMux() - d := deps{c} + + tpath := filepath.Join(c.Dirs.Templates, "*") + t := template.Must(template.ParseGlob(tpath)) + + d := deps{c, t} mux.HandleFunc("GET /", d.Index) mux.HandleFunc("GET /static/{file}", d.ServeStatic) diff --git a/routes/preview/renderer.go b/routes/preview/renderer.go index 10ea2ec..c0701f9 100644 --- a/routes/preview/renderer.go +++ b/routes/preview/renderer.go @@ -20,12 +20,13 @@ type Renderer interface { type MarkdownToHtmlRenderer struct{} +var sanitizer = bluemonday.UGCPolicy() + func (r MarkdownToHtmlRenderer) GetPreviewType() string { return "html" } func (r MarkdownToHtmlRenderer) Render(code []byte) ([]byte, error) { - sanitizer := bluemonday.UGCPolicy() unsafe := blackfriday.Run(code, blackfriday.WithExtensions(blackfriday.CommonExtensions)) return sanitizer.SanitizeBytes(unsafe), nil } diff --git a/routes/routes.go b/routes/routes.go index 71a0d67..5aacc95 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -25,8 +25,11 @@ import ( type deps struct { c *config.Config + t *template.Template } +var ugcPolicy = bluemonday.UGCPolicy() + func (d *deps) Index(w http.ResponseWriter, r *http.Request) { dirs, err := os.ReadDir(d.c.Repo.ScanPath) if err != nil { @@ -76,15 +79,12 @@ func (d *deps) Index(w http.ResponseWriter, r *http.Request) { return summaries[j].LastCommit.Committer.When.Before(summaries[i].LastCommit.Committer.When) }) - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - data := repoListData{ Config: d.c, Repositories: summaries, } - if err := t.ExecuteTemplate(w, "repo-list", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-list", data); err != nil { log.Println(err) return } @@ -138,7 +138,7 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { return blackfriday.GoToNext } - if node.Type == blackfriday.Link { + if node.Type == blackfriday.Link || node.Type == blackfriday.Image { href := string(node.LinkData.Destination) parsedURL, err := url.Parse(href) if err == nil && parsedURL.Host != "" { @@ -151,7 +151,9 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { href = "." + href } - if strings.LastIndexByte(href, '/') == len(href)-1 { + if node.Type == blackfriday.Image { + node.LinkData.Destination = fmt.Appendf([]byte{}, "/%s/blob/%s/%s?raw=true", name, mainBranch, href) + } else if strings.LastIndexByte(href, '/') == len(href)-1 { node.LinkData.Destination = fmt.Appendf([]byte{}, "/%s/tree/%s/%s", name, mainBranch, href) node.LinkData.Destination = node.LinkData.Destination[:len(node.LinkData.Destination)-1] } else { @@ -175,10 +177,10 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { writer.Bytes(), blackfriday.WithExtensions(blackfriday.CommonExtensions), ) - html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) + html := ugcPolicy.SanitizeBytes(unsafe) readmeContent = template.HTML(html) default: - safe := bluemonday.UGCPolicy().SanitizeBytes([]byte(content)) + safe := ugcPolicy.SanitizeBytes([]byte(content)) readmeContent = template.HTML( fmt.Sprintf(`<pre>%s</pre>`, safe), ) @@ -188,12 +190,10 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { } if readmeContent == "" { + readmeContent = template.HTML(fmt.Sprintf("no readme found for %s", name)) log.Printf("no readme found for %s", name) } - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - if len(commits) >= 3 { commits = commits[:3] } @@ -212,7 +212,7 @@ func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { IsGoModule: isGoModule(gr), } - if err := t.ExecuteTemplate(w, "repo-top", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-top", data); err != nil { log.Println(err) return } @@ -266,10 +266,7 @@ func (d *deps) RepoTree(w http.ResponseWriter, r *http.Request) { Files: files, } - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - - if err := t.ExecuteTemplate(w, "repo-tree-ref", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-tree-ref", data); err != nil { log.Println(err) return } @@ -330,9 +327,6 @@ func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) { relpath = strings.Split(treePath, "/") } - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - if r.URL.Query().Has("preview") { previewType := r.URL.Query().Get("preview") @@ -359,7 +353,7 @@ func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) { Content: template.HTML(html), } - if err := t.ExecuteTemplate(w, "repo-blob-ref-html-preview", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-blob-ref-html-preview", data); err != nil { log.Println(err) return } @@ -404,16 +398,14 @@ func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) { PreviewTypes: previewTypes, } - if d.c.Meta.SyntaxHighlight { - highlighted, err := highlightCode(treePath, contents) - if err != nil { - log.Println(err) - } else { - data.SyntaxHighlightedContent = highlighted - } + highlighted, err := highlightCode(treePath, contents) + if err != nil { + log.Println(err) + } else { + data.SyntaxHighlightedContent = highlighted } - if err := t.ExecuteTemplate(w, "repo-blob-ref", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-blob-ref", data); err != nil { log.Println(err) return } @@ -506,9 +498,6 @@ func (d *deps) Log(w http.ResponseWriter, r *http.Request) { return } - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - data := repoLogRefData{ Config: d.c, Meta: repositoryMeta{ @@ -520,7 +509,7 @@ func (d *deps) Log(w http.ResponseWriter, r *http.Request) { Commits: commits, } - if err := t.ExecuteTemplate(w, "repo-log-ref", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-log-ref", data); err != nil { log.Println(err) return } @@ -553,9 +542,6 @@ func (d *deps) Diff(w http.ResponseWriter, r *http.Request) { return } - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - data := repoCommitData{ Config: d.c, Meta: repositoryMeta{ @@ -569,7 +555,7 @@ func (d *deps) Diff(w http.ResponseWriter, r *http.Request) { Diff: diff, } - if err := t.ExecuteTemplate(w, "repo-commit", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-commit", data); err != nil { log.Println(err) return } @@ -615,9 +601,6 @@ func (d *deps) Refs(w http.ResponseWriter, r *http.Request) { return } - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - data := repoRefsData{ Config: d.c, Meta: repositoryMeta{ @@ -630,7 +613,7 @@ func (d *deps) Refs(w http.ResponseWriter, r *http.Request) { Branches: branches, } - if err := t.ExecuteTemplate(w, "repo-refs", data); err != nil { + if err := d.t.ExecuteTemplate(w, "repo-refs", data); err != nil { log.Println(err) return } diff --git a/routes/template.go b/routes/template.go index d83ce06..9e0b51e 100644 --- a/routes/template.go +++ b/routes/template.go @@ -1,36 +1,28 @@ package routes import ( - "html/template" "log" "net/http" - "path/filepath" ) func (d *deps) Write404(w http.ResponseWriter) { - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - data := error404Data{ Config: d.c, } w.WriteHeader(404) - if err := t.ExecuteTemplate(w, "404", data); err != nil { + if err := d.t.ExecuteTemplate(w, "404", data); err != nil { log.Printf("404 template: %s", err) } } func (d *deps) Write500(w http.ResponseWriter) { - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - data := error500Data{ Config: d.c, } w.WriteHeader(500) - if err := t.ExecuteTemplate(w, "500", data); err != nil { + if err := d.t.ExecuteTemplate(w, "500", data); err != nil { log.Printf("500 template: %s", err) } } diff --git a/routes/util.go b/routes/util.go index 2b5b853..5b91553 100644 --- a/routes/util.go +++ b/routes/util.go @@ -90,6 +90,8 @@ func countLines(r io.Reader) (int, error) { } } +var formatter = html.New(html.WithClasses(true), html.ClassPrefix("chroma-")) + func highlightCode(fileName string, code string) (template.HTML, error) { lexer := lexers.Get(fileName) @@ -98,8 +100,6 @@ func highlightCode(fileName string, code string) (template.HTML, error) { return "", nil } - formatter := html.New(html.WithClasses(true), html.ClassPrefix("chroma-")) - iter, err := lexer.Tokenise(nil, code) if err != nil { return "", fmt.Errorf("Failed to tokenize code: %s", err) diff --git a/templates/repo-blob-ref.html.tmpl b/templates/repo-blob-ref.html.tmpl index a0876df..7518c2f 100644 --- a/templates/repo-blob-ref.html.tmpl +++ b/templates/repo-blob-ref.html.tmpl @@ -73,6 +73,10 @@ SPDX-License-Identifier: MIT <aside class="aside"> <dl class="metadata"> {{- template "tab-selector" -}} + <dt class="metadata--key">Raw</dt> + <dd class="metadata--value"> + <a href="?raw=true">View raw</a> + </dd> {{- range .PreviewTypes -}} <dt class="metadata--key">Preview (<span class="preview-type">{{ . }}</span>)</dt> <dd class="metadata--value"> diff --git a/templates/repo-list.html.tmpl b/templates/repo-list.html.tmpl index efb2c37..9f78372 100644 --- a/templates/repo-list.html.tmpl +++ b/templates/repo-list.html.tmpl @@ -18,6 +18,7 @@ SPDX-License-Identifier: MIT <div class="header-title"> <h1 class="header-title--name">{{ .Config.Meta.Title }}</h1> <p class="header-title--description">{{ .Config.Meta.Description }}</p> + <p class="header-title--description">Powered by <a href="https://git.pocka.jp/legit.git">pocka/legit</a></p> </div> </header> <main class="main">
-
-
Unnamed-Server/overlays.nix (deleted)
-
@@ -1,21 +0,0 @@final: prev: { legit-web = prev.legit-web.overrideAttrs (old: { src = prev.fetchFromGitHub { owner = "pocka"; repo = "legit"; rev = "master"; hash = "sha256-Z7pDdIvJXfSCGFxhOxSL1dBVjgHnC5P6Wa7AsQ9t6CY="; }; vendorHash = "sha256-GR+ddG6058s9NDGwbk2z86vcOIa11DUQqP6tS0ruUdo="; # Use a patch instead of a repo hosted on this server to avoid a circular dependency patches = (old.patches or [ ]) ++ [ ./legit.patch ]; # The package in nixpkgs is a huge mess and has tons of mistakes postInstall = '' mkdir -p $out/lib/legit/templates mkdir -p $out/lib/legit/static cp -r templates/* $out/lib/legit/templates cp -r static/* $out/lib/legit/static ''; }); }
-
-
-
@@ -43,11 +43,11 @@}, "nixpkgs": { "locked": { "lastModified": 1783522502, "narHash": "sha256-iffAls3iaNTyJC2faYcUXSI+Gp02cDjYl+MygxKl2GI=", "lastModified": 1783776592, "narHash": "sha256-UgCQzxeWI75XM8G+hPrPh+MKzEPjG3SpAj7dtqSbksA=", "owner": "NixOS", "repo": "nixpkgs", "rev": "0bb7ec54c8483066ec9d7720e780a5caa71f8612", "rev": "e7a3ca8092b61ff85b6a45bf863ea2b2d6a661b3", "type": "github" }, "original": {
-