Skip to content

Commit

Permalink
fix: regexp rename error (close #4644 in #4653)
Browse files Browse the repository at this point in the history
Co-authored-by: Andy Hsu <i@nn.ci>
  • Loading branch information
varg1714 and xhofe authored Jun 26, 2023
1 parent 21b8e7f commit e9c74f9
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 150 deletions.
211 changes: 211 additions & 0 deletions server/handles/fsbatch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package handles

import (
"fmt"
"regexp"

"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/fs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/pkg/generic"
"github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)

type BatchRenameReq struct {
SrcDir string `json:"src_dir"`
RenameObjects []struct {
SrcName string `json:"src_name"`
NewName string `json:"new_name"`
} `json:"rename_objects"`
}

func FsBatchRename(c *gin.Context) {
var req BatchRenameReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}
user := c.MustGet("user").(*model.User)
if !user.CanRename() {
common.ErrorResp(c, errs.PermissionDenied, 403)
return
}

reqPath, err := user.JoinPath(req.SrcDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}

meta, err := op.GetNearestMeta(reqPath)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
return
}
}
c.Set("meta", meta)
for _, renameObject := range req.RenameObjects {
if renameObject.SrcName == "" || renameObject.NewName == "" {
continue
}
filePath := fmt.Sprintf("%s/%s", reqPath, renameObject.SrcName)
if err := fs.Rename(c, filePath, renameObject.NewName); err != nil {
common.ErrorResp(c, err, 500)
return
}
}
common.SuccessResp(c)
}

type RecursiveMoveReq struct {
SrcDir string `json:"src_dir"`
DstDir string `json:"dst_dir"`
}

func FsRecursiveMove(c *gin.Context) {
var req RecursiveMoveReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}

user := c.MustGet("user").(*model.User)
if !user.CanMove() {
common.ErrorResp(c, errs.PermissionDenied, 403)
return
}
srcDir, err := user.JoinPath(req.SrcDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
dstDir, err := user.JoinPath(req.DstDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}

meta, err := op.GetNearestMeta(srcDir)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
return
}
}
c.Set("meta", meta)

rootFiles, err := fs.List(c, srcDir, &fs.ListArgs{})
if err != nil {
common.ErrorResp(c, err, 500)
return
}

// record the file path
filePathMap := make(map[model.Obj]string)
movingFiles := generic.NewQueue[model.Obj]()
for _, file := range rootFiles {
movingFiles.Push(file)
filePathMap[file] = srcDir
}

for !movingFiles.IsEmpty() {

movingFile := movingFiles.Pop()
movingFilePath := filePathMap[movingFile]
movingFileName := fmt.Sprintf("%s/%s", movingFilePath, movingFile.GetName())
if movingFile.IsDir() {
// directory, recursive move
subFilePath := movingFileName
subFiles, err := fs.List(c, movingFileName, &fs.ListArgs{Refresh: true})
if err != nil {
common.ErrorResp(c, err, 500)
return
}
for _, subFile := range subFiles {
movingFiles.Push(subFile)
filePathMap[subFile] = subFilePath
}
} else {

if movingFilePath == dstDir {
// same directory, don't move
continue
}

// move
err := fs.Move(c, movingFileName, dstDir, movingFiles.IsEmpty())
if err != nil {
common.ErrorResp(c, err, 500)
return
}
}

}

common.SuccessResp(c)
}

type RegexRenameReq struct {
SrcDir string `json:"src_dir"`
SrcNameRegex string `json:"src_name_regex"`
NewNameRegex string `json:"new_name_regex"`
}

func FsRegexRename(c *gin.Context) {
var req RegexRenameReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}
user := c.MustGet("user").(*model.User)
if !user.CanRename() {
common.ErrorResp(c, errs.PermissionDenied, 403)
return
}

reqPath, err := user.JoinPath(req.SrcDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}

meta, err := op.GetNearestMeta(reqPath)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
return
}
}
c.Set("meta", meta)

srcRegexp, err := regexp.Compile(req.SrcNameRegex)
if err != nil {
common.ErrorResp(c, err, 500)
return
}

files, err := fs.List(c, reqPath, &fs.ListArgs{})
if err != nil {
common.ErrorResp(c, err, 500)
return
}

for _, file := range files {

if srcRegexp.MatchString(file.GetName()) {
filePath := fmt.Sprintf("%s/%s", reqPath, file.GetName())
newFileName := srcRegexp.ReplaceAllString(file.GetName(), req.NewNameRegex)
if err := fs.Rename(c, filePath, newFileName); err != nil {
common.ErrorResp(c, err, 500)
return
}
}

}

common.SuccessResp(c)
}
150 changes: 0 additions & 150 deletions server/handles/fsmanage.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"io"
stdpath "path"
"regexp"

"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/fs"
Expand Down Expand Up @@ -96,94 +95,6 @@ func FsMove(c *gin.Context) {
common.SuccessResp(c)
}

type RecursiveMoveReq struct {
SrcDir string `json:"src_dir"`
DstDir string `json:"dst_dir"`
}

func FsRecursiveMove(c *gin.Context) {
var req RecursiveMoveReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}

user := c.MustGet("user").(*model.User)
if !user.CanMove() {
common.ErrorResp(c, errs.PermissionDenied, 403)
return
}
srcDir, err := user.JoinPath(req.SrcDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
dstDir, err := user.JoinPath(req.DstDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}

meta, err := op.GetNearestMeta(srcDir)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
return
}
}
c.Set("meta", meta)

rootFiles, err := fs.List(c, srcDir, &fs.ListArgs{})
if err != nil {
common.ErrorResp(c, err, 500)
return
}

// record the file path
filePathMap := make(map[model.Obj]string)
movingFiles := generic.NewQueue[model.Obj]()
for _, file := range rootFiles {
movingFiles.Push(file)
filePathMap[file] = srcDir
}

for !movingFiles.IsEmpty() {

movingFile := movingFiles.Pop()
movingFilePath := filePathMap[movingFile]
movingFileName := fmt.Sprintf("%s/%s", movingFilePath, movingFile.GetName())
if movingFile.IsDir() {
// directory, recursive move
subFilePath := movingFileName
subFiles, err := fs.List(c, movingFileName, &fs.ListArgs{Refresh: true})
if err != nil {
common.ErrorResp(c, err, 500)
return
}
for _, subFile := range subFiles {
movingFiles.Push(subFile)
filePathMap[subFile] = subFilePath
}
} else {

if movingFilePath == dstDir {
// same directory, don't move
continue
}

// move
err := fs.Move(c, movingFileName, dstDir, movingFiles.IsEmpty())
if err != nil {
common.ErrorResp(c, err, 500)
return
}
}

}

common.SuccessResp(c)
}

func FsCopy(c *gin.Context) {
var req MoveCopyReq
if err := c.ShouldBind(&req); err != nil {
Expand Down Expand Up @@ -255,67 +166,6 @@ func FsRename(c *gin.Context) {
common.SuccessResp(c)
}

type RegexRenameReq struct {
SrcDir string `json:"src_dir"`
SrcNameRegex string `json:"src_name_regex"`
NewNameRegex string `json:"new_name_regex"`
}

func FsRegexRename(c *gin.Context) {
var req RegexRenameReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}
user := c.MustGet("user").(*model.User)
if !user.CanRename() {
common.ErrorResp(c, errs.PermissionDenied, 403)
return
}

reqPath, err := user.JoinPath(req.SrcDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}

meta, err := op.GetNearestMeta(reqPath)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
return
}
}
c.Set("meta", meta)

srcRegexp, err := regexp.Compile(req.SrcNameRegex)
if err != nil {
common.ErrorResp(c, err, 500)
return
}

files, err := fs.List(c, reqPath, &fs.ListArgs{})
if err != nil {
common.ErrorResp(c, err, 500)
return
}

for _, file := range files {

if srcRegexp.MatchString(file.GetName()) {
filePath := fmt.Sprintf("%s/%s", reqPath, file.GetName())
newFileName := srcRegexp.ReplaceAllString(file.GetName(), req.NewNameRegex)
if err := fs.Rename(c, filePath, newFileName); err != nil {
common.ErrorResp(c, err, 500)
return
}
}

}

common.SuccessResp(c)
}

type RemoveReq struct {
Dir string `json:"dir"`
Names []string `json:"names"`
Expand Down
1 change: 1 addition & 0 deletions server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func _fs(g *gin.RouterGroup) {
g.Any("/dirs", handles.FsDirs)
g.POST("/mkdir", handles.FsMkdir)
g.POST("/rename", handles.FsRename)
g.POST("/batch_rename", handles.FsBatchRename)
g.POST("/regex_rename", handles.FsRegexRename)
g.POST("/move", handles.FsMove)
g.POST("/recursive_move", handles.FsRecursiveMove)
Expand Down

0 comments on commit e9c74f9

Please sign in to comment.