fs: make Copy and Move return the destination object if possible

s3-about
Nick Craig-Wood 2017-12-01 15:31:20 +00:00
parent 11332a19a0
commit 7d15c33e42
2 changed files with 31 additions and 23 deletions

View File

@ -273,10 +273,14 @@ var _ MimeTyper = (*overrideRemoteObject)(nil)
// Copy src object to dst or f if nil. If dst is nil then it uses
// 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 {
Logf(src, "Not copying as --dry-run")
return nil
return newDst, nil
}
maxTries := Config.LowLevelRetries
tries := 0
@ -298,7 +302,6 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
// is same underlying remote
actionTaken = "Copied (server side copy)"
if doCopy := f.Features().Copy; doCopy != nil && SameConfig(src.Fs(), f) {
var newDst Object
newDst, err = doCopy(src, remote)
if err == nil {
dst = newDst
@ -328,6 +331,7 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
}
closeErr := in.Close()
if err == nil {
newDst = dst
err = closeErr
}
}
@ -347,7 +351,7 @@ func Copy(f Fs, dst Object, remote string, src Object) (err error) {
if err != nil {
Stats.Error(err)
Errorf(src, "Failed to copy: %v", err)
return err
return newDst, err
}
// 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)
Stats.Error(err)
removeFailedCopy(dst)
return err
return newDst, err
}
// 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)
Stats.Error(err)
removeFailedCopy(dst)
return err
return newDst, err
}
}
}
Infof(src, actionTaken)
return err
return newDst, err
}
// Move src object to dst or fdst if nil. If dst is nil then it uses
// 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 {
Logf(src, "Not moving as --dry-run")
return nil
return newDst, nil
}
// See if we have Move available
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 {
err = DeleteFile(dst)
if err != nil {
return err
return newDst, err
}
}
// Move dst <- src
_, err := doMove(src, remote)
newDst, err = doMove(src, remote)
switch err {
case nil:
Infof(src, "Moved (server side)")
return nil
return newDst, nil
case ErrorCantMove:
Debugf(src, "Can't move, switching to copy")
default:
Stats.Error(err)
Errorf(src, "Couldn't move: %v", err)
return err
return newDst, err
}
}
// 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 {
Errorf(src, "Not deleting source as copy failed: %v", err)
return err
return newDst, err
}
// Delete src if no error on copy
return DeleteFile(src)
return newDst, DeleteFile(src)
}
// CanServerSideMove returns true if fdst support server side moves or
@ -458,7 +466,7 @@ func deleteFileWithBackupDir(dst Object, backupDir Fs) (err error) {
} else {
remoteWithSuffix := dst.Remote() + Config.Suffix
overwritten, _ := backupDir.NewObject(remoteWithSuffix)
err = Move(backupDir, overwritten, remoteWithSuffix, dst)
_, err = Move(backupDir, overwritten, remoteWithSuffix, dst)
}
} else {
err = dst.Remove()
@ -1665,7 +1673,7 @@ func Rcat(fdst Fs, dstFileName string, in io.ReadCloser, modTime time.Time) (dst
return dst, err
}
if !canStream {
return dst, Copy(fdst, nil, dstFileName, dst)
return Copy(fdst, nil, dstFileName, dst)
}
return dst, nil
}
@ -1763,7 +1771,7 @@ func moveOrCopyFile(fdst Fs, fsrc Fs, dstFileName string, srcFileName string, cp
if NeedTransfer(dstObj, srcObj) {
Stats.Transferring(srcFileName)
err = Op(fdst, dstObj, dstFileName, srcObj)
_, err = Op(fdst, dstObj, dstFileName, srcObj)
Stats.DoneTransferring(srcFileName, err == nil)
} else {
Stats.Checking(srcFileName)

View File

@ -277,7 +277,7 @@ func (s *syncCopyMove) pairChecker(in ObjectPairChan, out ObjectPairChan, wg *sy
if pair.dst != nil && s.backupDir != nil {
remoteWithSuffix := pair.dst.Remote() + s.suffix
overwritten, _ := s.backupDir.NewObject(remoteWithSuffix)
err := Move(s.backupDir, overwritten, remoteWithSuffix, pair.dst)
_, err := Move(s.backupDir, overwritten, remoteWithSuffix, pair.dst)
if err != nil {
s.processError(err)
} else {
@ -344,9 +344,9 @@ func (s *syncCopyMove) pairCopyOrMove(in ObjectPairChan, fdst Fs, wg *sync.WaitG
src := pair.src
Stats.Transferring(src.Remote())
if s.DoMove {
err = Move(fdst, pair.dst, src.Remote(), src)
_, err = Move(fdst, pair.dst, src.Remote(), src)
} else {
err = Copy(fdst, pair.dst, src.Remote(), src)
_, err = Copy(fdst, pair.dst, src.Remote(), src)
}
s.processError(err)
Stats.DoneTransferring(src.Remote(), err == nil)
@ -624,7 +624,7 @@ func (s *syncCopyMove) tryRename(src Object) bool {
dstOverwritten, _ := s.fdst.NewObject(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 {
Debugf(src, "Failed to rename to %q: %v", dst.Remote(), err)
return false