diff --git a/glob/glob.go b/glob/glob.go index 0749bea0..ffcb5379 100644 --- a/glob/glob.go +++ b/glob/glob.go @@ -1,19 +1,25 @@ package glob -import "github.com/gobwas/glob" +import ( + "strings" + + "github.com/gobwas/glob" +) type Glob interface { Match(name string) bool + Prefix() string } type globber struct { - glob glob.Glob + pattern string + glob glob.Glob } func MustCompile(pattern string, separators ...rune) Glob { g := glob.MustCompile(pattern, separators...) - return &globber{glob: g} + return &globber{pattern: pattern, glob: g} } func Compile(pattern string, separators ...rune) (Glob, error) { @@ -22,13 +28,26 @@ func Compile(pattern string, separators ...rune) (Glob, error) { return nil, err } - return &globber{glob: g}, nil + return &globber{pattern: pattern, glob: g}, nil } func (g *globber) Match(name string) bool { return g.glob.Match(name) } +func (g *globber) Prefix() string { + return Prefix(g.pattern) +} + +func Prefix(pattern string) string { + index := strings.IndexAny(pattern, "*[{") + if index == -1 { + return pattern + } + + return strings.Clone(pattern[:index]) +} + // Match returns whether the name matches the glob pattern, also considering // one or several optionnal separator. An error is only returned if the pattern // is invalid. diff --git a/http/handler/filesystem.go b/http/handler/filesystem.go index 88d5c151..1bffccf5 100644 --- a/http/handler/filesystem.go +++ b/http/handler/filesystem.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/datarhei/core/v16/glob" "github.com/datarhei/core/v16/http/api" httpfs "github.com/datarhei/core/v16/http/fs" "github.com/datarhei/core/v16/http/handler/util" @@ -195,6 +196,14 @@ func (h *FSHandler) DeleteFiles(c echo.Context) error { return api.Err(http.StatusBadRequest, "", "a glob pattern is required") } + path := "/" + + if len(pattern) != 0 { + prefix := glob.Prefix(pattern) + index := strings.LastIndex(prefix, "/") + path = prefix[:index+1] + } + options := fs.ListOptions{ Pattern: pattern, } @@ -229,7 +238,7 @@ func (h *FSHandler) DeleteFiles(c echo.Context) error { } } - paths, _ := h.FS.Filesystem.RemoveList("/", options) + paths, _ := h.FS.Filesystem.RemoveList(path, options) if h.FS.Cache != nil { for _, path := range paths { @@ -256,6 +265,14 @@ func (h *FSHandler) ListFiles(c echo.Context) error { sortby := util.DefaultQuery(c, "sort", "none") order := util.DefaultQuery(c, "order", "asc") + path := "/" + + if len(pattern) != 0 { + prefix := glob.Prefix(pattern) + index := strings.LastIndex(prefix, "/") + path = prefix[:index+1] + } + options := fs.ListOptions{ Pattern: pattern, } @@ -290,7 +307,7 @@ func (h *FSHandler) ListFiles(c echo.Context) error { } } - files := h.FS.Filesystem.List("/", options) + files := h.FS.Filesystem.List(path, options) var sortFunc func(i, j int) bool diff --git a/io/fs/s3.go b/io/fs/s3.go index 316fd7ca..1d66e3ed 100644 --- a/io/fs/s3.go +++ b/io/fs/s3.go @@ -474,6 +474,7 @@ func (fs *s3Filesystem) RemoveList(path string, options ListOptions) ([]string, var totalSize int64 = 0 files := []string{} + recursive := false var compiledPattern glob.Glob var err error @@ -483,8 +484,14 @@ func (fs *s3Filesystem) RemoveList(path string, options ListOptions) ([]string, if err != nil { return nil, 0 } + + if strings.Contains(options.Pattern, "**") { + recursive = true + } } + recursive = true + objectsCh := make(chan minio.ObjectInfo) // Send object names that are needed to be removed to objectsCh @@ -495,7 +502,7 @@ func (fs *s3Filesystem) RemoveList(path string, options ListOptions) ([]string, WithVersions: false, WithMetadata: false, Prefix: path, - Recursive: true, + Recursive: recursive, MaxKeys: 0, StartAfter: "", UseV1: false, @@ -563,14 +570,21 @@ func (fs *s3Filesystem) List(path string, options ListOptions) []FileInfo { var compiledPattern glob.Glob var err error + recursive := false if len(options.Pattern) != 0 { compiledPattern, err = glob.Compile(options.Pattern, '/') if err != nil { return nil } + + if strings.Contains(options.Pattern, "**") { + recursive = true + } } + recursive = true + files := []FileInfo{} ctx, cancel := context.WithCancel(context.Background()) @@ -580,7 +594,7 @@ func (fs *s3Filesystem) List(path string, options ListOptions) []FileInfo { WithVersions: false, WithMetadata: false, Prefix: path, - Recursive: true, + Recursive: recursive, MaxKeys: 0, StartAfter: "", UseV1: false,