Skip to content

fix: forward windows option to basename in matchBase#179

Open
chatman-media wants to merge 1 commit into
micromatch:masterfrom
chatman-media:fix/matchbase-windows-backslash
Open

fix: forward windows option to basename in matchBase#179
chatman-media wants to merge 1 commit into
micromatch:masterfrom
chatman-media:fix/matchbase-windows-backslash

Conversation

@chatman-media

Copy link
Copy Markdown

What

picomatch.matchBase no longer honors the windows option, so backslash-separated paths are not split into segments when matching a basename pattern with { matchBase: true, windows: true }.

const picomatch = require('picomatch');

picomatch.isMatch('a\\b\\c\\foo.md', '*.md', { matchBase: true, windows: true });
//=> false  (expected: true)

picomatch.matchBase('foo\\bar.js', '*.js', { windows: true });
//=> false  (expected: true)

Forward-slash paths work as expected; only backslash separators are affected.

Why

When windows: true, the parser builds a regex whose path-segment class excludes both separators ([^\\/]), so a multi-segment backslash path like a\b\c\foo.md can't match a single-segment pattern like *.md directly. Matching then falls back to picomatch.matchBase, which is supposed to test the basename of the input.

picomatch.test still passes the posix/windows flag to matchBase:

match = picomatch.matchBase(input, regex, options, posix);

but in #64 (commit 2f25761, "Remove automatic windows detection") matchBase was changed from Node's path.basename to the internal utils.basename, and in the process:

  • the trailing posix parameter was dropped from the signature, and
  • utils.basename(input) was called without the { windows } flag.

utils.basename already supports { windows: true } (and is covered by tests in test/regex-features.js), so without the flag it only ever splits on /. For a backslash path it returns the whole string, which then fails the regex.

Fix

Restore the posix parameter (defaulting to options.windows, mirroring how picomatch.test derives it) and forward it to utils.basename:

picomatch.matchBase = (input, glob, options, posix = options && options.windows) => {
  const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
  return regex.test(utils.basename(input, { windows: posix }));
};

Minimal change; no behavior change for POSIX paths.

Tests

Added cases under options.matchBase in test/options.js covering backslash-separated paths with { matchBase: true, windows: true } and a direct matchBase(..., { windows: true }) call. Verified they fail without the fix and pass with it. Full suite green (npm run mocha → 1977 passing) and npm run lint clean.

`picomatch.matchBase` stopped honoring the `windows` option after the
switch from Node's `path.basename` to `utils.basename` (2f25761,
"Remove automatic windows detection"). The `posix` argument that
`picomatch.test` still passes was dropped from the signature, and
`utils.basename(input)` was called without the `{ windows }` flag, so
backslash-separated paths were never split into segments.

As a result `isMatch('a\\b\\c\\foo.md', '*.md', { matchBase: true,
windows: true })` returned `false` even though `utils.basename` already
supports `{ windows: true }` (and is tested for it).

Restore the `posix` parameter (defaulting to `options.windows`, as in
`picomatch.test`) and pass it through to `utils.basename`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant