From 961266888fe797390c535386f3b3aa46f4853602 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 17 Jul 2026 13:15:27 +0100 Subject: [PATCH] drime: disable server side copy as it always fails The /file-entries/duplicate endpoint returns a 500 Server Error for every request (reported to Drime 2026-06) which made all server side copies fail after 10 retries. Remove the Copy method so rclone falls back to downloading and re-uploading instead. It can be restored if Drime fix the endpoint. --- backend/drime/drime.go | 111 ---------------------------------- docs/data/backends/drime.yaml | 1 - 2 files changed, 112 deletions(-) diff --git a/backend/drime/drime.go b/backend/drime/drime.go index 2499627f6..3b3978b13 100644 --- a/backend/drime/drime.go +++ b/backend/drime/drime.go @@ -420,14 +420,6 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e return f, nil } -// rootSlash returns root with a slash on if it is empty, otherwise empty string -func (f *Fs) rootSlash() string { - if f.root == "" { - return f.root - } - return f.root + "/" -} - // Return an Object from a path // // If it can't be found it returns the error fs.ErrorObjectNotFound. @@ -1012,108 +1004,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string return nil } -// copy a file or a folder to a new directory -func (f *Fs) copy(ctx context.Context, id, newDirID string) (item *api.Item, err error) { - var resp *http.Response - var request = api.CopyRequest{ - EntryIDs: []string{id}, - DestinationID: newDirID, - } - var result api.CopyResponse - opts := rest.Opts{ - Method: "POST", - Path: "/file-entries/duplicate", - Parameters: url.Values{}, - } - if f.opt.WorkspaceID != "" { - opts.Parameters.Set("workspaceId", f.opt.WorkspaceID) - } - err = f.pacer.Call(func() (bool, error) { - resp, err = f.srv.CallJSON(ctx, &opts, &request, &result) - return shouldRetry(ctx, resp, err) - }) - if err != nil { - return nil, fmt.Errorf("failed to copy item: %w", err) - } - itemResult := result.Entries[0] - return &itemResult, nil -} - -// copy and rename a file or folder to directoryID with leaf -func (f *Fs) copyTo(ctx context.Context, srcID, srcLeaf, dstLeaf, dstDirectoryID string) (info *api.Item, err error) { - // Can have duplicates so don't have to be careful here - - // Copy to dstDirectoryID first - info, err = f.copy(ctx, srcID, dstDirectoryID) - if err != nil { - return nil, err - } - - // Rename if required - if srcLeaf != dstLeaf { - info, err = f.rename(ctx, info.ID.String(), dstLeaf) - if err != nil { - return nil, err - } - } - return info, nil -} - -// Copy src to this remote using server-side copy operations. -// -// This is stored with the remote path given. -// -// It returns the destination Object and a possible error. -// -// Will only be called if src.Fs().Name() == f.Name() -// -// If it isn't possible then return fs.ErrorCantCopy -func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (dst fs.Object, err error) { - srcObj, ok := src.(*Object) - if !ok { - fs.Debugf(src, "Can't copy - not same remote type") - return nil, fs.ErrorCantCopy - } - srcLeaf := path.Base(srcObj.remote) - - srcPath := srcObj.fs.rootSlash() + srcObj.remote - dstPath := f.rootSlash() + remote - if srcPath == dstPath { - return nil, fmt.Errorf("can't copy %q -> %q as are same name", srcPath, dstPath) - } - - // Find existing object - existingObj, err := f.NewObject(ctx, remote) - if err == nil { - defer func() { - // Don't remove existing object if returning an error - if err != nil { - return - } - fs.Debugf(existingObj, "Server side copy: removing existing object after successful copy") - err = existingObj.Remove(ctx) - }() - } - - // Create temporary object - dstObj, dstLeaf, dstDirectoryID, err := f.createObject(ctx, remote, srcObj.modTime, srcObj.size) - if err != nil { - return nil, err - } - - // Copy the object - info, err := f.copyTo(ctx, srcObj.id, srcLeaf, dstLeaf, dstDirectoryID) - if err != nil { - return nil, err - } - err = dstObj.setMetaData(info) - if err != nil { - return nil, err - } - - return dstObj, nil -} - // DirCacheFlush resets the directory cache - used in testing as an // optional interface func (f *Fs) DirCacheFlush() { @@ -1672,7 +1562,6 @@ var ( _ fs.Fs = (*Fs)(nil) _ fs.Purger = (*Fs)(nil) _ fs.PutStreamer = (*Fs)(nil) - _ fs.Copier = (*Fs)(nil) _ fs.Mover = (*Fs)(nil) _ fs.DirMover = (*Fs)(nil) _ fs.DirCacheFlusher = (*Fs)(nil) diff --git a/docs/data/backends/drime.yaml b/docs/data/backends/drime.yaml index fa5c40997..546e54a50 100644 --- a/docs/data/backends/drime.yaml +++ b/docs/data/backends/drime.yaml @@ -14,7 +14,6 @@ remote: 'TestDrime:' features: - About - CanHaveEmptyDirectories -- Copy - DirCacheFlush - DirMove - Move