- commit
- ca79cbc
- parent
- eeae06c
- author
- Antonio Mika
- date
- 2022-08-31 21:24:07 +0000 UTC
Work on optimizing imgs.sh
8 files changed,
+122,
-79
M
Makefile
+1,
-1
1@@ -18,7 +18,7 @@ css:
2 .PHONY: css
3
4 lint:
5- docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:latest golangci-lint run -E goimports -E godot
6+ docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:latest bash -c 'apt-get update > /dev/null 2>&1 && apt-get install -y libwebp-dev > /dev/null 2>&1; golangci-lint run -E goimports -E godot'
7 .PHONY: lint
8
9 bp-setup:
+1,
-1
1@@ -15,7 +15,7 @@ import (
2 "git.sr.ht/~erock/pico/wish/cms/util"
3 "git.sr.ht/~erock/pico/wish/send/utils"
4 "github.com/gliderlabs/ssh"
5- "github.com/scottleedavis/go-exif-remove"
6+ exifremove "github.com/scottleedavis/go-exif-remove"
7 "golang.org/x/exp/slices"
8 )
9
+3,
-1
1@@ -1,7 +1,9 @@
2 package uploadimgs
3
4 import (
5+ "bytes"
6 "fmt"
7+ "io"
8 "strings"
9
10 "git.sr.ht/~erock/pico/db"
11@@ -40,7 +42,7 @@ func (h *UploadImgHandler) metaImg(data *PostMetaData) error {
12 if err != nil {
13 return err
14 }
15- fname, err := h.Storage.PutFile(bucket, data.Filename, []byte(data.Text))
16+ fname, err := h.Storage.PutFile(bucket, data.Filename, io.NopCloser(bytes.NewReader([]byte(data.Text))))
17 if err != nil {
18 return err
19 }
M
go.mod
+19,
-14
1@@ -7,7 +7,7 @@ go 1.19
2
3 require (
4 github.com/alecthomas/chroma v0.10.0
5- github.com/antoniomika/go-rsync-receiver v0.0.0-20220825041817-0387edc9afb7
6+ github.com/antoniomika/go-rsync-receiver v0.0.0-20220825051444-e2df2a87b439
7 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
8 github.com/charmbracelet/bubbles v0.13.0
9 github.com/charmbracelet/bubbletea v0.22.1
10@@ -20,7 +20,7 @@ require (
11 github.com/lib/pq v1.10.6
12 github.com/matryer/is v1.4.0
13 github.com/microcosm-cc/bluemonday v1.0.19
14- github.com/minio/minio-go/v7 v7.0.34
15+ github.com/minio/minio-go/v7 v7.0.35
16 github.com/muesli/reflow v0.3.0
17 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
18 github.com/pkg/sftp v1.13.5
19@@ -29,8 +29,8 @@ require (
20 github.com/yuin/goldmark-highlighting v0.0.0-20220208100518-594be1970594
21 github.com/yuin/goldmark-meta v1.1.0
22 go.uber.org/zap v1.23.0
23- golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503
24- golang.org/x/exp v0.0.0-20220823124025-807a23277127
25+ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
26+ golang.org/x/exp v0.0.0-20220827204233-334a2380cb91
27 )
28
29 require (
30@@ -44,20 +44,25 @@ require (
31 github.com/charmbracelet/keygen v0.3.0 // indirect
32 github.com/containerd/console v1.0.3 // indirect
33 github.com/dlclark/regexp2 v1.7.0 // indirect
34- github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f // indirect
35- github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 // indirect
36- github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 // indirect
37- github.com/dsoprea/go-png-image-structure v0.0.0-20190624104353-c9b28dcdc5c8 // indirect
38+ github.com/dsoprea/go-exif v0.0.0-20210625224831-a6301f85c82b // indirect
39+ github.com/dsoprea/go-exif/v2 v2.0.0-20210625224831-a6301f85c82b // indirect
40+ github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 // indirect
41+ github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210512043942-b434301c6836 // indirect
42+ github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
43+ github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d // indirect
44+ github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d // indirect
45+ github.com/dsoprea/go-utility v0.0.0-20200717064901-2fccff4aa15e // indirect
46 github.com/dustin/go-humanize v1.0.0 // indirect
47- github.com/go-errors/errors v1.0.1 // indirect
48- github.com/golang/geo v0.0.0-20190812012225-f41920e961ce // indirect
49+ github.com/go-errors/errors v1.4.2 // indirect
50+ github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
51+ github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
52 github.com/golang/protobuf v1.5.2 // indirect
53 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
54 github.com/google/uuid v1.3.0 // indirect
55 github.com/gorilla/css v1.0.0 // indirect
56 github.com/json-iterator/go v1.1.12 // indirect
57 github.com/klauspost/compress v1.15.9 // indirect
58- github.com/klauspost/cpuid/v2 v2.1.0 // indirect
59+ github.com/klauspost/cpuid/v2 v2.1.1 // indirect
60 github.com/kr/fs v0.1.0 // indirect
61 github.com/kr/pretty v0.3.0 // indirect
62 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
63@@ -83,11 +88,11 @@ require (
64 github.com/sirupsen/logrus v1.9.0 // indirect
65 go.uber.org/atomic v1.10.0 // indirect
66 go.uber.org/multierr v1.8.0 // indirect
67- golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c // indirect
68- golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 // indirect
69+ golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
70+ golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
71 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
72 golang.org/x/text v0.3.7 // indirect
73 google.golang.org/protobuf v1.28.1 // indirect
74- gopkg.in/ini.v1 v1.66.6 // indirect
75+ gopkg.in/ini.v1 v1.67.0 // indirect
76 gopkg.in/yaml.v2 v2.4.0 // indirect
77 )
M
go.sum
+55,
-22
1@@ -44,8 +44,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
2 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
3 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
4 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
5-github.com/antoniomika/go-rsync-receiver v0.0.0-20220825041817-0387edc9afb7 h1:CECWxPqxYAwjlUQxEeuaqnjlTsOsaAMfu6f27xHswm0=
6-github.com/antoniomika/go-rsync-receiver v0.0.0-20220825041817-0387edc9afb7/go.mod h1:zmqePVIo1hp+WEKxERLLGHJBDOr8/z/T4eFqXgWIw1w=
7+github.com/antoniomika/go-rsync-receiver v0.0.0-20220825051444-e2df2a87b439 h1:5AjhKkEyKSn81jZXXSX/Mob3hLNUfP4Dyo49vyITQQI=
8+github.com/antoniomika/go-rsync-receiver v0.0.0-20220825051444-e2df2a87b439/go.mod h1:zmqePVIo1hp+WEKxERLLGHJBDOr8/z/T4eFqXgWIw1w=
9 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
10 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
11 github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
12@@ -91,14 +91,35 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
13 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
14 github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
15 github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
16-github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f h1:vqfYiZ+xF0xJvl9SZ1kovmMgKjaGZIz/Hn8JDQdyd9A=
17 github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f/go.mod h1:DmMpU91/Ax6BAwoRkjgRCr2rmgEgS4tsmatfV7M+U+c=
18-github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 h1:9zARagUAxQJjibcDy+0+koUMR6sbX38L49Bk2Vni628=
19+github.com/dsoprea/go-exif v0.0.0-20210625224831-a6301f85c82b h1:hoVHc4m/v8Al8mbWyvKJWr4Z37yM4QUSVh/NY6A5Sbc=
20+github.com/dsoprea/go-exif v0.0.0-20210625224831-a6301f85c82b/go.mod h1:lOaOt7+UEppOgyvRy749v3do836U/hw0YVJNjoyPaEs=
21+github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
22+github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4/go.mod h1:9EXlPeHfblFFnwu5UOqmP2eoZfJyAZ2Ri/Vki33ajO0=
23+github.com/dsoprea/go-exif/v2 v2.0.0-20210625224831-a6301f85c82b h1:8lVRnnni9zebcpjkrEXrEyxFpRWG/oTpWc2Y3giKomE=
24+github.com/dsoprea/go-exif/v2 v2.0.0-20210625224831-a6301f85c82b/go.mod h1:oKrjk2kb3rAR5NbtSTLUMvMSbc+k8ZosI3MaVH47noc=
25+github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
26+github.com/dsoprea/go-exif/v3 v3.0.0-20210512043655-120bcdb2a55e/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
27+github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM=
28+github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 h1:YDRiMEm32T60Kpm35YzOK9ZHgjsS1Qrid+XskNcsdp8=
29+github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM=
30 github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48/go.mod h1:H1hAaFyv9cRV1ywoHvaqVoNSThBvWZ0JarRBcV+FSnE=
31-github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 h1:VGFnZAcLwPpt1sHlAxml+pGLZz9A2s+K/s1YNhPC91Y=
32+github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210512043942-b434301c6836 h1:OHRfKIVRz2XrhZ6A7fJKHLoKky1giN+VUgU2npF0BvE=
33+github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210512043942-b434301c6836/go.mod h1:6+tQXZ+I62x13UZ+hemLVoZIuq/usVzvau7bqwUo9P0=
34 github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
35-github.com/dsoprea/go-png-image-structure v0.0.0-20190624104353-c9b28dcdc5c8 h1:SVQfy5rBFZXzvGkU2MZ0RzpS912/1sJrEJ+FMmeaC9U=
36+github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
37+github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg=
38+github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
39+github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c/go.mod h1:pqKB+ijp27cEcrHxhXVgUUMlSDRuGJJp1E+20Lj5H0E=
40+github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d h1:dg6UMHa50VI01WuPWXPbNJpO8QSyvIF5T5n2IZiqX3A=
41+github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d/go.mod h1:pqKB+ijp27cEcrHxhXVgUUMlSDRuGJJp1E+20Lj5H0E=
42 github.com/dsoprea/go-png-image-structure v0.0.0-20190624104353-c9b28dcdc5c8/go.mod h1:Bf0nmcDFFRQBjZwr9qY6c0zTxKQa+Q8YWZmlYxXGxY0=
43+github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d h1:8+qI8ant/vZkNSsbwSjIR6XJfWcDVTg/qx/3pRUUZNA=
44+github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d/go.mod h1:yTR3tKgyk20phAFg6IE9ulMA5NjEDD2wyx+okRFLVtw=
45+github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
46+github.com/dsoprea/go-utility v0.0.0-20200717064901-2fccff4aa15e h1:ojqYA1mU6LuRm8XzrVOvyfb000y59cbUcu6Wt8sFSAs=
47+github.com/dsoprea/go-utility v0.0.0-20200717064901-2fccff4aa15e/go.mod h1:KVK+/Hul09ujXAGq+42UBgCTnXkiJZRnLYdURGjQUwo=
48+github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU=
49 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
50 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
51 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
52@@ -107,8 +128,11 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
53 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
54 github.com/gliderlabs/ssh v0.3.4 h1:+AXBtim7MTKaLVPgvE+3mhewYRawNLTd+jEEz/wExZw=
55 github.com/gliderlabs/ssh v0.3.4/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
56-github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
57 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
58+github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
59+github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
60+github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
61+github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
62 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
63 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
64 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
65@@ -121,9 +145,15 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
66 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
67 github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
68 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
69+github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
70+github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U=
71+github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
72 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
73-github.com/golang/geo v0.0.0-20190812012225-f41920e961ce h1:rqIKPpIcEgiNn0KYNFYD34TbMO86l4woyhNzSP+Oegs=
74 github.com/golang/geo v0.0.0-20190812012225-f41920e961ce/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
75+github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
76+github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
77+github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
78+github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
79 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
80 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
81 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
82@@ -188,6 +218,7 @@ github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBba
83 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
84 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
85 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
86+github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
87 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
88 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
89 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
90@@ -203,8 +234,8 @@ github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQan
91 github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
92 github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
93 github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
94-github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
95-github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
96+github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
97+github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
98 github.com/kolesa-team/go-webp v1.0.1 h1:Btojkbzr6tt10zJ40xlbSfJeHFiNn0aR7H03QUqmMoI=
99 github.com/kolesa-team/go-webp v1.0.1/go.mod h1:oMvdivD6K+Q5qIIkVC2w4k2ZUnI1H+MyP7inwgWq9aA=
100 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
101@@ -241,8 +272,8 @@ github.com/microcosm-cc/bluemonday v1.0.19 h1:OI7hoF5FY4pFz2VA//RN8TfM0YJ2dJcl4P
102 github.com/microcosm-cc/bluemonday v1.0.19/go.mod h1:QNzV2UbLK2/53oIIwTOyLUSABMkjZ4tqiyC1g/DyqxE=
103 github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
104 github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
105-github.com/minio/minio-go/v7 v7.0.34 h1:JMfS5fudx1mN6V2MMNyCJ7UMrjEzZzIvMgfkWc1Vnjk=
106-github.com/minio/minio-go/v7 v7.0.34/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
107+github.com/minio/minio-go/v7 v7.0.35 h1:JuPPxWLdxQmNLSaS8AWZnO5HBadeI1xg6FGrEELQEVU=
108+github.com/minio/minio-go/v7 v7.0.35/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
109 github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
110 github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
111 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
112@@ -362,8 +393,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
113 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
114 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
115 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
116-golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503 h1:vJ2V3lFLg+bBhgroYuRfyN583UzVveQmIXjc8T/y3to=
117-golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
118+golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
119+golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
120 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
121 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
122 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
123@@ -374,8 +405,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
124 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
125 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
126 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
127-golang.org/x/exp v0.0.0-20220823124025-807a23277127 h1:S4NrSKDfihhl3+4jSTgwoIevKxX9p7Iv9x++OEIptDo=
128-golang.org/x/exp v0.0.0-20220823124025-807a23277127/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
129+golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
130+golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
131 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
132 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
133 golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
134@@ -419,6 +450,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
135 golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
136 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
137 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
138+golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
139 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
140 golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
141 golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
142@@ -432,8 +464,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
143 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
144 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
145 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
146-golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes=
147-golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
148+golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=
149+golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
150 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
151 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
152 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
153@@ -495,8 +527,8 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc
154 golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
155 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
156 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
157-golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 h1:TyKJRhyo17yWxOMCTHKWrc5rddHORMlnZ/j57umaUd8=
158-golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
159+golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
160+golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
161 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
162 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
163 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
164@@ -639,12 +671,13 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
165 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
166 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
167 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
168-gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
169-gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
170+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
171+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
172 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
173 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
174 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
175 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
176+gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
177 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
178 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
179 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+24,
-22
1@@ -8,12 +8,16 @@ import (
2 gif "image/gif"
3 jpeg "image/jpeg"
4 png "image/png"
5+ "io"
6 "net/http"
7 "net/url"
8 "strconv"
9 "strings"
10 "time"
11
12+ "net/http/pprof"
13+ _ "net/http/pprof"
14+
15 "git.sr.ht/~erock/pico/db"
16 "git.sr.ht/~erock/pico/db/postgres"
17 "git.sr.ht/~erock/pico/imgs/storage"
18@@ -210,8 +214,7 @@ type ImgOptimizer struct {
19 Dimes string
20 }
21
22-func (h *ImgOptimizer) GetImage(contents []byte, mimeType string) (image.Image, error) {
23- r := bytes.NewReader(contents)
24+func (h *ImgOptimizer) GetImage(r io.Reader, mimeType string) (image.Image, error) {
25 switch mimeType {
26 case "image/png":
27 return png.Decode(r)
28@@ -275,14 +278,15 @@ type SubImager interface {
29 SubImage(r image.Rectangle) image.Image
30 }
31
32-func (h *ImgOptimizer) Process(contents []byte, mimeType string) ([]byte, error) {
33+func (h *ImgOptimizer) Process(contents io.Reader, writer io.Writer, mimeType string) error {
34 if !h.Optimized {
35- return contents, nil
36+ _, err := io.Copy(writer, contents)
37+ return err
38 }
39
40 img, err := h.GetImage(contents, mimeType)
41 if err != nil {
42- return []byte{}, err
43+ return err
44 }
45
46 nextImg := img
47@@ -295,19 +299,10 @@ func (h *ImgOptimizer) Process(contents []byte, mimeType string) ([]byte, error)
48 h.Quality,
49 )
50 if err != nil {
51- return []byte{}, err
52- }
53-
54- output := &bytes.Buffer{}
55- err = webp.Encode(output, nextImg, options)
56- if err != nil {
57- return []byte{}, err
58+ return err
59 }
60
61- if mimeType == "image/png" {
62- fmt.Println(output)
63- }
64- return output.Bytes(), nil
65+ return webp.Encode(writer, nextImg, options)
66 }
67
68 func NewImgOptimizer(logger *zap.SugaredLogger, optimized bool, dimes string) *ImgOptimizer {
69@@ -362,12 +357,14 @@ func imgHandler(w http.ResponseWriter, h *ImgHandler) {
70 http.Error(w, err.Error(), http.StatusInternalServerError)
71 return
72 }
73+
74 contents, err := h.Storage.GetFile(bucket, post.Filename)
75 if err != nil {
76 h.Logger.Infof("file not found %s/%s", h.Username, post.Filename)
77 http.Error(w, err.Error(), http.StatusInternalServerError)
78 return
79 }
80+ defer contents.Close()
81
82 if h.Img.Optimized {
83 w.Header().Add("Content-Type", "image/webp")
84@@ -375,12 +372,7 @@ func imgHandler(w http.ResponseWriter, h *ImgHandler) {
85 w.Header().Add("Content-Type", post.MimeType)
86 }
87
88- contentsProc, err := h.Img.Process(contents, strings.TrimSpace(post.MimeType))
89- if err != nil {
90- h.Logger.Error(err)
91- }
92-
93- _, err = w.Write(contentsProc)
94+ err = h.Img.Process(contents, w, strings.TrimSpace(post.MimeType))
95 if err != nil {
96 h.Logger.Error(err)
97 }
98@@ -788,6 +780,16 @@ func createMainRoutes(staticRoutes []shared.Route) []shared.Route {
99 shared.NewRoute("GET", "/help", shared.CreatePageHandler("html/help.page.tmpl")),
100 shared.NewRoute("GET", "/transparency", transparencyHandler),
101 shared.NewRoute("GET", "/check", shared.CheckHandler),
102+ shared.NewRoute("GET", "/debug/pprof/(.*)", pprof.Index),
103+ shared.NewRoute("GET", "/debug/pprof/cmdline", pprof.Cmdline),
104+ shared.NewRoute("GET", "/debug/pprof/profile", pprof.Profile),
105+ shared.NewRoute("GET", "/debug/pprof/symbol", pprof.Symbol),
106+ shared.NewRoute("GET", "/debug/pprof/trace", pprof.Trace),
107+ shared.NewRoute("POST", "/debug/pprof/(.*)", pprof.Index),
108+ shared.NewRoute("POST", "/debug/pprof/cmdline", pprof.Cmdline),
109+ shared.NewRoute("POST", "/debug/pprof/profile", pprof.Profile),
110+ shared.NewRoute("POST", "/debug/pprof/symbol", pprof.Symbol),
111+ shared.NewRoute("POST", "/debug/pprof/trace", pprof.Trace),
112 }
113
114 routes = append(
+5,
-11
1@@ -1,7 +1,6 @@
2 package storage
3
4 import (
5- "bytes"
6 "context"
7 "errors"
8 "fmt"
9@@ -67,22 +66,17 @@ func (s *StorageMinio) UpsertBucket(name string) (Bucket, error) {
10 return bucket, nil
11 }
12
13-func (s *StorageMinio) GetFile(bucket Bucket, fname string) ([]byte, error) {
14+func (s *StorageMinio) GetFile(bucket Bucket, fname string) (io.ReadCloser, error) {
15 obj, err := s.Client.GetObject(context.TODO(), bucket.Name, fname, minio.GetObjectOptions{})
16 if err != nil {
17- return []byte{}, err
18- }
19-
20- dat, err := io.ReadAll(obj)
21- if err != nil {
22- return []byte{}, err
23+ return nil, err
24 }
25
26- return dat, nil
27+ return obj, nil
28 }
29
30-func (s *StorageMinio) PutFile(bucket Bucket, fname string, contents []byte) (string, error) {
31- info, err := s.Client.PutObject(context.TODO(), bucket.Name, fname, bytes.NewReader(contents), int64(len(contents)), minio.PutObjectOptions{})
32+func (s *StorageMinio) PutFile(bucket Bucket, fname string, contents io.ReadCloser) (string, error) {
33+ info, err := s.Client.PutObject(context.TODO(), bucket.Name, fname, contents, -1, minio.PutObjectOptions{})
34 if err != nil {
35 return "", err
36 }
+14,
-7
1@@ -2,6 +2,7 @@ package storage
2
3 import (
4 "fmt"
5+ "io"
6 "os"
7 "path"
8 )
9@@ -15,8 +16,8 @@ type ObjectStorage interface {
10 GetBucket(name string) (Bucket, error)
11 UpsertBucket(name string) (Bucket, error)
12
13- GetFile(bucket Bucket, fname string) ([]byte, error)
14- PutFile(bucket Bucket, fname string, contents []byte) (string, error)
15+ GetFile(bucket Bucket, fname string) (io.ReadCloser, error)
16+ PutFile(bucket Bucket, fname string, contents io.ReadCloser) (string, error)
17 DeleteFile(bucket Bucket, fname string) error
18 }
19
20@@ -67,18 +68,24 @@ func (s *StorageFS) UpsertBucket(name string) (Bucket, error) {
21 return bucket, nil
22 }
23
24-func (s *StorageFS) GetFile(bucket Bucket, fname string) ([]byte, error) {
25- dat, err := os.ReadFile(path.Join(bucket.Path, fname))
26+func (s *StorageFS) GetFile(bucket Bucket, fname string) (io.ReadCloser, error) {
27+ dat, err := os.Open(path.Join(bucket.Path, fname))
28 if err != nil {
29- return []byte{}, err
30+ return nil, err
31 }
32
33 return dat, nil
34 }
35
36-func (s *StorageFS) PutFile(bucket Bucket, fname string, contents []byte) (string, error) {
37+func (s *StorageFS) PutFile(bucket Bucket, fname string, contents io.ReadCloser) (string, error) {
38 loc := path.Join(bucket.Path, fname)
39- err := os.WriteFile(loc, contents, 0644)
40+ f, err := os.OpenFile(loc, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
41+ if err != nil {
42+ return "", err
43+ }
44+ defer f.Close()
45+
46+ _, err = io.Copy(f, contents)
47 if err != nil {
48 return "", err
49 }