From 0f845e3a59927e749911401e2298e263147df7c5 Mon Sep 17 00:00:00 2001 From: Cnly Date: Fri, 3 Aug 2018 00:13:37 +0800 Subject: [PATCH] onedrive: implement DirMove - fixes #197 --- backend/onedrive/onedrive.go | 104 +++++++++++++++++++++++++++++++++++ docs/content/overview.md | 2 +- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/backend/onedrive/onedrive.go b/backend/onedrive/onedrive.go index 76e920fbc..da46d8227 100644 --- a/backend/onedrive/onedrive.go +++ b/backend/onedrive/onedrive.go @@ -940,6 +940,110 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) { return dstObj, nil } +// DirMove moves src, srcRemote to this remote at dstRemote +// using server side move operations. +// +// Will only be called if src.Fs().Name() == f.Name() +// +// If it isn't possible then return fs.ErrorCantDirMove +// +// If destination exists then return fs.ErrorDirExists +func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error { + srcFs, ok := src.(*Fs) + if !ok { + fs.Debugf(srcFs, "Can't move directory - not same remote type") + return fs.ErrorCantDirMove + } + srcPath := path.Join(srcFs.root, srcRemote) + dstPath := path.Join(f.root, dstRemote) + + // Refuse to move to or from the root + if srcPath == "" || dstPath == "" { + fs.Debugf(src, "DirMove error: Can't move root") + return errors.New("can't move root directory") + } + + // find the root src directory + err := srcFs.dirCache.FindRoot(false) + if err != nil { + return err + } + + // find the root dst directory + if dstRemote != "" { + err = f.dirCache.FindRoot(true) + if err != nil { + return err + } + } else { + if f.dirCache.FoundRoot() { + return fs.ErrorDirExists + } + } + + // Find ID of dst parent, creating subdirs if necessary + var leaf, dstDirectoryID string + findPath := dstRemote + if dstRemote == "" { + findPath = f.root + } + leaf, dstDirectoryID, err = f.dirCache.FindPath(findPath, true) + if err != nil { + return err + } + parsedDstDirID, _, _ := parseDirID(dstDirectoryID) + + // Check destination does not exist + if dstRemote != "" { + _, err = f.dirCache.FindDir(dstRemote, false) + if err == fs.ErrorDirNotFound { + // OK + } else if err != nil { + return err + } else { + return fs.ErrorDirExists + } + } + + // Find ID of src + srcID, err := srcFs.dirCache.FindDir(srcRemote, false) + if err != nil { + return err + } + + // Get timestamps of src so they can be preserved + srcInfo, _, err := srcFs.readMetaDataForPath(srcPath) + if err != nil { + return err + } + + // Do the move + opts := newOptsCall(srcID, "PATCH", "") + move := api.MoveItemRequest{ + Name: replaceReservedChars(leaf), + ParentReference: &api.ItemReference{ + ID: parsedDstDirID, + }, + // We set the mod time too as it gets reset otherwise + FileSystemInfo: &api.FileSystemInfoFacet{ + CreatedDateTime: srcInfo.CreatedDateTime, + LastModifiedDateTime: srcInfo.LastModifiedDateTime, + }, + } + var resp *http.Response + var info api.Item + err = f.pacer.Call(func() (bool, error) { + resp, err = f.srv.CallJSON(&opts, &move, &info) + return shouldRetry(resp, err) + }) + if err != nil { + return err + } + + srcFs.dirCache.FlushDir(srcRemote) + return nil +} + // DirCacheFlush resets the directory cache - used in testing as an // optional interface func (f *Fs) DirCacheFlush() { diff --git a/docs/content/overview.md b/docs/content/overview.md index 0e975963e..9a841a9b2 100644 --- a/docs/content/overview.md +++ b/docs/content/overview.md @@ -139,7 +139,7 @@ operations more efficient. | Hubic | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | | Mega | Yes | No | Yes | Yes | No | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | | Microsoft Azure Blob Storage | Yes | Yes | No | No | No | Yes | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | -| Microsoft OneDrive | Yes | Yes | Yes | No [#197](https://github.com/ncw/rclone/issues/197) | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | +| Microsoft OneDrive | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | | OpenDrive | Yes | Yes | Yes | Yes | No | No | No | No | No | | Openstack Swift | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | | pCloud | Yes | Yes | Yes | Yes | Yes | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes |