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.
This commit is contained in:
Nick Craig-Wood 2023-10-24 17:39:33 +01:00
parent 9fdf3d548a
commit 54196f34e3
2 changed files with 15 additions and 7 deletions

View File

@ -2440,7 +2440,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo,
} else { } else {
createInfo.MimeType = fs.MimeTypeFromName(remote) 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 { if err != nil {
return nil, err 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), 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 { if err != nil {
return err return err
} }

View File

@ -27,7 +27,7 @@ var systemMetadataInfo = map[string]fs.MetadataHelp{
Example: "2006-01-02T15:04:05.999Z07:00", Example: "2006-01-02T15:04:05.999Z07:00",
}, },
"btime": { "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", Type: "RFC 3339",
Example: "2006-01-02T15:04:05.999Z07:00", 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 // 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 // It returns a callback which should be called to finish the updates
// after the data is uploaded. // 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{} callbackFns := []updateMetadataFn{}
callback = func(ctx context.Context, info *drive.File) error { callback = func(ctx context.Context, info *drive.File) error {
for _, fn := range callbackFns { for _, fn := range callbackFns {
@ -573,7 +577,11 @@ func (f *Fs) updateMetadata(ctx context.Context, updateInfo *drive.File, meta fs
return nil, err return nil, err
} }
case "btime": case "btime":
if update {
fs.Debugf(f, "Skipping btime metadata as can't update it on an existing file: %v", v)
} else {
updateInfo.CreatedTime = v updateInfo.CreatedTime = v
}
case "mtime": case "mtime":
updateInfo.ModifiedTime = v updateInfo.ModifiedTime = v
default: 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 // 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) meta, err := fs.GetMetadataOptions(ctx, src, options)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read metadata from source object: %w", err) 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 { if err != nil {
return nil, fmt.Errorf("failed to update metadata from source object: %w", err) return nil, fmt.Errorf("failed to update metadata from source object: %w", err)
} }