git-pr
created pr with
ps-3
added ps-4
1: 3b99dc0 < -: ------- feat: static assets
2: 8919af5 ! 1: 66cafc6 feat: static assets folder
3: 7346122 ! 2: 5e76ed3 fix(cli): access control for removing patchsets
4: d8792d5 < -: ------- feat: static folder
pr_reviewed
changed status to
reviewed
added ps-9
1: cc56ea1 = 1: 0467f9e feat: static assets folder
2: ef749a4 = 2: da1730f review: typo and future enhancement comment
-: ------- > 3: c038404 refactor: per-file override for static folder
changed status to
accepted
cmds
checkout latest patchset:
ssh pr.pico.sh print pr-3 | git am -3checkout any patchset in a patch request:
ssh pr.pico.sh print ps-X | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 3set PR to open (enables RSS notifications):
ssh pr.pico.sh pr open 3set PR to draft (stops RSS notifications):
ssh pr.pico.sh pr draft 3
Patchset
ps-3
feat: static assets
Eric Bower
2024-07-19T04:27:17ZSemantic diff summary
3 added,
3 modified,
0 signature changed,
0 removed
across 1 analyzed file
(1 file skipped: unsupported file type)
+4
-0
Makefile
#
@@ -26,3 +26,7 @@ bp: bp-setup
$(DOCKER_BUILDX_BUILD) -t "ghcr.io/picosh/pico/git-ssh:$(DOCKER_TAG)" --target release-ssh .
$(DOCKER_BUILDX_BUILD) -t "ghcr.io/picosh/pico/git-web:$(DOCKER_TAG)" --target release-web .
.PHONY: bp
+
+smol:
+ curl https://pico.sh/smol.css -o ./static/smol.css
+.PHONY: smol
+57
-0
web.go
#
@@ -6,8 +6,11 @@ import (
"embed"
"fmt"
"html/template"
+ "io"
+ "io/fs"
"log/slog"
"net/http"
+ "os"
"path/filepath"
"slices"
"strconv"
@@ -23,6 +26,9 @@ import (
//go:embed tmpl/*
var tmplFS embed.FS
+//go:embed static/*
+var staticFS embed.FS
+
type WebCtx struct {
Pr *PrCmd
Backend *Backend
@@ -618,6 +624,49 @@ func chromaStyleHandler(w http.ResponseWriter, r *http.Request) {
}
}
+func serveFile(staticfs fs.FS) func(w http.ResponseWriter, r *http.Request) {
+ return func(w http.ResponseWriter, r *http.Request) {
+ web, err := getWebCtx(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnprocessableEntity)
+ return
+ }
+ logger := web.Logger
+
+ file := r.PathValue("file")
+ reader, err := staticfs.Open(file)
+ if err != nil {
+ logger.Error(err.Error())
+ http.Error(w, "file not found", 404)
+ return
+ }
+ contents, err := io.ReadAll(reader)
+ if err != nil {
+ logger.Error(err.Error())
+ http.Error(w, "file not found", 404)
+ return
+ }
+ contentType := http.DetectContentType(contents)
+ w.Header().Add("Content-Type", contentType)
+
+ _, err = w.Write(contents)
+ if err != nil {
+ logger.Error(err.Error())
+ http.Error(w, "server error", 500)
+ return
+ }
+ }
+}
+
+type StaticFs struct {
+ Dir string
+}
+
+func (fs *StaticFs) Open(name string) (os.File, error) {
+ fp, err := os.Open(filepath.Join(fs.Dir, name))
+ return *fp, err
+}
+
func StartWebServer(cfg *GitCfg) {
addr := fmt.Sprintf("%s:%s", cfg.Host, cfg.WebPort)
@@ -659,6 +708,14 @@ func StartWebServer(cfg *GitCfg) {
http.HandleFunc("GET /", ctxMdw(ctx, repoListHandler))
http.HandleFunc("GET /syntax.css", ctxMdw(ctx, chromaStyleHandler))
http.HandleFunc("GET /rss", ctxMdw(ctx, rssHandler))
+ dir := filepath.Join(cfg.DataDir, "static")
+ var filesys fs.FS = staticFS
+ _, err = os.Stat(dir)
+ if err == nil {
+ cfg.Logger.Info("detected static folder, using instead of the default one")
+ filesys = os.DirFS(dir)
+ }
+ http.HandleFunc("GET /static/{file}", serveFile(filesys))
cfg.Logger.Info("starting web server", "addr", addr)
err = http.ListenAndServe(addr, nil)