From ee2fac18554c013a24d6c1bad27c59025375db85 Mon Sep 17 00:00:00 2001 From: database64128 Date: Fri, 21 May 2021 17:11:43 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=95=B0=EF=B8=8F=20GCS:=20Compatible=20wit?= =?UTF-8?q?h=20gsutil's=20mtime=20metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Write `goog-reserved-file-mtime` in addition to `mtime`. - Fallback to `goog-reserved-file-mtime` if `mtime` doesn't exist. - ref rclone/rclone#5331 --- .../googlecloudstorage/googlecloudstorage.go | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/backend/googlecloudstorage/googlecloudstorage.go b/backend/googlecloudstorage/googlecloudstorage.go index 388149fb6..45fbc66d7 100644 --- a/backend/googlecloudstorage/googlecloudstorage.go +++ b/backend/googlecloudstorage/googlecloudstorage.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "net/http" "path" + "strconv" "strings" "time" @@ -51,9 +52,10 @@ const ( rcloneClientID = "202264815644.apps.googleusercontent.com" rcloneEncryptedClientSecret = "Uj7C9jGfb9gmeaV70Lh058cNkWvepr-Es9sBm0zdgil7JaOWF1VySw" timeFormatIn = time.RFC3339 - timeFormatOut = "2006-01-02T15:04:05.000000000Z07:00" - metaMtime = "mtime" // key to store mtime under in metadata - listChunks = 1000 // chunk size to read directory listings + timeFormatOut = time.RFC3339Nano + metaMtime = "mtime" // key to store mtime in metadata + metaMtimeGsutil = "goog-reserved-file-mtime" // key used by GSUtil to store mtime in metadata + listChunks = 1000 // chunk size to read directory listings minSleep = 10 * time.Millisecond ) @@ -928,6 +930,17 @@ func (o *Object) setMetaData(info *storage.Object) { fs.Debugf(o, "Failed to read mtime from metadata: %s", err) } + // Fallback to GSUtil mtime + mtimeGsutilString, ok := info.Metadata[metaMtimeGsutil] + if ok { + unixTimeSec, err := strconv.ParseInt(mtimeGsutilString, 10, 64) + if err == nil { + o.modTime = time.Unix(unixTimeSec, 0) + return + } + fs.Debugf(o, "Failed to read GSUtil mtime from metadata: %s", err) + } + // Fallback to the Updated time modTime, err := time.Parse(timeFormatIn, info.Updated) if err != nil { @@ -987,6 +1000,7 @@ func (o *Object) ModTime(ctx context.Context) time.Time { func metadataFromModTime(modTime time.Time) map[string]string { metadata := make(map[string]string, 1) metadata[metaMtime] = modTime.Format(timeFormatOut) + metadata[metaMtimeGsutil] = strconv.FormatInt(modTime.Unix(), 10) return metadata } @@ -998,11 +1012,11 @@ func (o *Object) SetModTime(ctx context.Context, modTime time.Time) (err error) return err } // Add the mtime to the existing metadata - mtime := modTime.Format(timeFormatOut) if object.Metadata == nil { object.Metadata = make(map[string]string, 1) } - object.Metadata[metaMtime] = mtime + object.Metadata[metaMtime] = modTime.Format(timeFormatOut) + object.Metadata[metaMtimeGsutil] = strconv.FormatInt(modTime.Unix(), 10) // Copy the object to itself to update the metadata // Using PATCH requires too many permissions bucket, bucketPath := o.split()