local fs rename: if it fails with a cross device error try a copy

I don't want to add a new setting for this, at least until we get the
first complain for a slow rename :)

Fixes #440
This commit is contained in:
Nicola Murino 2021-05-27 20:14:12 +02:00
parent 3b46e6a6fb
commit e1bf46c6a5
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
4 changed files with 32 additions and 9 deletions

View file

@ -1,7 +0,0 @@
package vfs
import "syscall"
func (fi FileInfo) getFileInfoSys() interface{} {
return syscall.Win32FileAttributeData{}
}

View file

@ -11,6 +11,7 @@ import (
"time"
"github.com/eikenb/pipeat"
fscopy "github.com/otiai10/copy"
"github.com/pkg/sftp"
"github.com/rs/xid"
@ -98,8 +99,14 @@ func (*OsFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
}
// Rename renames (moves) source to target
func (*OsFs) Rename(source, target string) error {
return os.Rename(source, target)
func (fs *OsFs) Rename(source, target string) error {
err := os.Rename(source, target)
if err != nil && isCrossDeviceError(err) {
fsLog(fs, logger.LevelWarn, "cross device error detected while renaming %#v -> %#v. Trying a copy, this could take a long time",
source, target)
return fscopy.Copy(source, target)
}
return err
}
// Remove removes the named file or (empty) directory.

View file

@ -3,8 +3,11 @@
package vfs
import (
"errors"
"os"
"syscall"
"golang.org/x/sys/unix"
)
var (
@ -27,3 +30,7 @@ func (fi FileInfo) getFileInfoSys() interface{} {
Uid: uint32(defaultUID),
Gid: uint32(defaultGID)}
}
func isCrossDeviceError(err error) bool {
return errors.Is(err, unix.EXDEV)
}

16
vfs/sys_windows.go Normal file
View file

@ -0,0 +1,16 @@
package vfs
import (
"errors"
"syscall"
"golang.org/x/sys/windows"
)
func (fi FileInfo) getFileInfoSys() interface{} {
return syscall.Win32FileAttributeData{}
}
func isCrossDeviceError(err error) bool {
return errors.Is(err, windows.ERROR_NOT_SAME_DEVICE)
}