From 54196f34e3021caa59520d32b7dddb30be4fd918 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 24 Oct 2023 17:39:33 +0100 Subject: [PATCH] drive: fix error updating created time metadata on existing object Google drive doesn't allow the btime (created time) metadata to be updated when updating an existing object. This changes skips btime metadata if we are updating an existing object but allows it otherwise. --- backend/drive/drive.go | 4 ++-- backend/drive/metadata.go | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/backend/drive/drive.go b/backend/drive/drive.go index e39a5a6c2..20541fbc4 100644 --- a/backend/drive/drive.go +++ b/backend/drive/drive.go @@ -2440,7 +2440,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo, } else { createInfo.MimeType = fs.MimeTypeFromName(remote) } - updateMetadata, err := f.fetchAndUpdateMetadata(ctx, src, options, createInfo) + updateMetadata, err := f.fetchAndUpdateMetadata(ctx, src, options, createInfo, false) if err != nil { return nil, err } @@ -4070,7 +4070,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op ModifiedTime: src.ModTime(ctx).Format(timeFormatOut), } - updateMetadata, err := o.fs.fetchAndUpdateMetadata(ctx, src, options, updateInfo) + updateMetadata, err := o.fs.fetchAndUpdateMetadata(ctx, src, options, updateInfo, true) if err != nil { return err } diff --git a/backend/drive/metadata.go b/backend/drive/metadata.go index 8b3c87365..94a57ef18 100644 --- a/backend/drive/metadata.go +++ b/backend/drive/metadata.go @@ -27,7 +27,7 @@ var systemMetadataInfo = map[string]fs.MetadataHelp{ Example: "2006-01-02T15:04:05.999Z07:00", }, "btime": { - Help: "Time of file birth (creation) with mS accuracy.", + Help: "Time of file birth (creation) with mS accuracy. Note that this is only writable on fresh uploads - it can't be written for updates.", Type: "RFC 3339", Example: "2006-01-02T15:04:05.999Z07:00", }, @@ -492,9 +492,13 @@ type updateMetadataFn func(context.Context, *drive.File) error // read the metadata from meta and write it into updateInfo // +// update should be true if this is being used to create metadata for +// an update/PATCH call as the rules on what can be updated are +// slightly different there. +// // It returns a callback which should be called to finish the updates // after the data is uploaded. -func (f *Fs) updateMetadata(ctx context.Context, updateInfo *drive.File, meta fs.Metadata) (callback updateMetadataFn, err error) { +func (f *Fs) updateMetadata(ctx context.Context, updateInfo *drive.File, meta fs.Metadata, update bool) (callback updateMetadataFn, err error) { callbackFns := []updateMetadataFn{} callback = func(ctx context.Context, info *drive.File) error { for _, fn := range callbackFns { @@ -573,7 +577,11 @@ func (f *Fs) updateMetadata(ctx context.Context, updateInfo *drive.File, meta fs return nil, err } case "btime": - updateInfo.CreatedTime = v + if update { + fs.Debugf(f, "Skipping btime metadata as can't update it on an existing file: %v", v) + } else { + updateInfo.CreatedTime = v + } case "mtime": updateInfo.ModifiedTime = v default: @@ -587,12 +595,12 @@ func (f *Fs) updateMetadata(ctx context.Context, updateInfo *drive.File, meta fs } // Fetch metadata and update updateInfo if --metadata is in use -func (f *Fs) fetchAndUpdateMetadata(ctx context.Context, src fs.ObjectInfo, options []fs.OpenOption, updateInfo *drive.File) (callback updateMetadataFn, err error) { +func (f *Fs) fetchAndUpdateMetadata(ctx context.Context, src fs.ObjectInfo, options []fs.OpenOption, updateInfo *drive.File, update bool) (callback updateMetadataFn, err error) { meta, err := fs.GetMetadataOptions(ctx, src, options) if err != nil { return nil, fmt.Errorf("failed to read metadata from source object: %w", err) } - callback, err = f.updateMetadata(ctx, updateInfo, meta) + callback, err = f.updateMetadata(ctx, updateInfo, meta, update) if err != nil { return nil, fmt.Errorf("failed to update metadata from source object: %w", err) }