Ensure @source globs with symlinks are preserved#20203
Conversation
When we are dealing with `@source` patterns, we want to optimize them by moving as many static parts from the pattern to the base path. E.g.: ``` @source "./foo/bar/baz/*.html"; ``` Will look like: ``` SourceEntry { base = "/projects/project-a", pattern = "/foo/bar/baz/*.html", } ``` And becomes: ``` SourceEntry { base = "/projects/project-a/foo/bar/baz", pattern = "/*.html", } ``` But with this change, we don't canonicalize them, meaning that if we were referencing a symlink then we keep using the symlink in the pattern. We won't use the resolved canonical path all of a sudden.
ab1cec0 to
2154245
Compare
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR refactors the scanner's ignore-rule storage mechanism from 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
integrations/utils.ts (3)
52-52: ⚡ Quick winParameter naming is semantically backwards.
The first parameter is what the symlink points to (typically called
targetorsource), and the second is where the symlink is created (typically calledlinkordestination). The current naming(dst, src)reverses this convention, which can confuse callers. Additionally, the implementation (line 319) names the first parametertarget, creating an inconsistency with the signature.♻️ Rename parameters for clarity
- symlink(dst: string, src: string): Promise<void> + symlink(target: string, link: string): Promise<void>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/utils.ts` at line 52, The symlink signature currently uses semantically reversed names (symlink(dst: string, src: string)): rename parameters to match implementation and common conventions (e.g., symlink(target: string, link: string): Promise<void>) and update the implementation (the function that currently references `target` at line ~319) to use the `link` name for the path where the symlink is created; propagate the new parameter names to any internal callers, JSDoc/comments, and exports so the API is consistent and avoid breaking external callers by updating call sites accordingly.
319-329: 💤 Low valueRemove unnecessary target parent directory creation.
Creating the parent directory of the symlink target (lines 320-322) is unnecessary. Symlinks can point to non-existent targets, and when targets do exist, their parent directories are already created by earlier
fs.write()calls in the test setup loop (lines 427-439). Only the parent of the symlink itself (srcParent) needs to exist.♻️ Remove redundant mkdir
async symlink(target, src) { let targetAbsolute = path.join(root, target) - let targetParent = path.dirname(targetAbsolute) - await fs.mkdir(targetParent, { recursive: true }) - let srcAbsolute = path.join(root, src) let srcParent = path.dirname(srcAbsolute) await fs.mkdir(srcParent, { recursive: true }) await fs.symlink(targetAbsolute, srcAbsolute) },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/utils.ts` around lines 319 - 329, The symlink helper unnecessarily creates the target's parent directory; update the async symlink function to stop creating targetParent and only ensure the symlink's parent exists: remove or omit the fs.mkdir call that uses targetParent/targetAbsolute, keep computing targetAbsolute for fs.symlink and preserve creation of srcParent (srcAbsolute) with fs.mkdir({ recursive: true}) before calling fs.symlink(targetAbsolute, srcAbsolute). Ensure references to targetAbsolute, srcParent/srcAbsolute, and fs.symlink remain intact.
428-438: 💤 Low valueClarify comment wording.
The comment "The symlink path is relative to the target destination's path" is ambiguous. It's unclear whether "target destination" refers to the symlink location or what the symlink points to.
✏️ Suggested rewording
if (content.toString().startsWith('symlink:')) { - // The symlink path is relative to the target destination's path + // The path after 'symlink:' is relative to the symlink's location let target = path.join( filename, content.toString().slice('symlink:'.length), )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/utils.ts` around lines 428 - 438, The comment is ambiguous about what "target destination" refers to; update it to explicitly say that the string after 'symlink:' is a path for the symlink target resolved relative to the symlink's directory (i.e., the directory containing filename), and, if you intended resolution against that directory, consider using path.dirname(filename) when building target; reference the code paths using content.toString().startsWith('symlink:'), the target variable, path.join(...), filename, and context.fs.symlink.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@integrations/utils.ts`:
- Line 52: The symlink signature currently uses semantically reversed names
(symlink(dst: string, src: string)): rename parameters to match implementation
and common conventions (e.g., symlink(target: string, link: string):
Promise<void>) and update the implementation (the function that currently
references `target` at line ~319) to use the `link` name for the path where the
symlink is created; propagate the new parameter names to any internal callers,
JSDoc/comments, and exports so the API is consistent and avoid breaking external
callers by updating call sites accordingly.
- Around line 319-329: The symlink helper unnecessarily creates the target's
parent directory; update the async symlink function to stop creating
targetParent and only ensure the symlink's parent exists: remove or omit the
fs.mkdir call that uses targetParent/targetAbsolute, keep computing
targetAbsolute for fs.symlink and preserve creation of srcParent (srcAbsolute)
with fs.mkdir({ recursive: true}) before calling fs.symlink(targetAbsolute,
srcAbsolute). Ensure references to targetAbsolute, srcParent/srcAbsolute, and
fs.symlink remain intact.
- Around line 428-438: The comment is ambiguous about what "target destination"
refers to; update it to explicitly say that the string after 'symlink:' is a
path for the symlink target resolved relative to the symlink's directory (i.e.,
the directory containing filename), and, if you intended resolution against that
directory, consider using path.dirname(filename) when building target; reference
the code paths using content.toString().startsWith('symlink:'), the target
variable, path.join(...), filename, and context.fs.symlink.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1dad4c43-5368-40b3-a8c9-f7d4db4b214c
📒 Files selected for processing (12)
crates/oxide/src/extractor/candidate_machine.rscrates/oxide/src/extractor/mod.rscrates/oxide/src/extractor/pre_processors/haml.rscrates/oxide/src/extractor/pre_processors/pug.rscrates/oxide/src/extractor/pre_processors/ruby.rscrates/oxide/src/extractor/pre_processors/rust.rscrates/oxide/src/extractor/pre_processors/slim.rscrates/oxide/src/scanner/mod.rscrates/oxide/src/scanner/sources.rscrates/oxide/tests/scanner.rsintegrations/cli/index.test.tsintegrations/utils.ts
Confidence Score: 5/5The changes are safe to merge; the two bugs being fixed are well-scoped and backed by thorough tests across all OSes. The optimize() rewrite is correct: only the initial base is canonicalized, path components are pushed by their original symlinked names, and path_to_posix_string handles Windows separator normalization. The Vec switch in create_walker correctly preserves @source declaration order. No files require special attention. Reviews (4): Last reviewed commit: "udpate changelog" | Re-trigger Greptile |
| async symlink(target, src) { | ||
| let targetAbsolute = path.join(root, target) | ||
| let targetParent = path.dirname(targetAbsolute) | ||
| await fs.mkdir(targetParent, { recursive: true }) | ||
|
|
||
| let srcAbsolute = path.join(root, src) | ||
| let srcParent = path.dirname(srcAbsolute) | ||
| await fs.mkdir(srcParent, { recursive: true }) | ||
|
|
||
| await fs.symlink(targetAbsolute, srcAbsolute) | ||
| }, |
There was a problem hiding this comment.
Windows symlink type depends on key ordering in the config object
fs.symlink(targetAbsolute, srcAbsolute) is called without an explicit type argument. On Windows, Node.js auto-detects 'file' vs 'dir' based on whether the target exists at call time — if it doesn't exist yet, it defaults to 'file', which silently creates an invalid symlink for directory targets. The current integration tests happen to define target directory files before the symlink: entry (so auto-detection succeeds), but if a future test lists the symlink key first in the config.fs object, directory symlinks will silently be created as file symlinks on Windows and the walker will fail to traverse them. Passing 'junction' (or 'dir') as the third argument, or processing all regular-file writes before symlinks, would make this robust regardless of key order.
+ move pinned pattern check (leading `/`) to the optimize step as well.
2154245 to
506e6a9
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/oxide/src/scanner/sources.rs (1)
129-149:⚠️ Potential issue | 🟠 MajorHandle
?and character classes ([...]) when switching to pattern mode inPublicSourceEntry::optimize()
optimize()only switches toComponentStage::Patternwhenpart.contains('*'). The optimized(base, pattern)is later matched withfast_glob::glob_match, which supports?and character classes ([ab],[a-z], etc.), so segments containing those metacharacters can be hoisted intobaseand treated as literal paths, changing glob semantics.Suggested fix
- Component::Normal(part) if part.to_string_lossy().contains("*") => { + Component::Normal(part) if has_glob_meta(part) => { new_pattern.push(component); stage = ComponentStage::Pattern; }fn has_glob_meta(part: &std::ffi::OsStr) -> bool { let part = part.to_string_lossy(); part.contains('*') || part.contains('?') || part.contains('[') }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/oxide/src/scanner/sources.rs` around lines 129 - 149, PublicSourceEntry::optimize() currently only switches to ComponentStage::Pattern when a component contains '*', which misses other glob metacharacters supported by fast_glob::glob_match (like '?' and character classes '['). Add a helper (e.g. has_glob_meta(part: &OsStr) -> bool) that checks for '*' or '?' or '[' on the component string, then replace occurrences of part.to_string_lossy().contains("*") with has_glob_meta(&part) in the Component::Normal match arms (including the last-component branch that decides between pushing to base or new_pattern) so any segment with '?', '[' or '*' is treated as pattern and moves to ComponentStage::Pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/oxide/src/scanner/sources.rs`:
- Around line 129-149: PublicSourceEntry::optimize() currently only switches to
ComponentStage::Pattern when a component contains '*', which misses other glob
metacharacters supported by fast_glob::glob_match (like '?' and character
classes '['). Add a helper (e.g. has_glob_meta(part: &OsStr) -> bool) that
checks for '*' or '?' or '[' on the component string, then replace occurrences
of part.to_string_lossy().contains("*") with has_glob_meta(&part) in the
Component::Normal match arms (including the last-component branch that decides
between pushing to base or new_pattern) so any segment with '?', '[' or '*' is
treated as pattern and moves to ComponentStage::Pattern.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5bdd0d19-884a-4975-93af-b8ef8bfb53dc
📒 Files selected for processing (4)
CHANGELOG.mdcrates/oxide/src/scanner/mod.rscrates/oxide/src/scanner/sources.rscrates/oxide/tests/scanner.rs
✅ Files skipped from review due to trivial changes (1)
- CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/oxide/tests/scanner.rs
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/oxide/src/scanner/sources.rs (1)
249-313: ⚡ Quick winConsider adding unit tests for absolute path handling.
The new
Component::PrefixandComponent::RootDirbranches (lines 152-162) aren't exercised by the existing unit tests. Adding tests for patterns like/absolute/path/**/*.html(Unix) andC:\absolute\path\**\*.html(Windows, if CI supports it) would help ensure the platform-specific logic remains correct.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/oxide/src/scanner/sources.rs` around lines 249 - 313, Add unit tests that exercise absolute-path branches by constructing PublicSourceEntry instances whose pattern starts with an absolute path so optimize() will hit Component::RootDir and Component::Prefix handling (e.g. patterns like "/absolute/path/**/*.html" on Unix and "C:\\absolute\\path\\**\\*.html" on Windows where CI supports it); ensure each test creates the on-disk directory (fs::create_dir_all), calls source.optimize(), and asserts that source.base is the dunce::canonicalize(...) of the hoisted directory and that source.pattern preserves the leading "/**/*.html" (or equivalent) per the existing assertions to validate the new branches in optimize().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/oxide/src/scanner/sources.rs`:
- Around line 249-313: Add unit tests that exercise absolute-path branches by
constructing PublicSourceEntry instances whose pattern starts with an absolute
path so optimize() will hit Component::RootDir and Component::Prefix handling
(e.g. patterns like "/absolute/path/**/*.html" on Unix and
"C:\\absolute\\path\\**\\*.html" on Windows where CI supports it); ensure each
test creates the on-disk directory (fs::create_dir_all), calls
source.optimize(), and asserts that source.base is the dunce::canonicalize(...)
of the hoisted directory and that source.pattern preserves the leading
"/**/*.html" (or equivalent) per the existing assertions to validate the new
branches in optimize().
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: fbd00595-086e-492e-91b3-30eb3120843b
📒 Files selected for processing (1)
crates/oxide/src/scanner/sources.rs
Here is everything you need to know about this update. Please take a good look at what changed and the test results before merging this pull request. ### What changed? #### ✳️ eslint (9.37.0 → 9.39.1) · [Repo](https://github.com/eslint/eslint) · [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) <details> <summary>Release Notes</summary> <h4><a href="https://github.com/eslint/eslint/releases/tag/v9.39.1">9.39.1</a></h4> <blockquote><h2 dir="auto">Bug Fixes</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/650753ee3976784343ceb40170619dab1aa9fe0d"><code class="notranslate">650753e</code></a> fix: Only pass node to JS lang visitor methods (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20283">#20283</a>) (Nicholas C. Zakas)</li> </ul> <h2 dir="auto">Documentation</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/51b51f4f1ce82ef63264c4e45d9ef579bcd73f8e"><code class="notranslate">51b51f4</code></a> docs: add a section on when to use extends vs cascading (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20268">#20268</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b44d42699dcd1729b7ecb50ca70e4c1c17f551f1"><code class="notranslate">b44d426</code></a> docs: Update README (GitHub Actions Bot)</li> </ul> <h2 dir="auto">Chores</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/92db329211c8da5ce8340a4d4c05ce9c12845381"><code class="notranslate">92db329</code></a> chore: update <code class="notranslate">@eslint/js</code> version to 9.39.1 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20284">#20284</a>) (Francesco Trotta)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/c7ebefc9eaf99b76b30b0d3cf9960807a47367c4"><code class="notranslate">c7ebefc</code></a> chore: package.json update for @eslint/js release (Jenkins)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/61778f6ca33c0f63962a91d6a75a4fa5db9f47d2"><code class="notranslate">61778f6</code></a> chore: update eslint-config-eslint dependency @eslint/js to ^9.39.0 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20275">#20275</a>) (renovate[bot])</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/d9ca2fcd9ad63331bfd329a69534e1ff04f231e8"><code class="notranslate">d9ca2fc</code></a> ci: Add rangeStrategy to eslint group in renovate config (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20266">#20266</a>) (唯然)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/009e5076ff5a4bd845f55e17676e3bb88f47c280"><code class="notranslate">009e507</code></a> test: fix version tests for ESLint v10 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20274">#20274</a>) (Milos Djermanovic)</li> </ul></blockquote> <h4><a href="https://github.com/eslint/eslint/releases/tag/v9.39.0">9.39.0</a></h4> <blockquote><h2 dir="auto">Features</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/cc57d87a3f119e9d39c55e044e526ae067fa31ce"><code class="notranslate">cc57d87</code></a> feat: update error loc to key in <code class="notranslate">no-dupe-class-members</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20259">#20259</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/126552fcf35da3ddcefa527db06dabc54c04041c"><code class="notranslate">126552f</code></a> feat: update error location in <code class="notranslate">for-direction</code> and <code class="notranslate">no-dupe-args</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20258">#20258</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/167d0970d3802a66910e9820f31dcd717fab0b2a"><code class="notranslate">167d097</code></a> feat: update <code class="notranslate">complexity</code> rule to highlight only static block header (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20245">#20245</a>) (jaymarvelz)</li> </ul> <h2 dir="auto">Bug Fixes</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/15f5c7c168d0698683943f51dd617f14a5e6815c"><code class="notranslate">15f5c7c</code></a> fix: forward traversal <code class="notranslate">step.args</code> to visitors (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20253">#20253</a>) (jaymarvelz)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/5a1a534e877f7c4c992885867f923df307c3929d"><code class="notranslate">5a1a534</code></a> fix: allow JSDoc comments in object-shorthand rule (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20167">#20167</a>) (Nitin Kumar)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e86b813eb660f1a5adc8e143a70d9b683cd12362"><code class="notranslate">e86b813</code></a> fix: Use more types from @eslint/core (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20257">#20257</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/927272d1f0d5683b029b729d368a96527f283323"><code class="notranslate">927272d</code></a> fix: correct <code class="notranslate">Scope</code> typings (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20198">#20198</a>) (jaymarvelz)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/37f76d9c539bb6fc816fedb7be4486b71a58620a"><code class="notranslate">37f76d9</code></a> fix: use <code class="notranslate">AST.Program</code> type for Program node (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20244">#20244</a>) (Francesco Trotta)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/ae07f0b3334ebd22ae2e7b09bca5973b96aa9768"><code class="notranslate">ae07f0b</code></a> fix: unify timing report for concurrent linting (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20188">#20188</a>) (jaymarvelz)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b165d471be6062f4475b972155b02654a974a0e9"><code class="notranslate">b165d47</code></a> fix: correct <code class="notranslate">Rule</code> typings (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20199">#20199</a>) (jaymarvelz)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/fb97cda70d87286a7dbd2457f578ef578d6905e8"><code class="notranslate">fb97cda</code></a> fix: improve error message for missing fix function in suggestions (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20218">#20218</a>) (jaymarvelz)</li> </ul> <h2 dir="auto">Documentation</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/d3e81e30ee6be5a21151b7a17ef10a714b6059c0"><code class="notranslate">d3e81e3</code></a> docs: Always recommend to include a files property (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20158">#20158</a>) (Percy Ma)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/0f0385f1404dcadaba4812120b1ad02334dbd66a"><code class="notranslate">0f0385f</code></a> docs: use consistent naming recommendation (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20250">#20250</a>) (Alex M. Spieslechner)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a3b145609ac649fac837c8c0515cbb2a9321ca40"><code class="notranslate">a3b1456</code></a> docs: Update README (GitHub Actions Bot)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/cf5f2dd58dd98084a21da04fe7b9054b9478d552"><code class="notranslate">cf5f2dd</code></a> docs: fix correct tag of <code class="notranslate">no-useless-constructor</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20255">#20255</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/10b995c8e5473de8d66d3cd99d816e046f35e3ec"><code class="notranslate">10b995c</code></a> docs: add TS options and examples for <code class="notranslate">nofunc</code> in <code class="notranslate">no-use-before-define</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20249">#20249</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/2584187e4a305ea7a98e1a5bd4dca2a60ad132f8"><code class="notranslate">2584187</code></a> docs: remove repetitive word in comment (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20242">#20242</a>) (reddaisyy)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/637216bd4f2aae7c928ad04a4e40eecffb50c9e5"><code class="notranslate">637216b</code></a> docs: update CLI flags migration instructions (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20238">#20238</a>) (jaymarvelz)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e7cda3bdf1bdd664e6033503a3315ad81736b200"><code class="notranslate">e7cda3b</code></a> docs: Update README (GitHub Actions Bot)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/7b9446f7cc2054aa2cdf8e6225f4ac15a03671a8"><code class="notranslate">7b9446f</code></a> docs: handle empty flags sections on the feature flags page (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20222">#20222</a>) (sethamus)</li> </ul> <h2 dir="auto">Chores</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/dfe3c1b2034228765c48c8a445554223767dd16d"><code class="notranslate">dfe3c1b</code></a> chore: update <code class="notranslate">@eslint/js</code> version to 9.39.0 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20270">#20270</a>) (Francesco Trotta)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/2375a6de8263393c129d41cac1b407b40111a73c"><code class="notranslate">2375a6d</code></a> chore: package.json update for @eslint/js release (Jenkins)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a1f4e52d67c94bef61edd1607dcd130047c1baf0"><code class="notranslate">a1f4e52</code></a> chore: update <code class="notranslate">@eslint</code> dependencies (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20265">#20265</a>) (Francesco Trotta)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/c7d32298482752eeac9fb46378d4f1ea095f3836"><code class="notranslate">c7d3229</code></a> chore: update dependency @eslint/core to ^0.17.0 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20256">#20256</a>) (renovate[bot])</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/27549bc774c7c2dc5c569070a3e87c62f602bf7d"><code class="notranslate">27549bc</code></a> chore: update fuzz testing to not error if code sample minimizer fails (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20252">#20252</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a1370ee40e9d8e0e41843f3278cd745fc1ad543f"><code class="notranslate">a1370ee</code></a> ci: bump actions/setup-node from 5 to 6 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20230">#20230</a>) (dependabot[bot])</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/9e7fad4a1867709060686d03e0ec1d0d69671cfb"><code class="notranslate">9e7fad4</code></a> chore: add script to auto-generate eslint:recommended configuration (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20208">#20208</a>) (唯然)</li> </ul></blockquote> <h4><a href="https://github.com/eslint/eslint/releases/tag/v9.38.0">9.38.0</a></h4> <blockquote><h2 dir="auto">Features</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/ce40f74efd45f66d9fbfc6f78ce622ee72008485"><code class="notranslate">ce40f74</code></a> feat: update <code class="notranslate">complexity</code> rule to only highlight function header (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20048">#20048</a>) (Atul Nair)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e37e590aae2a7fcca4d3a9adc1379ad466e5c5d1"><code class="notranslate">e37e590</code></a> feat: correct <code class="notranslate">no-loss-of-precision</code> false positives with <code class="notranslate">e</code> notation (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20187">#20187</a>) (Francesco Trotta)</li> </ul> <h2 dir="auto">Bug Fixes</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/50c3dfd98065622765a51a8ddb1e70c44fc5a4cb"><code class="notranslate">50c3dfd</code></a> fix: improve type support for isolated dependencies in pnpm (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20201">#20201</a>) (Francesco Trotta)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a1f06a350c4155c4dbf39bf932a38d71d70f1b65"><code class="notranslate">a1f06a3</code></a> fix: correct SourceCode typings (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20114">#20114</a>) (Pixel998)</li> </ul> <h2 dir="auto">Documentation</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/462675af8a811f9ca984efaedbdc5b46b13ced7a"><code class="notranslate">462675a</code></a> docs: improve web accessibility by hiding non-semantic character (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20205">#20205</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/c070e65f6bb9e38d06a89ba2b3261781bec3d397"><code class="notranslate">c070e65</code></a> docs: correct formatting in <code class="notranslate">no-irregular-whitespace</code> rule documentation (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20203">#20203</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b39e71a2130ae1ea3fbc19b19f5b951eb625722a"><code class="notranslate">b39e71a</code></a> docs: Update README (GitHub Actions Bot)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/cd3998314876a4fad6463d9011bc73778ccc1fd9"><code class="notranslate">cd39983</code></a> docs: move <code class="notranslate">custom-formatters</code> type descriptions to <code class="notranslate">nodejs-api</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20190">#20190</a>) (Percy Ma)</li> </ul> <h2 dir="auto">Chores</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/d17c795bf1624e0604998482b98e6bb6bff39045"><code class="notranslate">d17c795</code></a> chore: upgrade @eslint/js@9.38.0 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20221">#20221</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/25d0e33270e08baed09dbee2cdd56a8e5cd9da0f"><code class="notranslate">25d0e33</code></a> chore: package.json update for @eslint/js release (Jenkins)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/c82b5efa1fc91900e029efa23e688fad67fc17fa"><code class="notranslate">c82b5ef</code></a> refactor: Use types from @eslint/core (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20168">#20168</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/ff31609f195654d448954210ba4d31e921d463e8"><code class="notranslate">ff31609</code></a> ci: add Node.js 25 to <code class="notranslate">ci.yml</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20220">#20220</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/004577eda2f2f4b2829e0364f8b41893cebfc859"><code class="notranslate">004577e</code></a> ci: bump github/codeql-action from 3 to 4 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20211">#20211</a>) (dependabot[bot])</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/eac71fb77113de7bf199ff20c6ee44cefcb59848"><code class="notranslate">eac71fb</code></a> test: remove use of <code class="notranslate">nodejsScope</code> option of eslint-scope from tests (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20206">#20206</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/4168a18b7efd8facbbd71cd44a62942a9f656a30"><code class="notranslate">4168a18</code></a> chore: fix typo in legacy-eslint.js (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20202">#20202</a>) (Sweta Tanwar)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/205dbd2d9272e761574c478e3b0181f7b89ed0f6"><code class="notranslate">205dbd2</code></a> chore: fix typos (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20200">#20200</a>) (ntnyq)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/dbb200e3604e63bba23a18d40089ca44604835ed"><code class="notranslate">dbb200e</code></a> chore: use team member's username when name is not available in data (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20194">#20194</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/8962089edbd978b43513576387a134036b8e2d36"><code class="notranslate">8962089</code></a> chore: mark deprecated rules as available until v11.0.0 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/20184">#20184</a>) (Pixel998)</li> </ul></blockquote> <p><em>Does any of this look wrong? <a href="https://depfu.com/packages/npm/eslint/feedback">Please let us know.</a></em></p> </details> <details> <summary>Commits</summary> <p><a href="https://github.com/eslint/eslint/compare/d5d1bdf5fdfad75197aadd3e894182135158c3b1...e2772811a8595d161870835ff04822b25a2cdf45">See the full diff on Github</a>. The new version differs by 59 commits:</p> <ul> <li><a href="https://github.com/eslint/eslint/commit/e2772811a8595d161870835ff04822b25a2cdf45"><code>9.39.1</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/4cdf397b30b2b749865ea0fcf4d30eb8ba458896"><code>Build: changelog update for 9.39.1</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/92db329211c8da5ce8340a4d4c05ce9c12845381"><code>chore: update `@eslint/js` version to 9.39.1 (#20284)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/c7ebefc9eaf99b76b30b0d3cf9960807a47367c4"><code>chore: package.json update for @eslint/js release</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/650753ee3976784343ceb40170619dab1aa9fe0d"><code>fix: Only pass node to JS lang visitor methods (#20283)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/51b51f4f1ce82ef63264c4e45d9ef579bcd73f8e"><code>docs: add a section on when to use extends vs cascading (#20268)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/61778f6ca33c0f63962a91d6a75a4fa5db9f47d2"><code>chore: update eslint-config-eslint dependency @eslint/js to ^9.39.0 (#20275)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/d9ca2fcd9ad63331bfd329a69534e1ff04f231e8"><code>ci: Add rangeStrategy to eslint group in renovate config (#20266)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/009e5076ff5a4bd845f55e17676e3bb88f47c280"><code>test: fix version tests for ESLint v10 (#20274)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/b44d42699dcd1729b7ecb50ca70e4c1c17f551f1"><code>docs: Update README</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/ac3a60dffc29d8d4d5031621bc062e77f891532a"><code>9.39.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/e79017ff52cada700e743110bd17409f41f4fdfa"><code>Build: changelog update for 9.39.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/dfe3c1b2034228765c48c8a445554223767dd16d"><code>chore: update `@eslint/js` version to 9.39.0 (#20270)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/2375a6de8263393c129d41cac1b407b40111a73c"><code>chore: package.json update for @eslint/js release</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/d3e81e30ee6be5a21151b7a17ef10a714b6059c0"><code>docs: Always recommend to include a files property (tailwindlabs#20158)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/15f5c7c168d0698683943f51dd617f14a5e6815c"><code>fix: forward traversal `step.args` to visitors (#20253)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/5a1a534e877f7c4c992885867f923df307c3929d"><code>fix: allow JSDoc comments in object-shorthand rule (tailwindlabs#20167)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/cc57d87a3f119e9d39c55e044e526ae067fa31ce"><code>feat: update error loc to key in `no-dupe-class-members` (#20259)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a1f4e52d67c94bef61edd1607dcd130047c1baf0"><code>chore: update `@eslint` dependencies (#20265)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/e86b813eb660f1a5adc8e143a70d9b683cd12362"><code>fix: Use more types from @eslint/core (#20257)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/126552fcf35da3ddcefa527db06dabc54c04041c"><code>feat: update error location in `for-direction` and `no-dupe-args` (#20258)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/927272d1f0d5683b029b729d368a96527f283323"><code>fix: correct `Scope` typings (tailwindlabs#20198)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/c7d32298482752eeac9fb46378d4f1ea095f3836"><code>chore: update dependency @eslint/core to ^0.17.0 (#20256)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/0f0385f1404dcadaba4812120b1ad02334dbd66a"><code>docs: use consistent naming recommendation (tailwindlabs#20250)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a3b145609ac649fac837c8c0515cbb2a9321ca40"><code>docs: Update README</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/37f76d9c539bb6fc816fedb7be4486b71a58620a"><code>fix: use `AST.Program` type for Program node (tailwindlabs#20244)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/cf5f2dd58dd98084a21da04fe7b9054b9478d552"><code>docs: fix correct tag of `no-useless-constructor` (#20255)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/27549bc774c7c2dc5c569070a3e87c62f602bf7d"><code>chore: update fuzz testing to not error if code sample minimizer fails (#20252)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/10b995c8e5473de8d66d3cd99d816e046f35e3ec"><code>docs: add TS options and examples for `nofunc` in `no-use-before-define` (tailwindlabs#20249)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/167d0970d3802a66910e9820f31dcd717fab0b2a"><code>feat: update `complexity` rule to highlight only static block header (tailwindlabs#20245)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/2584187e4a305ea7a98e1a5bd4dca2a60ad132f8"><code>docs: remove repetitive word in comment (tailwindlabs#20242)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/ae07f0b3334ebd22ae2e7b09bca5973b96aa9768"><code>fix: unify timing report for concurrent linting (tailwindlabs#20188)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/b165d471be6062f4475b972155b02654a974a0e9"><code>fix: correct `Rule` typings (tailwindlabs#20199)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/637216bd4f2aae7c928ad04a4e40eecffb50c9e5"><code>docs: update CLI flags migration instructions (tailwindlabs#20238)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/e7cda3bdf1bdd664e6033503a3315ad81736b200"><code>docs: Update README</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a1370ee40e9d8e0e41843f3278cd745fc1ad543f"><code>ci: bump actions/setup-node from 5 to 6 (tailwindlabs#20230)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/fb97cda70d87286a7dbd2457f578ef578d6905e8"><code>fix: improve error message for missing fix function in suggestions (tailwindlabs#20218)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/9e7fad4a1867709060686d03e0ec1d0d69671cfb"><code>chore: add script to auto-generate eslint:recommended configuration (tailwindlabs#20208)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/7b9446f7cc2054aa2cdf8e6225f4ac15a03671a8"><code>docs: handle empty flags sections on the feature flags page (tailwindlabs#20222)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/8fe511b4c0fb74df3290271b29c672c3fbf3be1f"><code>9.38.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/f961736693e8b5658eb117eedbb9754be589c0ce"><code>Build: changelog update for 9.38.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/d17c795bf1624e0604998482b98e6bb6bff39045"><code>chore: upgrade @eslint/js@9.38.0 (tailwindlabs#20221)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/25d0e33270e08baed09dbee2cdd56a8e5cd9da0f"><code>chore: package.json update for @eslint/js release</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/50c3dfd98065622765a51a8ddb1e70c44fc5a4cb"><code>fix: improve type support for isolated dependencies in pnpm (tailwindlabs#20201)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/c82b5efa1fc91900e029efa23e688fad67fc17fa"><code>refactor: Use types from @eslint/core (tailwindlabs#20168)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/ff31609f195654d448954210ba4d31e921d463e8"><code>ci: add Node.js 25 to `ci.yml` (tailwindlabs#20220)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/ce40f74efd45f66d9fbfc6f78ce622ee72008485"><code>feat: update `complexity` rule to only highlight function header (tailwindlabs#20048)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/e37e590aae2a7fcca4d3a9adc1379ad466e5c5d1"><code>feat: correct `no-loss-of-precision` false positives with `e` notation (tailwindlabs#20187)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/004577eda2f2f4b2829e0364f8b41893cebfc859"><code>ci: bump github/codeql-action from 3 to 4 (tailwindlabs#20211)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/eac71fb77113de7bf199ff20c6ee44cefcb59848"><code>test: remove use of `nodejsScope` option of eslint-scope from tests (tailwindlabs#20206)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/462675af8a811f9ca984efaedbdc5b46b13ced7a"><code>docs: improve web accessibility by hiding non-semantic character (tailwindlabs#20205)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/c070e65f6bb9e38d06a89ba2b3261781bec3d397"><code>docs: correct formatting in `no-irregular-whitespace` rule documentation (tailwindlabs#20203)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/b39e71a2130ae1ea3fbc19b19f5b951eb625722a"><code>docs: Update README</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/4168a18b7efd8facbbd71cd44a62942a9f656a30"><code>chore: fix typo in legacy-eslint.js (#20202)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/205dbd2d9272e761574c478e3b0181f7b89ed0f6"><code>chore: fix typos (tailwindlabs#20200)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a1f06a350c4155c4dbf39bf932a38d71d70f1b65"><code>fix: correct SourceCode typings (tailwindlabs#20114)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/dbb200e3604e63bba23a18d40089ca44604835ed"><code>chore: use team member&tailwindlabs#39;s username when name is not available in data (tailwindlabs#20194)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/cd3998314876a4fad6463d9011bc73778ccc1fd9"><code>docs: move `custom-formatters` type descriptions to `nodejs-api` (tailwindlabs#20190)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/8962089edbd978b43513576387a134036b8e2d36"><code>chore: mark deprecated rules as available until v11.0.0 (tailwindlabs#20184)</code></a></li> </ul> </details> ---  [Depfu](https://depfu.com) will automatically keep this PR conflict-free, as long as you don't add any commits to this branch yourself. You can also trigger a rebase manually by commenting with `@depfu rebase`. <details><summary>All Depfu comment commands</summary> <blockquote><dl> <dt>@depfu rebase</dt><dd>Rebases against your default branch and redoes this update</dd> <dt>@depfu recreate</dt><dd>Recreates this PR, overwriting any edits that you've made to it</dd> <dt>@depfu merge</dt><dd>Merges this PR once your tests are passing and conflicts are resolved</dd> <dt>@depfu cancel merge</dt><dd>Cancels automatic merging of this PR</dd> <dt>@depfu close</dt><dd>Closes this PR and deletes the branch</dd> <dt>@depfu reopen</dt><dd>Restores the branch and reopens this PR (if it's closed)</dd> <dt>@depfu pause</dt><dd>Ignores all future updates for this dependency and closes this PR</dd> <dt>@depfu pause [minor|major]</dt><dd>Ignores all future minor/major updates for this dependency and closes this PR</dd> <dt>@depfu resume</dt><dd>Future versions of this dependency will create PRs again (leaves this PR as is)</dd> </dl></blockquote> </details> Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
This PR fixes an issue when working with
@sourceand@source notthat involves symlinks.Internally our sources are mapped to a source entry where we have a
basepath and apattern. You can think about this where we insert a.gitignorefile in thebasepath for the given pattern.However, we optimize these entries to move as many "static" parts into the base path. For example:
Is mapped to something like:
We then optimize it by turning it into:
While doing this, we also use
dunce::canonicalizeto resolve the actual paths on disk. This means that a symlink is resolved to their real paths. This can cause issues because the "real" path is not what you wrote in the@sourcedirectives.So before, it could be that you have this:
Which was mapped to this on the Rust side:
But was then optimized to:
...and we lost the
symlinked-folderinformation. This causes issues as seen in #17985.With this PR, we keep the symlinked information in those globs since that's what you wrote in those
@sourcedirectives.While setting up integration tests, I stumbled upon an issue because I wanted to test that ignoring a symlinked folder, but including a single particular file of that ignored folder resulted in that file being ignored as well. Let's look at an example:
Earlier I mentioned that we create
.gitignorefiles based on these@sourcedirectives. In this case, when we're dealing with a folder, we use**/*as the contents.Looking at the example above, we should essentially have something like this:
Since it's a
.gitignorefile, we have to invert the globs. But the bug I noticed is that in reality the result of those gitignores didn't look like the above, it looked like:Notice how the
!except.htmland**/*are flipped. When dealing with.gitignorefiles, the order is important.This was caused because internally we kept a
BTreeMapofBTreeSets where the map was the base path and a set of patterns. The patterns were sorted because of theBTreeSet... which is not what we want.Fixes: #17985
Closes: #20091
Test plan
@sourcefiles with a folder + file is sorted correctly.