fix: Handle folder move override (#22)
parent
9f931d3d24
commit
853a5e5c5e
|
@ -1,7 +1,9 @@
|
|||
package fileutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
@ -16,8 +18,14 @@ func MoveFile(fs afero.Fs, src, dst string) error {
|
|||
if fs.Rename(src, dst) == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
info, err := fs.Stat(src)
|
||||
if err == nil && info.IsDir() {
|
||||
return CopyFolder(fs, src, dst)
|
||||
}
|
||||
|
||||
// fallback
|
||||
err := CopyFile(fs, src, dst)
|
||||
err = CopyFile(fs, src, dst)
|
||||
if err != nil {
|
||||
_ = fs.Remove(dst)
|
||||
return err
|
||||
|
@ -71,6 +79,40 @@ func CopyFile(fs afero.Fs, source, dest string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// CopyFolder copies a folder to destination and returns
|
||||
// an error if any. If the destination already exists,
|
||||
// it get overriden.
|
||||
func CopyFolder(fs afero.Fs, source, dest string) error {
|
||||
tmpDest := ""
|
||||
_, err := fs.Stat(dest)
|
||||
if err == nil {
|
||||
// destination already exists - rename it so that src
|
||||
// could be moved to its place
|
||||
tmpDest = fmt.Sprintf("%s.%d", dest, rand.Intn(9999))
|
||||
err = fs.Rename(dest, tmpDest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
// unknown error, return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = fs.Rename(source, dest); err != nil {
|
||||
// if moving fails and we renamed an existing destination
|
||||
// in the previous step, then restore its name
|
||||
if tmpDest != "" {
|
||||
fs.Rename(tmpDest, dest)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// if moving was successful, delete the renamed dest
|
||||
_ = fs.Remove(tmpDest)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommonPrefix returns common directory path of provided files
|
||||
func CommonPrefix(sep byte, paths ...string) string {
|
||||
// Handle special cases.
|
||||
|
|
|
@ -415,6 +415,32 @@ func patchAction(ctx context.Context, action, src, dst string, d *data, fileCach
|
|||
}
|
||||
|
||||
return fileutils.Copy(d.user.Fs, src, dst)
|
||||
case "rename":
|
||||
if !d.user.Perm.Rename {
|
||||
return errors.ErrPermissionDenied
|
||||
}
|
||||
src = path.Clean("/" + src)
|
||||
dst = path.Clean("/" + dst)
|
||||
|
||||
file, err := files.NewFileInfo(files.FileOptions{
|
||||
Fs: d.user.Fs,
|
||||
Path: src,
|
||||
Modify: d.user.Perm.Modify,
|
||||
Expand: false,
|
||||
ReadHeader: false,
|
||||
Checker: d,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete thumbnails
|
||||
err = delThumbs(ctx, fileCache, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fileutils.MoveFile(d.user.Fs, src, dst)
|
||||
case "unarchive":
|
||||
if !d.user.Perm.Create {
|
||||
return errors.ErrPermissionDenied
|
||||
|
@ -459,32 +485,6 @@ func patchAction(ctx context.Context, action, src, dst string, d *data, fileCach
|
|||
return errors.ErrInvalidRequestParams
|
||||
}
|
||||
return nil
|
||||
case "rename":
|
||||
if !d.user.Perm.Rename {
|
||||
return errors.ErrPermissionDenied
|
||||
}
|
||||
src = path.Clean("/" + src)
|
||||
dst = path.Clean("/" + dst)
|
||||
|
||||
file, err := files.NewFileInfo(files.FileOptions{
|
||||
Fs: d.user.Fs,
|
||||
Path: src,
|
||||
Modify: d.user.Perm.Modify,
|
||||
Expand: false,
|
||||
ReadHeader: false,
|
||||
Checker: d,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete thumbnails
|
||||
err = delThumbs(ctx, fileCache, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fileutils.MoveFile(d.user.Fs, src, dst)
|
||||
default:
|
||||
return fmt.Errorf("unsupported action %s: %w", action, errors.ErrInvalidRequestParams)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue