forked from TrueCloudLab/rclone
Add srcRemote and dstRemote parameters to DirMove #954
This commit is contained in:
parent
e4835f535d
commit
f3c5745468
9 changed files with 172 additions and 92 deletions
|
@ -660,55 +660,90 @@ func (f *Fs) DirCacheFlush() {
|
||||||
f.dirCache.ResetRoot()
|
f.dirCache.ResetRoot()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirMove moves src directory to this remote using server side move
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
// operations.
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
func (f *Fs) DirMove(src fs.Fs) (err error) {
|
func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) (err error) {
|
||||||
// go test -v -run '^Test(Setup|Init|FsMkdir|FsPutFile1|FsPutFile2|FsUpdateFile1|FsDirMove)$
|
|
||||||
srcFs, ok := src.(*Fs)
|
srcFs, ok := src.(*Fs)
|
||||||
if !ok {
|
if !ok {
|
||||||
fs.Debugf(src, "DirMove error: not same remote type")
|
fs.Debugf(src, "DirMove error: not same remote type")
|
||||||
return fs.ErrorCantDirMove
|
return fs.ErrorCantDirMove
|
||||||
}
|
}
|
||||||
|
srcPath := path.Join(srcFs.root, srcRemote)
|
||||||
// Check if destination exists
|
dstPath := path.Join(f.root, dstRemote)
|
||||||
if f.dirCache.FoundRoot() {
|
|
||||||
fs.Debugf(src, "DirMove error: destination exists")
|
|
||||||
return fs.ErrorDirExists
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refuse to move to or from the root
|
// Refuse to move to or from the root
|
||||||
if f.root == "" || srcFs.root == "" {
|
if srcPath == "" || dstPath == "" {
|
||||||
fs.Debugf(src, "DirMove error: Can't move root")
|
fs.Debugf(src, "DirMove error: Can't move root")
|
||||||
return errors.New("can't move root directory")
|
return errors.New("can't move root directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find ID of parent
|
// find the root src directory
|
||||||
dstLeaf, dstDirectoryID, err := f.dirCache.FindPath(f.root, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the ID of the source and make a node from it
|
|
||||||
err = srcFs.dirCache.FindRoot(false)
|
err = srcFs.dirCache.FindRoot(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fs.Debugf(src, "DirMove error: error finding src root: %v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
srcDirectoryID, err := srcFs.dirCache.RootParentID()
|
|
||||||
|
// 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
|
||||||
|
findPath := dstRemote
|
||||||
|
if dstRemote == "" {
|
||||||
|
findPath = f.root
|
||||||
|
}
|
||||||
|
dstLeaf, dstDirectoryID, err := f.dirCache.FindPath(findPath, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 parent
|
||||||
|
findPath = srcRemote
|
||||||
|
var srcDirectoryID string
|
||||||
|
if srcRemote == "" {
|
||||||
|
srcDirectoryID, err = srcFs.dirCache.RootParentID()
|
||||||
|
} else {
|
||||||
|
_, srcDirectoryID, err = srcFs.dirCache.FindPath(findPath, false)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srcLeaf, _ := dircache.SplitPath(srcPath)
|
||||||
|
|
||||||
|
// Find ID of src
|
||||||
|
srcID, err := srcFs.dirCache.FindDir(srcRemote, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fs.Debugf(src, "DirMove error: error finding src RootParentID: %v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
srcLeaf, _ := dircache.SplitPath(srcFs.root)
|
|
||||||
|
|
||||||
// FIXME make a proper node.UpdateMetadata command
|
// FIXME make a proper node.UpdateMetadata command
|
||||||
srcInfo := acd.NodeFromId(srcFs.dirCache.RootID(), f.c.Nodes)
|
srcInfo := acd.NodeFromId(srcID, f.c.Nodes)
|
||||||
var jsonStr string
|
var jsonStr string
|
||||||
err = srcFs.pacer.Call(func() (bool, error) {
|
err = srcFs.pacer.Call(func() (bool, error) {
|
||||||
jsonStr, err = srcInfo.GetMetadata()
|
jsonStr, err = srcInfo.GetMetadata()
|
||||||
|
@ -724,10 +759,13 @@ func (f *Fs) DirMove(src fs.Fs) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = f.moveNode(srcFs.root, dstLeaf, dstDirectoryID, srcInfo, srcLeaf, srcDirectoryID, true)
|
err = f.moveNode(srcPath, dstLeaf, dstDirectoryID, srcInfo, srcLeaf, srcDirectoryID, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
srcFs.dirCache.ResetRoot()
|
srcFs.dirCache.FlushDir(srcRemote)
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// purgeCheck remotes the root directory, if check is set then it
|
// purgeCheck remotes the root directory, if check is set then it
|
||||||
|
|
|
@ -254,15 +254,15 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) {
|
||||||
return f.newObject(oResult), nil
|
return f.newObject(oResult), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirMove moves src to this remote using server side move
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
// operations.
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
func (f *Fs) DirMove(src fs.Fs) error {
|
func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error {
|
||||||
do := f.Fs.Features().DirMove
|
do := f.Fs.Features().DirMove
|
||||||
if do == nil {
|
if do == nil {
|
||||||
return fs.ErrorCantDirMove
|
return fs.ErrorCantDirMove
|
||||||
|
@ -272,7 +272,7 @@ func (f *Fs) DirMove(src fs.Fs) error {
|
||||||
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
||||||
return fs.ErrorCantDirMove
|
return fs.ErrorCantDirMove
|
||||||
}
|
}
|
||||||
return do(srcFs.Fs)
|
return do(srcFs.Fs, f.cipher.EncryptDirName(srcRemote), f.cipher.EncryptDirName(dstRemote))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutUnchecked uploads the object
|
// PutUnchecked uploads the object
|
||||||
|
|
|
@ -791,34 +791,72 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) {
|
||||||
return dstObj, nil
|
return dstObj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirMove moves src directory to this remote using server side move
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
// operations.
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
func (f *Fs) DirMove(src fs.Fs) error {
|
func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error {
|
||||||
srcFs, ok := src.(*Fs)
|
srcFs, ok := src.(*Fs)
|
||||||
if !ok {
|
if !ok {
|
||||||
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
||||||
return fs.ErrorCantDirMove
|
return fs.ErrorCantDirMove
|
||||||
}
|
}
|
||||||
|
srcPath := path.Join(srcFs.root, srcRemote)
|
||||||
// Check if destination exists
|
dstPath := path.Join(f.root, dstRemote)
|
||||||
if f.dirCache.FoundRoot() {
|
|
||||||
return fs.ErrorDirExists
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refuse to move to or from the root
|
// Refuse to move to or from the root
|
||||||
if f.root == "" || srcFs.root == "" {
|
if srcPath == "" || dstPath == "" {
|
||||||
fs.Debugf(src, "DirMove error: Can't move root")
|
fs.Debugf(src, "DirMove error: Can't move root")
|
||||||
return errors.New("can't move root directory")
|
return errors.New("can't move root directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find ID of parent
|
// find the root src directory
|
||||||
leaf, directoryID, err := f.dirCache.FindPath(f.root, true)
|
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, directoryID string
|
||||||
|
findPath := dstRemote
|
||||||
|
if dstRemote == "" {
|
||||||
|
findPath = f.root
|
||||||
|
}
|
||||||
|
leaf, directoryID, err = f.dirCache.FindPath(findPath, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -829,13 +867,13 @@ func (f *Fs) DirMove(src fs.Fs) error {
|
||||||
Parents: []*drive.ParentReference{{Id: directoryID}},
|
Parents: []*drive.ParentReference{{Id: directoryID}},
|
||||||
}
|
}
|
||||||
err = f.pacer.Call(func() (bool, error) {
|
err = f.pacer.Call(func() (bool, error) {
|
||||||
_, err = f.svc.Files.Patch(srcFs.dirCache.RootID(), &patch).Do()
|
_, err = f.svc.Files.Patch(srcID, &patch).Do()
|
||||||
return shouldRetry(err)
|
return shouldRetry(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
srcFs.dirCache.ResetRoot()
|
srcFs.dirCache.FlushDir(srcRemote)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -563,19 +563,22 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) {
|
||||||
return dstObj, nil
|
return dstObj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirMove moves src to this remote using server side move operations.
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
func (f *Fs) DirMove(src fs.Fs) error {
|
func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error {
|
||||||
srcFs, ok := src.(*Fs)
|
srcFs, ok := src.(*Fs)
|
||||||
if !ok {
|
if !ok {
|
||||||
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
||||||
return fs.ErrorCantDirMove
|
return fs.ErrorCantDirMove
|
||||||
}
|
}
|
||||||
|
srcPath := path.Join(srcFs.slashRoot, srcRemote)
|
||||||
|
dstPath := path.Join(f.slashRoot, dstRemote)
|
||||||
|
|
||||||
// Check if destination exists
|
// Check if destination exists
|
||||||
entry, err := f.db.Metadata(f.slashRoot, false, false, "", "", metadataLimit)
|
entry, err := f.db.Metadata(f.slashRoot, false, false, "", "", metadataLimit)
|
||||||
|
@ -583,8 +586,11 @@ func (f *Fs) DirMove(src fs.Fs) error {
|
||||||
return fs.ErrorDirExists
|
return fs.ErrorDirExists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the parent directory exists
|
||||||
|
// ...apparently not necessary
|
||||||
|
|
||||||
// Do the move
|
// Do the move
|
||||||
_, err = f.db.Move(srcFs.slashRoot, f.slashRoot)
|
_, err = f.db.Move(srcPath, dstPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "MoveDir failed")
|
return errors.Wrap(err, "MoveDir failed")
|
||||||
}
|
}
|
||||||
|
|
12
fs/fs.go
12
fs/fs.go
|
@ -256,15 +256,15 @@ type Features struct {
|
||||||
// If it isn't possible then return fs.ErrorCantMove
|
// If it isn't possible then return fs.ErrorCantMove
|
||||||
Move func(src Object, remote string) (Object, error)
|
Move func(src Object, remote string) (Object, error)
|
||||||
|
|
||||||
// DirMove moves src to this remote using server side move
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
// operations.
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
DirMove func(src Fs) error
|
DirMove func(src Fs, srcRemote, dstRemote string) error
|
||||||
|
|
||||||
// UnWrap returns the Fs that this Fs is wrapping
|
// UnWrap returns the Fs that this Fs is wrapping
|
||||||
UnWrap func() Fs
|
UnWrap func() Fs
|
||||||
|
@ -412,15 +412,15 @@ type Mover interface {
|
||||||
|
|
||||||
// DirMover is an optional interface for Fs
|
// DirMover is an optional interface for Fs
|
||||||
type DirMover interface {
|
type DirMover interface {
|
||||||
// DirMove moves src to this remote using server side move
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
// operations.
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
DirMove(src Fs) error
|
DirMove(src Fs, srcRemote, dstRemote string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnWrapper is an optional interfaces for Fs
|
// UnWrapper is an optional interfaces for Fs
|
||||||
|
|
|
@ -1107,7 +1107,7 @@ func MoveDir(fdst, fsrc Fs) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
Debugf(fdst, "Using server side directory move")
|
Debugf(fdst, "Using server side directory move")
|
||||||
err := fdstDirMove(fsrc)
|
err := fdstDirMove(fsrc, "", "")
|
||||||
switch err {
|
switch err {
|
||||||
case ErrorCantDirMove, ErrorDirExists:
|
case ErrorCantDirMove, ErrorDirExists:
|
||||||
Infof(fdst, "Server side directory move failed - fallback to file moves: %v", err)
|
Infof(fdst, "Server side directory move failed - fallback to file moves: %v", err)
|
||||||
|
|
|
@ -481,6 +481,8 @@ func TestFsMove(t *testing.T) {
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
|
|
||||||
// TestFsDirMove tests DirMove
|
// TestFsDirMove tests DirMove
|
||||||
|
//
|
||||||
|
// go test -v -run '^Test(Setup|Init|FsMkdir|FsPutFile1|FsPutFile2|FsUpdateFile1|FsDirMove)$
|
||||||
func TestFsDirMove(t *testing.T) {
|
func TestFsDirMove(t *testing.T) {
|
||||||
skipIfNotOk(t)
|
skipIfNotOk(t)
|
||||||
|
|
||||||
|
@ -491,7 +493,7 @@ func TestFsDirMove(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check it can't move onto itself
|
// Check it can't move onto itself
|
||||||
err := doDirMove(remote)
|
err := doDirMove(remote, "", "")
|
||||||
require.Equal(t, fs.ErrorDirExists, err)
|
require.Equal(t, fs.ErrorDirExists, err)
|
||||||
|
|
||||||
// new remote
|
// new remote
|
||||||
|
@ -499,17 +501,23 @@ func TestFsDirMove(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer removeNewRemote()
|
defer removeNewRemote()
|
||||||
|
|
||||||
|
const newName = "new_name/sub_new_name"
|
||||||
// try the move
|
// try the move
|
||||||
err = newRemote.Features().DirMove(remote)
|
err = newRemote.Features().DirMove(remote, "", newName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// check remotes
|
// check remotes
|
||||||
// FIXME: Prints errors.
|
// FIXME: Prints errors.
|
||||||
fstest.CheckListing(t, remote, []fstest.Item{})
|
fstest.CheckListing(t, remote, []fstest.Item{})
|
||||||
fstest.CheckListing(t, newRemote, []fstest.Item{file2, file1})
|
file1Copy := file1
|
||||||
|
file1Copy.Path = path.Join(newName, file1.Path)
|
||||||
|
file2Copy := file2
|
||||||
|
file2Copy.Path = path.Join(newName, file2.Path)
|
||||||
|
file2Copy.WinPath = path.Join(newName, file2.WinPath)
|
||||||
|
fstest.CheckListing(t, newRemote, []fstest.Item{file2Copy, file1Copy})
|
||||||
|
|
||||||
// move it back
|
// move it back
|
||||||
err = doDirMove(newRemote)
|
err = doDirMove(newRemote, newName, "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// check remotes
|
// check remotes
|
||||||
|
|
|
@ -485,38 +485,38 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) {
|
||||||
return dstObj, nil
|
return dstObj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirMove moves src directory to this remote using server side move
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
// operations.
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
func (f *Fs) DirMove(src fs.Fs) error {
|
func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error {
|
||||||
srcFs, ok := src.(*Fs)
|
srcFs, ok := src.(*Fs)
|
||||||
if !ok {
|
if !ok {
|
||||||
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
||||||
return fs.ErrorCantDirMove
|
return fs.ErrorCantDirMove
|
||||||
}
|
}
|
||||||
// Check if source exists
|
srcPath := f.cleanPath(filepath.Join(srcFs.root, srcRemote))
|
||||||
sstat, err := os.Lstat(srcFs.root)
|
dstPath := f.cleanPath(filepath.Join(f.root, dstRemote))
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// And is a directory
|
|
||||||
if !sstat.IsDir() {
|
|
||||||
return fs.ErrorCantDirMove
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if destination exists
|
// Check if destination exists
|
||||||
_, err = os.Lstat(f.root)
|
_, err := os.Lstat(dstPath)
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return fs.ErrorDirExists
|
return fs.ErrorDirExists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create parent of destination
|
||||||
|
dstParentPath, _ := getDirFile(dstPath)
|
||||||
|
err = os.MkdirAll(dstParentPath, 0777)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Do the move
|
// Do the move
|
||||||
return os.Rename(srcFs.root, f.root)
|
return os.Rename(srcPath, dstPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hashes returns the supported hash sets.
|
// Hashes returns the supported hash sets.
|
||||||
|
|
32
sftp/sftp.go
32
sftp/sftp.go
|
@ -384,23 +384,25 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) {
|
||||||
return dstObj, nil
|
return dstObj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirMove moves src directory to this remote using server side move
|
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||||
// operations.
|
// using server side move operations.
|
||||||
//
|
//
|
||||||
// Will only be called if src.Fs().Name() == f.Name()
|
// Will only be called if src.Fs().Name() == f.Name()
|
||||||
//
|
//
|
||||||
// If it isn't possible then return fs.ErrorCantDirMove
|
// If it isn't possible then return fs.ErrorCantDirMove
|
||||||
//
|
//
|
||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
func (f *Fs) DirMove(src fs.Fs) error {
|
func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error {
|
||||||
srcFs, ok := src.(*Fs)
|
srcFs, ok := src.(*Fs)
|
||||||
if !ok {
|
if !ok {
|
||||||
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
fs.Debugf(srcFs, "Can't move directory - not same remote type")
|
||||||
return fs.ErrorCantDirMove
|
return fs.ErrorCantDirMove
|
||||||
}
|
}
|
||||||
|
srcPath := path.Join(srcFs.root, srcRemote)
|
||||||
|
dstPath := path.Join(f.root, dstRemote)
|
||||||
|
|
||||||
// Check if destination exists
|
// Check if destination exists
|
||||||
ok, err := f.dirExists(f.root)
|
ok, err := f.dirExists(dstPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "DirMove dirExists dst failed")
|
return errors.Wrap(err, "DirMove dirExists dst failed")
|
||||||
}
|
}
|
||||||
|
@ -408,31 +410,19 @@ func (f *Fs) DirMove(src fs.Fs) error {
|
||||||
return fs.ErrorDirExists
|
return fs.ErrorDirExists
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refuse to move to or from the root
|
|
||||||
if f.root == "" || srcFs.root == "" {
|
|
||||||
fs.Debugf(src, "DirMove error: Can't move root")
|
|
||||||
return errors.New("can't move root directory")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the parent directory exists
|
// Make sure the parent directory exists
|
||||||
// err = f.mkParentDir(f.root)
|
err = f.mkdir(path.Dir(dstPath))
|
||||||
// if err != nil {
|
|
||||||
// return errors.Wrap(err, "DirMove mkParentDir dst failed")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Make sure the source directory exists
|
|
||||||
err = srcFs.mkdir(srcFs.root)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "DirMove mkdir src failed")
|
return errors.Wrap(err, "DirMove mkParentDir dst failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the move
|
// Do the move
|
||||||
err = f.sftpClient.Rename(
|
err = f.sftpClient.Rename(
|
||||||
srcFs.root,
|
srcPath,
|
||||||
f.root,
|
dstPath,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "DirMove Rename(%q,%q) failed", srcFs.root, f.root)
|
return errors.Wrapf(err, "DirMove Rename(%q,%q) failed", srcPath, dstPath)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue