Repository navigation
Add brace expansion and a dotfile option to the Rust glob module - #2708
somewhatabstract wants to merge 14 commits into
Conversation
expand_braces expands `{a,b}` groups, including nested and repeated
groups, as fast-glob's micromatch does, keeping braces that form no
group literal and leaving ranges unexpanded. Escapes are kept in the
results so each stays a glob pattern. fastglob-vectors.json records
micromatch's expansions, with the deliberate differences explained.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
GlobOptions gains `dot`. With it off, in pathname mode, as in fast-glob, wildcards don't match a `.` that starts a name: only a literal `.` or a bracket set that isn't negated does, and `**` doesn't enter hidden folders. With it on, matching is unchanged, and the gitignore handling turns it on. fastglob-vectors.json gains match cases from micromatch, with the deliberate differences explained. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
🦋 Changeset detectedLatest commit: 3f070b3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Bundle ReportBundle size has no change ✅ |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## claude/jolly-galileo-72zesp-glob-gitignore-modules #2708 +/- ##
======================================================================================
Coverage 100.00% 100.00%
======================================================================================
Files 112 126 +14
Lines 3843 5085 +1242
Branches 3051 4293 +1242
======================================================================================
+ Hits 3843 5085 +1242
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
expand_braces now returns a Result. It refuses a pattern over 10,000 bytes, braces nested more than 64 deep, and an expansion of more than 100,000 patterns or 10,000,000 bytes, so no input can overflow the stack or exhaust memory. A piece with a single text is appended to the results in place, and runs of ordinary bytes are read as one piece. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Remove GlobOptions' Default, whose `dot: false` was easy to pick up by accident, and work out once, when a pattern is compiled, whether its wildcards stay off hidden names. Bring the docs that described only slashes and case up to date. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Reword the escape divergences to say the results match fast-glob, which
keeps escapes, while micromatch's bare brace expansion drops them. Pin
the differences for parentheses, quotes and `${` in braces, for `[^a]`
next to a leading dot, and for micromatch's `[!.]` and `[[:punct:]]`
quirks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Thread one output budget through the recursion, counting every partial result and alternative held at once, so the 100,000-pattern and 10,000,000-byte caps hold for the whole call. Combining consumes the old results as it builds the new ones. Measure nesting by brace groups only, in one pass, so a pattern with no group always expands to itself, whatever its braces or length; the length and nesting limits apply only to patterns with groups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Rewrite the doc summaries that wrapped onto a second line, and define the plain and pathname test options once in the glob module, so adding an option means one edit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
|
Generated by Claude Code |
Brace expansion recursed once per level of nested groups, which overflowed the smaller stacks on Windows. It now keeps its work as frames on a heap-allocated stack, so its use of the call stack doesn't grow with nesting, and the 64-level nesting limit is gone. The shared output budget and the 10,000-byte length limit are unchanged, and a pattern with no group still expands to itself. Tests now expand deeply nested groups on a thread with a 64 KB stack, so a regression shows up on any platform. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Check the documented caps of 100,000 patterns and 10,000,000 bytes on each set of results as it's built. Each such set ends up in the final output, so this refuses exactly the expansions whose output is too large, whatever order the groups come in. The shared budget now only bounds what's held at once, at twice the caps, which an expansion within the caps never reaches. Debug builds now catch output released twice. Tests cover the exact cap, groups before and after a long literal, results left alone on error, and the budget counting what enclosing groups hold. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
micromatch refuses `{a}` followed by 10,000 bytes, though it has no
brace group; here it's kept as it is.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjLhVH1NnUc7MzCSYLd8Yn
Stacked on #2707. These are the two pieces of fast-glob's matching that
get_filesneeds in Rust. Both were written by the clean-room agent and checked against the micromatch build fast-glob 3.3.3 uses, run as a black box.expand_braces):src/*.{js,ts}becomessrc/*.jsandsrc/*.ts. It handles comma lists, nesting and escapes, and braces that don't form a group stay literal.{1..3}is deliberately not expanded and stays literal.GlobOptions::dot): withdot: false, no wildcard (*,?, a set,**) matches a.at the start of a name, but a literal.in the pattern does. gitignore keepsdot: true, so its behaviour doesn't change.x/**match the folderxitself, skips a leading./in a pattern, and treats.,..and empty names specially. The walker and pattern-splitting steps cover the cases that matter.*.*doesn't matcha., and its[!a]doesn't act as a negated set.__conformance__/fastglob-vectors.jsonrecords 172 cases with micromatch's answers, plus arustreason for each deliberate difference. Tests check both features against it.expand_braceshas no caller yet, so it carries a test-onlydead_codeexpectation. The next PR, which splits include patterns, calls it and removes the expectation.Part of #2615.
Test plan
dot: true, the glob matcher andIgnoreFilestill agree with git on the earlier 500,000 glob cases and 150,000 path decisions. The clean-room agent's own runs: 100,000 glob cases and 110,182 decisions.Generated by Claude Code