Don't scan sibling files of a concrete @source inside an auto source root - #20406
Don't scan sibling files of a concrete @source inside an auto source root#20406benjamincanac wants to merge 3 commits into
@source inside an auto source root#20406Conversation
WalkthroughThe scanner now checks whether automatic directory walks can reach restricted pattern bases. It accounts for default-ignored directories and ancestor 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/oxide/src/scanner/sources.rs (1)
756-793: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider adding a unit test for the non-repository
cwdboundary.The new tests cover the repository case, where
.gitstops the ancestor walk. Thecwdboundary branch inis_ignored_by_gitignore(lines 340-346) is not covered by a unit test for the restricted-pattern path. A test with no.gitmarker and a.gitignoreabove the boundary would pin that behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8a64208f-33ba-4e9e-8a50-2b040de51569
📒 Files selected for processing (3)
CHANGELOG.mdcrates/oxide/src/scanner/sources.rscrates/oxide/tests/scanner.rs
Confidence Score: 4/5The nested The new coverage helper independently evaluates every ancestor Files Needing Attention: crates/oxide/src/scanner/sources.rs Reviews (1): Last reviewed commit: "Add PR number to changelog entry" | Re-trigger Greptile |
| let covered = bypassing_roots.iter().any(|root| base.starts_with(root)) | ||
| || (auto_roots | ||
| .iter() | ||
| .any(|root| base.starts_with(root) && !crosses_ignored_content_dir(root, base)) |
There was a problem hiding this comment.
Nested re-inclusions lose precedence
When a nearer .gitignore re-includes the concrete source directory while a farther ancestor ignores it, is_ignored_by_gitignore still classifies the directory as ignored. This adds an explicit * restriction even though the Auto walker reaches the directory, causing sibling files expected from Auto detection to be omitted from generated CSS.
Knowledge Base Used: Oxide Scanner Engine
Summary
A concrete file
@sourcewhose base sits inside an auto detection root scans the file's entire parent directory:With the project root as an auto source, every sibling of
button.tsgets scanned and their classes ship. The same directive pointing outside the root narrows correctly since #20263.The cause is in
expand_restricted_patterns: a pattern whose base is inside an unrestricted root skips the*+!<pattern>restriction, assuming everything under that root is walked anyway. That's false when the base hides behind a directory the auto walk prunes (node_modulesor a git-ignored one). The pattern's own walk root is then the only thing reaching the file, and its rules are just!button.ts, so every sibling is walked and included. This is the remaining half of #20255.The fix makes the coverage check ignore-aware: an auto root only covers a pattern base when the path down to it crosses no default-ignored directory and the base isn't git-ignored (reusing the ancestor
.gitignorewalk that promotes auto sources to external ones). External and**pattern roots still cover everything, and patterns in ordinary subdirectories keep the previous behavior.The
.gitignorewalk now also honors nested re-includes with git's precedence (the nearest.gitignorewith a definitive answer wins), so a directory re-included by a deeper!dirpattern is not treated as ignored. Since the walk is shared with the auto-to-external promotion, such re-included directory sources now stay auto sources instead of being promoted to external ones.Ran into this in Nuxt UI: we emit per-component
@sourcelines intonode_modules/.nuxt-ui, and the narrowed list produced byte-identical CSS to sourcing the whole directory (nuxt/ui#6731).Test plan
node_modulesand a git-ignored directory), both failed before the fix with the sibling's candidates included.expand_restricted_patterns, including a control for patterns in ordinary covered subdirectories.cargo testincrates/oxidepasses (191 tests), fmt clean, no new clippy warnings.@tailwindcss/viteon Vite 8 by patching the built oxide binary into a reproduction project: a file@sourceinside the root now ships only that file's classes, whole-directory sources and auto detection unchanged.🤖 Generated with Claude Code