Skip to content

Glob walk: an anchor option, a directory taken as the name it is - #620

Open
ronleizrowice-ant wants to merge 2 commits into
mainfrom
feat/glob-walk-anchor
Open

ronleizrowice-ant wants to merge 2 commits into
mainfrom
feat/glob-walk-anchor

Conversation

@ronleizrowice-ant

@ronleizrowice-ant ronleizrowice-ant commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

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/**/.env reads [WIP] as a class and finds nothing. walkGlobPattern and expandGlobPattern take anchor, 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. expandReadDenyGlobLinux passes it on through a fourth parameter opts: { 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 anchor every value is what it was, and nothing passes one yet.

Tests

34 new cases in glob-expand.test.ts and read-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* or notes (draft?) is read as pattern. File-system walks on Linux, both runtimes. Ten mutations each fail a test.

Merge order

#575 rewrites walkGlobPattern around the same lines: keep its globBaseDirIsRoot(baseDir) as it is (an anchored base is never a root). #607 gives expandReadDenyGlobLinux a fourth parameter opts: { budget }: the two are one object, opts: { anchor?, budget? }, and both go on to walkGlobPattern, since an anchored walk needs the budget too.

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.
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

No deployments
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