feat: add move directory
This commit is contained in:
parent
d4268f4ab1
commit
d3f307af6c
@ -123,6 +123,18 @@ func (s *Service) HandleRenameDirectory(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
params := req.Binded.(*RenameParams)
|
||||
srcPath := utils.NormalizePath(params.SrcPath)
|
||||
dstPath := utils.NormalizePath(params.DstPath)
|
||||
isDir := params.IsDir
|
||||
|
||||
oldPath := utils.FullPath(srcPath)
|
||||
newPath := utils.FullPath(dstPath)
|
||||
if err := s.FileSystemManager.RenameDirectory(req.Context(), oldPath, newPath, isDir); err != nil {
|
||||
logger.Error("rename dir %s to %s: %v", params.SrcPath, params.DstPath, err)
|
||||
return resp.InternalServerError("rename dir is failed, " + err.Error())
|
||||
}
|
||||
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
|
||||
@ -137,7 +137,7 @@ func (s *Service) HandleRenameFile(
|
||||
|
||||
err := s.FileSystemManager.RenameFile(req.Context(), srcPath, dstPath, isDir)
|
||||
if err != nil {
|
||||
logger.Error("rename %s to %s: %v", srcPath, dstPath, err)
|
||||
logger.Error("rename file %s to %s: %v", srcPath, dstPath, err)
|
||||
return resp.InternalServerError("rename file failed, " + err.Error())
|
||||
}
|
||||
|
||||
|
||||
134
engine/filesystem_reanme.go
Normal file
134
engine/filesystem_reanme.go
Normal file
@ -0,0 +1,134 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gosvc/logger"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"robotfs/utils"
|
||||
)
|
||||
|
||||
func (f *FileSystemManager) RenameDirectory(ctx context.Context, oldPath, newPath utils.FullPath, isDir bool) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
if err := f.canRename(oldPath, newPath, isDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oldEntry, err := f.FindEntry(ctx, oldPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s not found: %v", oldPath, err)
|
||||
}
|
||||
|
||||
moveErr := f.moveEntry(ctx, oldPath, oldEntry, newPath)
|
||||
if moveErr != nil {
|
||||
return fmt.Errorf("%s move error: %v", oldPath, moveErr)
|
||||
}
|
||||
|
||||
if err := utils.Move(f.root, string(oldPath), string(newPath)); err != nil {
|
||||
return fmt.Errorf("move file data failed: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) canRename(source, target utils.FullPath, isDir bool) error {
|
||||
if string(source) == "/" {
|
||||
return fmt.Errorf("mv: cannot move root directory")
|
||||
}
|
||||
|
||||
if isDir && strings.HasPrefix(string(target), string(source)) {
|
||||
return fmt.Errorf("mv: can not move directory to a subdirectory if itself")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) moveEntry(ctx context.Context, oldPath utils.FullPath, entry *utils.Entry, newPath utils.FullPath) error {
|
||||
if err := f.moveSelfEntry(ctx, oldPath, entry, newPath, func() error {
|
||||
if entry.IsDir {
|
||||
if err := f.moveFolderSubEntries(ctx, oldPath, newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return fmt.Errorf("fail to move %s => %s: %v", oldPath, newPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) moveFolderSubEntries(ctx context.Context, oldPath utils.FullPath, newPath utils.FullPath) error {
|
||||
logger.Info("moving folder %s => %s", oldPath, newPath)
|
||||
|
||||
lastFileName := ""
|
||||
includeLastFile := false
|
||||
for {
|
||||
entries := make([]*utils.Entry, 0, 1000)
|
||||
lastFileName, err := f.doListDirectoryEntries(ctx, oldPath, lastFileName, includeLastFile, 1000, func(entry *utils.Entry) bool {
|
||||
entries = append(entries, entry)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, item := range entries {
|
||||
itemOldPath := oldPath.Child(item.FullPath.Name())
|
||||
itemNewPath := newPath.Child(item.FullPath.Name())
|
||||
err := f.moveEntry(ctx, itemOldPath, item, itemNewPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if lastFileName == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) moveSelfEntry(ctx context.Context, oldPath utils.FullPath, entry *utils.Entry, newPath utils.FullPath, moveFolderSubEntries func() error) error {
|
||||
logger.Info("moving entry %s => %s", oldPath, newPath)
|
||||
|
||||
if oldPath == newPath {
|
||||
logger.Info("skip moving entry %s => %s", oldPath, newPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
newEntry := &utils.Entry{
|
||||
FullPath: newPath,
|
||||
IsDir: entry.IsDir,
|
||||
Size: entry.Size,
|
||||
CreateTime: time.Now().Unix(),
|
||||
S3Key: entry.S3Key,
|
||||
ContentType: entry.ContentType,
|
||||
Etag: entry.Etag,
|
||||
VersionID: entry.VersionID,
|
||||
LastModificationTime: time.Now().Unix(),
|
||||
Extended: entry.Extended,
|
||||
}
|
||||
|
||||
if createErr := f.meta.InsertEntry(ctx, newEntry); createErr != nil {
|
||||
return createErr
|
||||
}
|
||||
|
||||
if moveFolderSubEntries != nil {
|
||||
if moveChildrenErr := moveFolderSubEntries(); moveChildrenErr != nil {
|
||||
return moveChildrenErr
|
||||
}
|
||||
}
|
||||
|
||||
deleteErr := f.meta.DeleteEntry(ctx, oldPath)
|
||||
if deleteErr != nil {
|
||||
return deleteErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user