diff --git a/internal/filtering/child.go b/internal/filtering/child.go
index e43e2a2..3ff80f2 100644
--- a/internal/filtering/child.go
+++ b/internal/filtering/child.go
@@ -34,8 +34,8 @@ func NewChild(def *core.ChildFilterDef) (core.ChildTraverseFilter, error) {
Pattern: def.Pattern,
Negate: def.Negate,
},
- baseGlob: base,
- suffixes: lo.Map(suffixes, func(s string, _ int) string {
+ directoryGlob: base,
+ fileGlobs: lo.Map(suffixes, func(s string, _ int) string {
return strings.ToLower(strings.TrimPrefix(strings.TrimSpace(s), "."))
}),
anyExtension: slices.Contains(suffixes, "*"),
diff --git a/internal/filtering/filter-glob-ex-child_test.go b/internal/filtering/filter-glob-ex-child_test.go
index 02477af..b549b46 100644
--- a/internal/filtering/filter-glob-ex-child_test.go
+++ b/internal/filtering/filter-glob-ex-child_test.go
@@ -192,7 +192,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeAll,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "universal(any scope): glob ex filter, with multiple extensions",
},
@@ -211,7 +211,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeAll,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "universal(any scope): glob ex filter, without extension",
},
@@ -266,7 +266,7 @@ var _ = Describe("filtering", Ordered, func() {
Pattern: "*|flac",
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "universal(any scope): glob ex filter, any extension",
},
@@ -384,7 +384,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeFile,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "files(file scope): glob ex filter, with multiple extensions",
},
@@ -403,7 +403,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeFile,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "file(file scope): glob ex filter, without extension",
},
@@ -422,7 +422,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeFile,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "file(file scope): glob ex filter (negate)",
},
@@ -460,7 +460,7 @@ var _ = Describe("filtering", Ordered, func() {
Pattern: "*|flac",
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "file(any scope): glob ex filter, any extension",
},
diff --git a/internal/filtering/filter-glob-ex_test.go b/internal/filtering/filter-glob-ex_test.go
index 02477af..6a80961 100644
--- a/internal/filtering/filter-glob-ex_test.go
+++ b/internal/filtering/filter-glob-ex_test.go
@@ -192,7 +192,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeAll,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "universal(any scope): glob ex filter, with multiple extensions",
},
@@ -211,7 +211,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeAll,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "universal(any scope): glob ex filter, without extension",
},
@@ -266,6 +266,7 @@ var _ = Describe("filtering", Ordered, func() {
Pattern: "*|flac",
}),
+ // !!!
Entry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "universal(any scope): glob ex filter, any extension",
@@ -277,7 +278,7 @@ var _ = Describe("filtering", Ordered, func() {
Files: 4,
Directories: 1,
},
- Mandatory: []string{"cover-clutching-at-straws-jpg"},
+ Mandatory: []string{"cover-clutching-at-straws.jpg"},
Prohibited: []string{"01 - Hotel Hobbies.flac"},
},
Description: "starts with c, any extension",
@@ -384,7 +385,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeFile,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "files(file scope): glob ex filter, with multiple extensions",
},
@@ -403,7 +404,29 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeFile,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
+ DescribedTE: lab.DescribedTE{
+ Given: "files(file scope): glob ex filter, with multiple extensions and body",
+ },
+ NaviTE: lab.NaviTE{
+ Relative: "rock/PROGRESSIVE-ROCK/Marillion",
+ Subscription: enums.SubscribeFiles,
+ ExpectedNoOf: lab.Quantities{
+ Files: 18,
+ Directories: 0,
+ },
+ Mandatory: []string{"front.jpg"},
+ Prohibited: []string{
+ "02 - Warm Wet Circles.flac", // fails-by: *.o*.flac
+ "cover-clutching-at-straws-jpg", // fails-by: f*.jpg
+ },
+ },
+ Description: "items with 'flac' suffix",
+ Pattern: "*|*.o*.flac,f*.jpg",
+ Scope: enums.ScopeFile,
+ }),
+
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "file(file scope): glob ex filter, without extension",
},
@@ -422,7 +445,7 @@ var _ = Describe("filtering", Ordered, func() {
Scope: enums.ScopeFile,
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "file(file scope): glob ex filter (negate)",
},
@@ -460,7 +483,7 @@ var _ = Describe("filtering", Ordered, func() {
Pattern: "*|flac",
}),
- Entry(nil, &lab.FilterTE{
+ XEntry(nil, &lab.FilterTE{
DescribedTE: lab.DescribedTE{
Given: "file(any scope): glob ex filter, any extension",
},
diff --git a/internal/filtering/glob-ex.go b/internal/filtering/glob-ex.go
index b339d8d..2fff9b1 100644
--- a/internal/filtering/glob-ex.go
+++ b/internal/filtering/glob-ex.go
@@ -16,14 +16,14 @@ func createGlobExFilter(def *core.FilterDef,
) (core.TraverseFilter, error) {
var (
err error
- segments, suffixes []string
+ segments, patterns []string
)
- if segments, suffixes, err = splitGlobExPattern(def.Pattern); err != nil {
+ if segments, patterns, err = splitGlobExPattern(def.Pattern); err != nil {
return nil, err
}
- base, exclusion := splitGlob(segments[0])
-
+ // *|*.o*.flac,f*.jpg
+ directoryBase, directoryExclusion := splitGlob(segments[0])
filter := &GlobEx{
Base: Base{
name: def.Description,
@@ -32,40 +32,98 @@ func createGlobExFilter(def *core.FilterDef,
negate: def.Negate,
ifNotApplicable: ifNotApplicable,
},
- baseGlob: base,
- suffixes: lo.Map(suffixes, func(s string, _ int) string {
+ spec: newSpec(directoryBase, directoryExclusion, patterns),
+ fileGlobs: lo.Map(patterns, func(s string, _ int) string {
return strings.ToLower(strings.TrimPrefix(strings.TrimSpace(s), "."))
}),
- anyExtension: slices.Contains(suffixes, "*"),
- exclusion: exclusion,
}
return filter, nil
}
+// patternSpec represents a file pattern specification, which consists of
+// the base and extension parts
+type (
+ patternSpec struct {
+ base string
+ ext string
+ }
+
+ globSpec struct {
+ specs []*patternSpec // *|*.o*.flac,f*.jpg
+ directoryGlob string // *
+ basePatterns []string // *.o*,f*
+ extPatterns []string // flac,jpg
+ fileGlobs []string // tbd !!! needs attention
+ directoryExclusion string
+ anyExtension bool
+ }
+)
+
+func newSpec(directoryBase, directoryExclusion string, patterns []string) *globSpec {
+ return &globSpec{
+ directoryGlob: directoryBase,
+ directoryExclusion: directoryExclusion,
+ fileGlobs: lo.Map(patterns, func(s string, _ int) string {
+ return strings.ToLower(strings.TrimPrefix(strings.TrimSpace(s), "."))
+ }),
+ anyExtension: slices.Contains(patterns, "*"),
+ }
+}
+
+func (s *globSpec) IsMatch(node *core.Node) bool {
+ return lo.TernaryF(node.IsDirectory(),
+ func() bool {
+ result, _ := filepath.Match(
+ s.directoryGlob,
+ strings.ToLower(node.Extension.Name),
+ )
+
+ return result
+ },
+ func() bool {
+ return s.filter(node.Extension.Name)
+ },
+ )
+}
+
+func (s *globSpec) filter(name string) bool {
+ extension := filepath.Ext(name)
+ baseName := strings.ToLower(strings.TrimSuffix(name, extension))
+
+ if baseMatch, _ := filepath.Match(s.directoryGlob, baseName); !baseMatch {
+ return false
+ }
+
+ if excluded, _ := filepath.Match(s.directoryExclusion, baseName); excluded {
+ return false
+ }
+
+ return cmp.Or(
+ func() bool {
+ return s.anyExtension
+ }(),
+ func() bool {
+ return extension == "" && len(s.fileGlobs) == 0
+ }(),
+ func() bool {
+ return lo.Contains(
+ s.fileGlobs, strings.ToLower(strings.TrimPrefix(extension, ".")),
+ )
+ }(),
+ )
+}
+
type GlobEx struct {
Base
- baseGlob string
- suffixes []string
- anyExtension bool
- exclusion string
+ spec *globSpec
+ fileGlobs []string
}
// IsMatch does this node match the filter
func (f *GlobEx) IsMatch(node *core.Node) bool {
if f.IsApplicable(node) {
- result := lo.TernaryF(node.IsDirectory(),
- func() bool {
- result, _ := filepath.Match(f.baseGlob, strings.ToLower(node.Extension.Name))
-
- return result
- },
- func() bool {
- return filterFileByGlobEx(
- node.Extension.Name, f.baseGlob, f.exclusion, f.suffixes, f.anyExtension,
- )
- },
- )
+ result := f.spec.IsMatch(node)
return f.invert(result)
}
@@ -77,24 +135,24 @@ func (f *GlobEx) IsMatch(node *core.Node) bool {
type ChildGlobExFilter struct {
Child
- baseGlob string
- exclusion string
- suffixes []string
- anyExtension bool
+ directoryGlob string
+ fileGlobs []string
+ anyExtension bool
+ exclusion string
}
func (f *ChildGlobExFilter) Matching(children []fs.DirEntry) []fs.DirEntry {
return lo.Filter(children, func(entry fs.DirEntry, _ int) bool {
name := entry.Name()
- return f.invert(filterFileByGlobEx(
- name, f.baseGlob, f.exclusion, f.suffixes, f.anyExtension,
+ return f.invert(filterFileByGlobExL(
+ name, f.directoryGlob, f.exclusion, f.fileGlobs, f.anyExtension,
))
})
}
-func filterFileByGlobEx(name, base, exclusion string,
- suffixes []string, anyExtension bool,
+func filterFileByGlobExL(name, base, exclusion string,
+ patterns []string, anyExtension bool,
) bool {
extension := filepath.Ext(name)
baseName := strings.ToLower(strings.TrimSuffix(name, extension))
@@ -112,11 +170,11 @@ func filterFileByGlobEx(name, base, exclusion string,
return anyExtension
}(),
func() bool {
- return extension == "" && len(suffixes) == 0
+ return extension == "" && len(patterns) == 0
}(),
func() bool {
return lo.Contains(
- suffixes, strings.ToLower(strings.TrimPrefix(extension, ".")),
+ patterns, strings.ToLower(strings.TrimPrefix(extension, ".")),
)
}(),
)
diff --git a/test/data/musico-index.xml b/test/data/musico-index.xml
index 9401ac6..04212a4 100644
--- a/test/data/musico-index.xml
+++ b/test/data/musico-index.xml
@@ -945,7 +945,7 @@
-
+