forked from TrueCloudLab/rclone
onedrive: implement DirMove - fixes #197
This commit is contained in:
parent
2e80d4c18e
commit
0f845e3a59
2 changed files with 105 additions and 1 deletions
|
@ -940,6 +940,110 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) {
|
||||||
return dstObj, nil
|
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
|
// DirCacheFlush resets the directory cache - used in testing as an
|
||||||
// optional interface
|
// optional interface
|
||||||
func (f *Fs) DirCacheFlush() {
|
func (f *Fs) DirCacheFlush() {
|
||||||
|
|
|
@ -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 |
|
| 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 |
|
| 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 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 |
|
| 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 |
|
| 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 |
|
| pCloud | Yes | Yes | Yes | Yes | Yes | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes |
|
||||||
|
|
Loading…
Reference in a new issue