pgs-etag.diff

· erock's pastes · raw

expires: 2025-09-17

 1diff --git a/go.mod b/go.mod
 2index 50c34bf..ff68aa7 100644
 3--- a/go.mod
 4+++ b/go.mod
 5@@ -48,6 +48,7 @@ require (
 6 	github.com/picosh/pubsub v0.0.0-20241114191831-ec8f16c0eb88
 7 	github.com/picosh/utils v0.0.0-20250528150332-0721504d3a96
 8 	github.com/pkg/sftp v1.13.9
 9+	github.com/pkg/xattr v0.4.11
10 	github.com/prometheus/client_golang v1.21.1
11 	github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
12 	github.com/sendgrid/sendgrid-go v3.16.0+incompatible
13diff --git a/go.sum b/go.sum
14index a63ea40..c22dd98 100644
15--- a/go.sum
16+++ b/go.sum
17@@ -652,6 +652,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
18 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
19 github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw=
20 github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA=
21+github.com/pkg/xattr v0.4.11 h1:DA7usy0rTMNMGvm06b5LhZUwiPj708D89S8DkXpMB1E=
22+github.com/pkg/xattr v0.4.11/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
23 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
24 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
25 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
26@@ -1086,6 +1088,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
27 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
28 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
29 golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
30+golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
31 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
32 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
33 golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
34diff --git a/pkg/pobj/storage/fs.go b/pkg/pobj/storage/fs.go
35index c703b90..1f4204e 100644
36--- a/pkg/pobj/storage/fs.go
37+++ b/pkg/pobj/storage/fs.go
38@@ -1,6 +1,8 @@
39 package storage
40 
41 import (
42+	"crypto/md5"
43+	"encoding/hex"
44 	"fmt"
45 	"io"
46 	"io/fs"
47@@ -14,6 +16,7 @@ import (
48 
49 	"github.com/picosh/pico/pkg/send/utils"
50 	"github.com/picosh/pico/pkg/shared/mime"
51+	"github.com/pkg/xattr"
52 )
53 
54 // https://stackoverflow.com/a/32482941
55@@ -113,6 +116,14 @@ func (s *StorageFS) GetObject(bucket Bucket, fpath string) (utils.ReadAndReaderA
56 		return nil, objInfo, err
57 	}
58 
59+	attr, err := xattr.FGet(dat, "user.etag")
60+	if err != nil {
61+		s.Logger.Error("xattr read etag", "err", err)
62+	}
63+	etag := string(attr)
64+	s.Logger.Info("xattr get etag", "etag", etag)
65+
66+	objInfo.ETag = etag
67 	objInfo.Size = info.Size()
68 	objInfo.LastModified = info.ModTime()
69 	objInfo.Metadata.Set("content-type", mime.GetMimeType(fpath))
70@@ -130,11 +141,26 @@ func (s *StorageFS) PutObject(bucket Bucket, fpath string, contents io.Reader, e
71 		return "", 0, err
72 	}
73 
74+	// calculate etag
75+	h := md5.New()
76+	tr := io.TeeReader(contents, h)
77+	if _, err := io.Copy(h, tr); err != nil {
78+		return "", 0, err
79+	}
80+	md5Sum := h.Sum(nil)
81+	etag := hex.EncodeToString(md5Sum)
82+
83 	size, err := io.Copy(f, contents)
84 	if err != nil {
85 		return "", 0, err
86 	}
87 
88+	s.Logger.Info("xattr set etag", "etag", etag)
89+	err = xattr.FSet(f, "user.etag", []byte(etag))
90+	if err != nil {
91+		s.Logger.Error("xattr set etag", "err", err)
92+	}
93+
94 	err = f.Close()
95 	if err != nil {
96 		return "", 0, err