Skip to content

fix: match variable-depth ** alongside {placeholder} and excludeFiles globs#58

Open
mliem2k wants to merge 1 commit into
vercel-labs:mainfrom
mliem2k:fix/placeholder-double-star-matching
Open

fix: match variable-depth ** alongside {placeholder} and excludeFiles globs#58
mliem2k wants to merge 1 commit into
vercel-labs:mainfrom
mliem2k:fix/placeholder-double-star-matching

Conversation

@mliem2k

@mliem2k mliem2k commented Jul 12, 2026

Copy link
Copy Markdown

Pull Request Description

Fixes #56
Fixes #57

Both issues share the same root cause, per the reproduction steps in each: tryExtractPlaceholders() in src/core/path-matcher.ts required the pattern and the matched path to have the exact same number of /-separated segments. Since ** can legitimately match a variable number of segments, this equal-length check silently rejected any candidate where ** didn't happen to consume exactly one segment.

Relevant technical choices

Rather than special-casing or warning about ** next to a placeholder, this implements the "real fix" the reporter suggested: path segment matching (matchPatternSegments in path-matcher.ts) now backtracks through candidate consumption counts when it hits a ** pattern segment, trying each possible number of consumed path segments until the rest of the pattern (including any placeholders after the **) also matches. This is a standard backtracking glob-with-captures matcher; it replaces the old index-by-index walk in tryExtractPlaceholders.

excludeFiles matching in runner.ts (isFileExcluded) previously only supported exact-path and basename comparisons — it never actually ran patterns through glob matching, which is why **/-prefixed patterns (and any other wildcard syntax) never worked despite docs/reference/configuration.md documenting "**/*.test.ts" as valid. I added a new exported matchesPathPattern() in path-matcher.ts (reusing the same backtracking segment matcher) and call it from isFileExcluded as an additional check, so excludeFiles now supports the same *, ?, and ** glob syntax as paths, while keeping the existing exact-path/basename behavior for plain filenames unchanged.

Testing

  • Added unit tests in path-matcher.test.ts reproducing the exact ** next to a {placeholder} silently matches only one directory level (not all depths) #56 fixture tree/pattern (all three depths now match with correct placeholder values), a baseline check that plain ** without a placeholder still matches every depth, a multi-placeholder-consistency check with ** present, and direct tests of matchesPathPattern covering **/-prefixed, trailing-**, and literal patterns.
  • Added a regression test in runner.test.ts reproducing excludeFiles patterns prefixed with **/ are silently ignored (docs show **/*.test.ts as valid) #57's exclusion scenario end-to-end through run().
  • Updated the exclude-files e2e fixture to exclude via a **/-prefixed pattern instead of a full relative path, exercising the real tinyglobby-backed CLI path; confirmed (by temporarily reverting the source fix) that this fixture fails without the fix and passes with it.
  • Full suite (pnpm test, pnpm typecheck, pnpm check, pnpm test:e2e) passes.

Checklist

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated
  • A changeset has been added (run pnpm changeset in the project root if package files were modified)
  • I have reviewed this pull request (self-review)

Copilot AI review requested due to automatic review settings July 12, 2026 13:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…excludeFiles globs

Path matching required the pattern and matched path to have the same
number of segments when extracting placeholder values. This made any
`**` segment collapse to matching exactly one directory level whenever
the pattern also contained a `{placeholder}`, silently dropping
candidates at every other depth (vercel-labs#56).

`excludeFiles` entries hit the same equal-segment-count check, so a
`**/`-prefixed entry (as shown in docs/reference/configuration.md)
never matched and the file stayed in scope (vercel-labs#57).

Path segment matching now backtracks through candidate consumption
counts for `**`, so it can reconcile a variable-depth wildcard with
placeholder extraction and with plain excludeFiles glob patterns.
@mliem2k mliem2k force-pushed the fix/placeholder-double-star-matching branch from fe0e55a to 294e853 Compare July 12, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants