diff --git a/backend/drive/drive.go b/backend/drive/drive.go index 5609ba3b6..6e3b5fe35 100644 --- a/backend/drive/drive.go +++ b/backend/drive/drive.go @@ -54,17 +54,18 @@ const ( // Globals var ( // Flags - driveAuthOwnerOnly = flags.BoolP("drive-auth-owner-only", "", false, "Only consider files owned by the authenticated user.") - driveUseTrash = flags.BoolP("drive-use-trash", "", true, "Send files to the trash instead of deleting permanently.") - driveSkipGdocs = flags.BoolP("drive-skip-gdocs", "", false, "Skip google documents in all listings.") - driveSharedWithMe = flags.BoolP("drive-shared-with-me", "", false, "Only show files that are shared with me") - driveTrashedOnly = flags.BoolP("drive-trashed-only", "", false, "Only show files that are in the trash") - driveExtensions = flags.StringP("drive-formats", "", defaultExtensions, "Comma separated list of preferred formats for downloading Google docs.") - driveUseCreatedDate = flags.BoolP("drive-use-created-date", "", false, "Use created date instead of modified date.") - driveListChunk = flags.Int64P("drive-list-chunk", "", 1000, "Size of listing chunk 100-1000. 0 to disable.") - driveImpersonate = flags.StringP("drive-impersonate", "", "", "Impersonate this user when using a service account.") - driveAlternateExport = flags.BoolP("drive-alternate-export", "", false, "Use alternate export URLs for google documents export.") - driveAcknowledgeAbuse = flags.BoolP("drive-acknowledge-abuse", "", false, "Set to allow files which return cannotDownloadAbusiveFile to be downloaded.") + driveAuthOwnerOnly = flags.BoolP("drive-auth-owner-only", "", false, "Only consider files owned by the authenticated user.") + driveUseTrash = flags.BoolP("drive-use-trash", "", true, "Send files to the trash instead of deleting permanently.") + driveSkipGdocs = flags.BoolP("drive-skip-gdocs", "", false, "Skip google documents in all listings.") + driveSharedWithMe = flags.BoolP("drive-shared-with-me", "", false, "Only show files that are shared with me") + driveTrashedOnly = flags.BoolP("drive-trashed-only", "", false, "Only show files that are in the trash") + driveExtensions = flags.StringP("drive-formats", "", defaultExtensions, "Comma separated list of preferred formats for downloading Google docs.") + driveUseCreatedDate = flags.BoolP("drive-use-created-date", "", false, "Use created date instead of modified date.") + driveListChunk = flags.Int64P("drive-list-chunk", "", 1000, "Size of listing chunk 100-1000. 0 to disable.") + driveImpersonate = flags.StringP("drive-impersonate", "", "", "Impersonate this user when using a service account.") + driveAlternateExport = flags.BoolP("drive-alternate-export", "", false, "Use alternate export URLs for google documents export.") + driveAcknowledgeAbuse = flags.BoolP("drive-acknowledge-abuse", "", false, "Set to allow files which return cannotDownloadAbusiveFile to be downloaded.") + driveKeepRevisionForever = flags.BoolP("drive-keep-revision-forever", "", false, "Keep new head revision forever.") // chunkSize is the size of the chunks created during a resumable upload and should be a power of two. // 1<<18 is the minimum size supported by the Google uploader, and there is no maximum. chunkSize = fs.SizeSuffix(8 * 1024 * 1024) @@ -857,7 +858,7 @@ func (f *Fs) PutUnchecked(in io.Reader, src fs.ObjectInfo, options ...fs.OpenOpt // Make the API request to upload metadata and file data. // Don't retry, return a retry error instead err = f.pacer.CallNoRetry(func() (bool, error) { - info, err = f.svc.Files.Create(createInfo).Media(in, googleapi.ContentType("")).Fields(googleapi.Field(partialFields)).SupportsTeamDrives(f.isTeamDrive).Do() + info, err = f.svc.Files.Create(createInfo).Media(in, googleapi.ContentType("")).Fields(googleapi.Field(partialFields)).SupportsTeamDrives(f.isTeamDrive).KeepRevisionForever(*driveKeepRevisionForever).Do() return shouldRetry(err) }) if err != nil { @@ -1014,7 +1015,7 @@ func (f *Fs) Copy(src fs.Object, remote string) (fs.Object, error) { var info *drive.File err = o.fs.pacer.Call(func() (bool, error) { - info, err = o.fs.svc.Files.Copy(srcObj.id, createInfo).Fields(googleapi.Field(partialFields)).SupportsTeamDrives(f.isTeamDrive).Do() + info, err = o.fs.svc.Files.Copy(srcObj.id, createInfo).Fields(googleapi.Field(partialFields)).SupportsTeamDrives(f.isTeamDrive).KeepRevisionForever(*driveKeepRevisionForever).Do() return shouldRetry(err) }) if err != nil { @@ -1665,7 +1666,7 @@ func (o *Object) Update(in io.Reader, src fs.ObjectInfo, options ...fs.OpenOptio if size == 0 || size < int64(driveUploadCutoff) { // Don't retry, return a retry error instead err = o.fs.pacer.CallNoRetry(func() (bool, error) { - info, err = o.fs.svc.Files.Update(o.id, updateInfo).Media(in, googleapi.ContentType("")).Fields(googleapi.Field(partialFields)).SupportsTeamDrives(o.fs.isTeamDrive).Do() + info, err = o.fs.svc.Files.Update(o.id, updateInfo).Media(in, googleapi.ContentType("")).Fields(googleapi.Field(partialFields)).SupportsTeamDrives(o.fs.isTeamDrive).KeepRevisionForever(*driveKeepRevisionForever).Do() return shouldRetry(err) }) if err != nil { diff --git a/backend/drive/upload.go b/backend/drive/upload.go index 0a6a1e341..281ffe855 100644 --- a/backend/drive/upload.go +++ b/backend/drive/upload.go @@ -58,6 +58,9 @@ func (f *Fs) Upload(in io.Reader, size int64, contentType string, fileID string, if f.isTeamDrive { params.Set("supportsTeamDrives", "true") } + if *driveKeepRevisionForever { + params.Set("keepRevisionForever", "true") + } urls := "https://www.googleapis.com/upload/drive/v3/files" method := "POST" if fileID != "" { diff --git a/docs/content/drive.md b/docs/content/drive.md index cbbe4a798..c8956bcd0 100644 --- a/docs/content/drive.md +++ b/docs/content/drive.md @@ -437,6 +437,10 @@ See rclone issue [#2243](https://github.com/ncw/rclone/issues/2243) for backgrou When using a service account, this instructs rclone to impersonate the user passed in. +#### --drive-keep-revision-forever #### + +Keeps new head revision of the file forever. + #### --drive-list-chunk int #### Size of listing chunk 100-1000. 0 to disable. (default 1000)