Glob walk: an anchor option, a directory taken as the name it is - #620
Open
ronleizrowice-ant wants to merge 2 commits into
Open
ronleizrowice-ant wants to merge 2 commits into
ronleizrowice-ant wants to merge 2 commits into
Conversation
The glob dialect has no escape, so a pattern cannot be aimed beneath a directory whose own name holds `[`, `*` or `?`: those characters are read as pattern. `walkGlobPattern`, `expandGlobPattern` and `expandReadDenyGlobLinux` take an `anchor`, a leading run of the path that is a name on disk. Only what follows it is compiled and matched. Without an anchor nothing changes, and nothing passes one yet.
The tail was cut off the pattern by the anchor's length alone, so a wrong anchor of the right length walked another directory and handed back what the tail matched there. An anchor that is empty or the root, that the pattern does not start with, or that ends inside a name now throws a TypeError. Thrown, not skipped: this feeds deny lists, and a skipped deny is lost. An anchored base can then never be the root, so the refusal of a pattern with no literal directory needs no exception for anchors.
This was referenced Sep 29, 2026
Open
ronleizrowice-ant
added a commit
that referenced
this pull request
Sep 30, 2026
The walk's budget (#607), its shared listings (#627) and its steps (#628) rewrite one code path, and the path entries of #620 to #622 sit on top of it. Everything above the walk is a generator now: the read-deny expansion, the function readDenyGlobExpander() returns, the allowRead expansion, the resolution of read path entries, and withOtherReadings(), which calls the expander once for each reading of an entry. The synchronous names finish those on the spot. In the walk the step comes first and the budget's clock is read after it, before the next listing. The deadline is wall time, so turns given to other work count against it: a wrap can be refused earlier for that, and a list is never cut short. The budget error is given its code around the delegated generator. An abort is raised by the driver and does not pass through there, so a wrap with a spent budget and an aborted signal rejects with the signal's reason. A wrap that starts over makes a new budget and new listings, and reads the new configuration's denyReadGlobBudget. In the scan's catch the abort is looked at first, then what ripgrep listed.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of three stacked pull requests that replace #608 (next: #621, the
{ path, literal: true }marker; then #622, entries read as the paths they spell).What
The glob dialect has no escape, so a pattern cannot be aimed beneath a directory whose own name holds
[,*or?:/w/[WIP] project/**/.envreads[WIP]as a class and finds nothing.walkGlobPatternandexpandGlobPatterntakeanchor, a leading run of the path that is a name on disk. Only what follows it is compiled and matched, and the walk starts at the anchor plus the tail's own base.expandReadDenyGlobLinuxpasses it on through a fourth parameteropts: { anchor? }.An anchor that is empty or the root, that the pattern does not start with, or that ends inside a name throws a
TypeError: the tail is cut by length, this feeds deny lists, and a skipped deny is lost.Without
anchorevery value is what it was, and nothing passes one yet.Tests
34 new cases in
glob-expand.test.tsandread-deny-glob.test.ts: tails that split and that cannot be split, a trailing separator, the directory form, a link beneath the anchor, and that no character of[WIP] project,build*ornotes (draft?)is read as pattern. File-system walks on Linux, both runtimes. Ten mutations each fail a test.Merge order
#575 rewrites
walkGlobPatternaround the same lines: keep itsglobBaseDirIsRoot(baseDir)as it is (an anchored base is never a root). #607 givesexpandReadDenyGlobLinuxa fourth parameteropts: { budget }: the two are one object,opts: { anchor?, budget? }, and both go on towalkGlobPattern, since an anchored walk needs the budget too.