What's wrong
The fix for #114 (MaskPathSeparators, TextFilter/TextFilter.cs ~L406–428) replaces / and \ with U+E000 in both the pattern and the text before DotNet.Glob sees them. That lets * and ? cross slashes as intended, but it also removes DotNet.Glob's directory-wildcard handling of **, which only applies when ** sits between path separators. After masking, **/ is just ** followed by a literal private-use character, so it no longer means "zero or more path segments". Every pattern that uses the standard **/ form now matches nothing, including paths that fit it exactly.
Reproduction
Items ["src/a.cs", "src/x/a.cs", "docs/readme.md"], glob filter:
| Pattern |
HEAD (2ad72cb) |
Before the #114 fix (df1c960^) |
src/**/*.cs |
[] |
[src/a.cs, src/x/a.cs] |
**/*.cs |
[] |
[src/a.cs, src/x/a.cs] |
**/readme.md |
[] |
[docs/readme.md] |
IsMatch(..., Glob, ByWholeString) on HEAD returns false for ("src/a.cs","src/**/*.cs"), ("src/x/a.cs","src/**/*.cs"), ("src/a.cs","**/*.cs") and ("a.cs","**/*.cs"). All four returned true before the fix. Bare ** and src/** still match.
These results come from a console app that references TextFilter.csproj and was run against both commits. The test project has no test that uses **, so the regression went uncaught.
Why it matters
**/ is the most common way to write a recursive path glob. Anyone filtering file lists with it now gets an empty result and no error.
Suggested fix / acceptance criteria
Keep the #114 behaviour (*readme* matches docs/readme.md, AC* matches AC/DC) and make **/ mean "zero or more characters ending at a separator" again. Two ways to do it:
- Rewrite
** followed by a separator before masking, so the masked glob covers both the no-directory case and the "anything, then a separator" case.
- Translate the glob to a regex rather than relying on DotNet.Glob's separator semantics.
Tests to add:
src/**/*.cs matches src/a.cs and src/x/a.cs
**/*.cs matches a.cs and src/a.cs
**/readme.md matches docs/readme.md
GlobStarMatchesAcrossSlash, GlobFilterKeepsPathItems and GlobLiteralSlashInPatternStillMatchesSlashInText still pass
What's wrong
The fix for #114 (
MaskPathSeparators,TextFilter/TextFilter.cs~L406–428) replaces/and\with U+E000 in both the pattern and the text before DotNet.Glob sees them. That lets*and?cross slashes as intended, but it also removes DotNet.Glob's directory-wildcard handling of**, which only applies when**sits between path separators. After masking,**/is just**followed by a literal private-use character, so it no longer means "zero or more path segments". Every pattern that uses the standard**/form now matches nothing, including paths that fit it exactly.Reproduction
Items
["src/a.cs", "src/x/a.cs", "docs/readme.md"], glob filter:src/**/*.cs[][src/a.cs, src/x/a.cs]**/*.cs[][src/a.cs, src/x/a.cs]**/readme.md[][docs/readme.md]IsMatch(..., Glob, ByWholeString)on HEAD returnsfalsefor("src/a.cs","src/**/*.cs"),("src/x/a.cs","src/**/*.cs"),("src/a.cs","**/*.cs")and("a.cs","**/*.cs"). All four returnedtruebefore the fix. Bare**andsrc/**still match.These results come from a console app that references
TextFilter.csprojand was run against both commits. The test project has no test that uses**, so the regression went uncaught.Why it matters
**/is the most common way to write a recursive path glob. Anyone filtering file lists with it now gets an empty result and no error.Suggested fix / acceptance criteria
Keep the #114 behaviour (
*readme*matchesdocs/readme.md,AC*matchesAC/DC) and make**/mean "zero or more characters ending at a separator" again. Two ways to do it:**followed by a separator before masking, so the masked glob covers both the no-directory case and the "anything, then a separator" case.Tests to add:
src/**/*.csmatchessrc/a.csandsrc/x/a.cs**/*.csmatchesa.csandsrc/a.cs**/readme.mdmatchesdocs/readme.mdGlobStarMatchesAcrossSlash,GlobFilterKeepsPathItemsandGlobLiteralSlashInPatternStillMatchesSlashInTextstill pass