fix: Handle folder move override (#22)

pull/3756/head
Laurynas Gadliauskas 2021-09-07 12:56:38 +03:00 committed by GitHub
parent 9f931d3d24
commit 853a5e5c5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 27 deletions

View File

@ -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.

View File

@ -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)
}