forked from TrueCloudLab/rclone
fs: make Copy and Move return the destination object if possible
This commit is contained in:
parent
11332a19a0
commit
7d15c33e42
2 changed files with 31 additions and 23 deletions
|
@ -273,10 +273,14 @@ var _ MimeTyper = (*overrideRemoteObject)(nil)
|
||||||
|
|
||||||
// Copy src object to dst or f if nil. If dst is nil then it uses
|
// Copy src object to dst or f if nil. If dst is nil then it uses
|
||||||
// remote as the name of the new object.
|
// remote as the name of the new object.
|
||||||
func Copy(f Fs, dst Object, remote string, src Object) (err error) {
|
//
|
||||||
|
// It returns the destination object if possible. Note that this may
|
||||||
|
// be nil.
|
||||||
|
func Copy(f Fs, dst Object, remote string, src Object) (newDst Object, err error) {
|
||||||
|
newDst = dst
|
||||||
if Config.DryRun {
|
if Config.DryRun {
|
||||||
Logf(src, "Not copying as --dry-run")
|
Logf(src, "Not copying as --dry-run")
|
||||||
return nil
|
return newDst, nil
|
||||||
}
|
}
|
||||||
maxTries := Config.LowLevelRetries
|
maxTries := Config.LowLevelRetries
|
||||||
tries := 0
|
tries := 0
|
||||||
|
@ -298,7 +302,6 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
|
||||||
// is same underlying remote
|
// is same underlying remote
|
||||||
actionTaken = "Copied (server side copy)"
|
actionTaken = "Copied (server side copy)"
|
||||||
if doCopy := f.Features().Copy; doCopy != nil && SameConfig(src.Fs(), f) {
|
if doCopy := f.Features().Copy; doCopy != nil && SameConfig(src.Fs(), f) {
|
||||||
var newDst Object
|
|
||||||
newDst, err = doCopy(src, remote)
|
newDst, err = doCopy(src, remote)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
dst = newDst
|
dst = newDst
|
||||||
|
@ -328,6 +331,7 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
|
||||||
}
|
}
|
||||||
closeErr := in.Close()
|
closeErr := in.Close()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
newDst = dst
|
||||||
err = closeErr
|
err = closeErr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +351,7 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Stats.Error(err)
|
Stats.Error(err)
|
||||||
Errorf(src, "Failed to copy: %v", err)
|
Errorf(src, "Failed to copy: %v", err)
|
||||||
return err
|
return newDst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify sizes are the same after transfer
|
// Verify sizes are the same after transfer
|
||||||
|
@ -356,7 +360,7 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
|
||||||
Errorf(dst, "%v", err)
|
Errorf(dst, "%v", err)
|
||||||
Stats.Error(err)
|
Stats.Error(err)
|
||||||
removeFailedCopy(dst)
|
removeFailedCopy(dst)
|
||||||
return err
|
return newDst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify hashes are the same after transfer - ignoring blank hashes
|
// Verify hashes are the same after transfer - ignoring blank hashes
|
||||||
|
@ -379,21 +383,25 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
|
||||||
Errorf(dst, "%v", err)
|
Errorf(dst, "%v", err)
|
||||||
Stats.Error(err)
|
Stats.Error(err)
|
||||||
removeFailedCopy(dst)
|
removeFailedCopy(dst)
|
||||||
return err
|
return newDst, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Infof(src, actionTaken)
|
Infof(src, actionTaken)
|
||||||
return err
|
return newDst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move src object to dst or fdst if nil. If dst is nil then it uses
|
// Move src object to dst or fdst if nil. If dst is nil then it uses
|
||||||
// remote as the name of the new object.
|
// remote as the name of the new object.
|
||||||
func Move(fdst Fs, dst Object, remote string, src Object) (err error) {
|
//
|
||||||
|
// It returns the destination object if possible. Note that this may
|
||||||
|
// be nil.
|
||||||
|
func Move(fdst Fs, dst Object, remote string, src Object) (newDst Object, err error) {
|
||||||
|
newDst = dst
|
||||||
if Config.DryRun {
|
if Config.DryRun {
|
||||||
Logf(src, "Not moving as --dry-run")
|
Logf(src, "Not moving as --dry-run")
|
||||||
return nil
|
return newDst, nil
|
||||||
}
|
}
|
||||||
// See if we have Move available
|
// See if we have Move available
|
||||||
if doMove := fdst.Features().Move; doMove != nil && SameConfig(src.Fs(), fdst) {
|
if doMove := fdst.Features().Move; doMove != nil && SameConfig(src.Fs(), fdst) {
|
||||||
|
@ -401,31 +409,31 @@ func Move(fdst Fs, dst Object, remote string, src Object) (err error) {
|
||||||
if dst != nil {
|
if dst != nil {
|
||||||
err = DeleteFile(dst)
|
err = DeleteFile(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return newDst, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Move dst <- src
|
// Move dst <- src
|
||||||
_, err := doMove(src, remote)
|
newDst, err = doMove(src, remote)
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
Infof(src, "Moved (server side)")
|
Infof(src, "Moved (server side)")
|
||||||
return nil
|
return newDst, nil
|
||||||
case ErrorCantMove:
|
case ErrorCantMove:
|
||||||
Debugf(src, "Can't move, switching to copy")
|
Debugf(src, "Can't move, switching to copy")
|
||||||
default:
|
default:
|
||||||
Stats.Error(err)
|
Stats.Error(err)
|
||||||
Errorf(src, "Couldn't move: %v", err)
|
Errorf(src, "Couldn't move: %v", err)
|
||||||
return err
|
return newDst, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Move not found or didn't work so copy dst <- src
|
// Move not found or didn't work so copy dst <- src
|
||||||
err = Copy(fdst, dst, remote, src)
|
newDst, err = Copy(fdst, dst, remote, src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Errorf(src, "Not deleting source as copy failed: %v", err)
|
Errorf(src, "Not deleting source as copy failed: %v", err)
|
||||||
return err
|
return newDst, err
|
||||||
}
|
}
|
||||||
// Delete src if no error on copy
|
// Delete src if no error on copy
|
||||||
return DeleteFile(src)
|
return newDst, DeleteFile(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanServerSideMove returns true if fdst support server side moves or
|
// CanServerSideMove returns true if fdst support server side moves or
|
||||||
|
@ -458,7 +466,7 @@ func deleteFileWithBackupDir(dst Object, backupDir Fs) (err error) {
|
||||||
} else {
|
} else {
|
||||||
remoteWithSuffix := dst.Remote() + Config.Suffix
|
remoteWithSuffix := dst.Remote() + Config.Suffix
|
||||||
overwritten, _ := backupDir.NewObject(remoteWithSuffix)
|
overwritten, _ := backupDir.NewObject(remoteWithSuffix)
|
||||||
err = Move(backupDir, overwritten, remoteWithSuffix, dst)
|
_, err = Move(backupDir, overwritten, remoteWithSuffix, dst)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = dst.Remove()
|
err = dst.Remove()
|
||||||
|
@ -1665,7 +1673,7 @@ func Rcat(fdst Fs, dstFileName string, in io.ReadCloser, modTime time.Time) (dst
|
||||||
return dst, err
|
return dst, err
|
||||||
}
|
}
|
||||||
if !canStream {
|
if !canStream {
|
||||||
return dst, Copy(fdst, nil, dstFileName, dst)
|
return Copy(fdst, nil, dstFileName, dst)
|
||||||
}
|
}
|
||||||
return dst, nil
|
return dst, nil
|
||||||
}
|
}
|
||||||
|
@ -1763,7 +1771,7 @@ func moveOrCopyFile(fdst Fs, fsrc Fs, dstFileName string, srcFileName string, cp
|
||||||
|
|
||||||
if NeedTransfer(dstObj, srcObj) {
|
if NeedTransfer(dstObj, srcObj) {
|
||||||
Stats.Transferring(srcFileName)
|
Stats.Transferring(srcFileName)
|
||||||
err = Op(fdst, dstObj, dstFileName, srcObj)
|
_, err = Op(fdst, dstObj, dstFileName, srcObj)
|
||||||
Stats.DoneTransferring(srcFileName, err == nil)
|
Stats.DoneTransferring(srcFileName, err == nil)
|
||||||
} else {
|
} else {
|
||||||
Stats.Checking(srcFileName)
|
Stats.Checking(srcFileName)
|
||||||
|
|
|
@ -277,7 +277,7 @@ func (s *syncCopyMove) pairChecker(in ObjectPairChan, out ObjectPairChan, wg *sy
|
||||||
if pair.dst != nil && s.backupDir != nil {
|
if pair.dst != nil && s.backupDir != nil {
|
||||||
remoteWithSuffix := pair.dst.Remote() + s.suffix
|
remoteWithSuffix := pair.dst.Remote() + s.suffix
|
||||||
overwritten, _ := s.backupDir.NewObject(remoteWithSuffix)
|
overwritten, _ := s.backupDir.NewObject(remoteWithSuffix)
|
||||||
err := Move(s.backupDir, overwritten, remoteWithSuffix, pair.dst)
|
_, err := Move(s.backupDir, overwritten, remoteWithSuffix, pair.dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.processError(err)
|
s.processError(err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -344,9 +344,9 @@ func (s *syncCopyMove) pairCopyOrMove(in ObjectPairChan, fdst Fs, wg *sync.WaitG
|
||||||
src := pair.src
|
src := pair.src
|
||||||
Stats.Transferring(src.Remote())
|
Stats.Transferring(src.Remote())
|
||||||
if s.DoMove {
|
if s.DoMove {
|
||||||
err = Move(fdst, pair.dst, src.Remote(), src)
|
_, err = Move(fdst, pair.dst, src.Remote(), src)
|
||||||
} else {
|
} else {
|
||||||
err = Copy(fdst, pair.dst, src.Remote(), src)
|
_, err = Copy(fdst, pair.dst, src.Remote(), src)
|
||||||
}
|
}
|
||||||
s.processError(err)
|
s.processError(err)
|
||||||
Stats.DoneTransferring(src.Remote(), err == nil)
|
Stats.DoneTransferring(src.Remote(), err == nil)
|
||||||
|
@ -624,7 +624,7 @@ func (s *syncCopyMove) tryRename(src Object) bool {
|
||||||
dstOverwritten, _ := s.fdst.NewObject(src.Remote())
|
dstOverwritten, _ := s.fdst.NewObject(src.Remote())
|
||||||
|
|
||||||
// Rename dst to have name src.Remote()
|
// Rename dst to have name src.Remote()
|
||||||
err := Move(s.fdst, dstOverwritten, src.Remote(), dst)
|
_, err := Move(s.fdst, dstOverwritten, src.Remote(), dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Debugf(src, "Failed to rename to %q: %v", dst.Remote(), err)
|
Debugf(src, "Failed to rename to %q: %v", dst.Remote(), err)
|
||||||
return false
|
return false
|
||||||
|
|
Loading…
Add table
Reference in a new issue