Make PATHEXT normalisation testable on any host (#485) - #503
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
Summary
Scope
WalkthroughEnable direct Unix-runnable ChangesPATHEXT contract
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 19 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (19 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Reviewer's GuideMake PATHEXT normalization logic testable on all hosts by ungating the parser/default list behind cfg(any(windows, test)), refining its implementation, and replacing Windows-only EnvSnapshot-based tests with direct, host-independent unit tests that cover normalization, de-duplication, ordering, and fallback behavior. Sequence diagram for PATHEXT tests using parse_pathext on all hostssequenceDiagram
actor TestRunner
participant pathext_tests
participant parse_pathext
participant DEFAULT_PATHEXT
TestRunner->>pathext_tests: run
pathext_tests->>parse_pathext: parse_pathext(raw)
alt raw is None
parse_pathext->>DEFAULT_PATHEXT: join segments with semicolons for source
else raw is Some
parse_pathext->>parse_pathext: value.to_string_lossy().into_owned()
end
parse_pathext->>parse_pathext: normalise segments and deduplicate
alt dedup is empty
parse_pathext->>DEFAULT_PATHEXT: iter().copied().map(String::from).collect()
end
parse_pathext-->>pathext_tests: Vec<String> extensions
pathext_tests-->>TestRunner: assertions pass
Flow diagram for PATHEXT normalisation in parse_pathextflowchart TD
A["raw Option<&OsStr>"] --> B{raw is Some}
B -- Yes --> C["source = raw.to_string_lossy().into_owned()"]
B -- No --> D["source = DEFAULT_PATHEXT.join(';')"]
C --> E["split source by ';'"]
D --> E
E --> F["trim segment; skip if empty"]
F --> G["ensure leading '.'; lowercase"]
G --> H["insert into IndexSet dedup"]
H --> I{dedup is empty}
I -- Yes --> J["return DEFAULT_PATHEXT.iter().copied().map(String::from).collect()"]
I -- No --> K["return dedup.into_iter().collect()"]
File-Level Changes
Assessment against linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Addresses two review findings on #503. Sourcery: the doc comments claimed the items were "deliberately free of `cfg` gating" while carrying `#[cfg(any(windows, test))]`. The wording now matches the attribute and records why that pair is the right one: `#[cfg(windows)]` alone hides the logic from the CI host, while no gate at all leaves it dead in a Unix release build, which `-D warnings` rejects. Sourcery also observed that asserting the parse equals `DEFAULT_PATHEXT` is tautological — emptying or mangling the constant would keep that assertion true. Their suggested replacement hard-codes a four-entry list, which does not match the eleven-entry constant, so rather than inline a duplicate the new test asserts the properties consumers rely on: non-empty, every entry lowercase and dot-prefixed, and the four extensions callers actually expect. Adds the usage example and the developers' guide entry required by AGENTS.md. Refs #485, #496. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@src/stdlib/which/env.rs`:
- Line 132: Update the documentation comment for the PATHEXT normalization logic
to use “Normalize” instead of “Normalise”; change prose only and leave the
existing “normalised” identifier unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 9910bae3-2ef9-4dcd-a0a2-4de2823a9b83
📒 Files selected for processing (10)
docs/adr-006-adopt-polonius-nightly-toolchain.mddocs/developers-guide.mddocs/netsuke-design.mddocs/polonius.mddocs/snapshot-testing-in-netsuke-using-insta.mddocs/users-guide.mdsrc/stdlib/which/env.rssrc/stdlib/which/lookup/tests.rssrc/stdlib/which/mod.rssrc/stdlib/which/pathext_tests.rs
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/shared-actions(auto-detected)
💤 Files with no reviewable changes (1)
- src/stdlib/which/lookup/tests.rs
Addresses two review findings on #503. Sourcery: the doc comments claimed the items were "deliberately free of `cfg` gating" while carrying `#[cfg(any(windows, test))]`. The wording now matches the attribute and records why that pair is the right one: `#[cfg(windows)]` alone hides the logic from the CI host, while no gate at all leaves it dead in a Unix release build, which `-D warnings` rejects. Sourcery also observed that asserting the parse equals `DEFAULT_PATHEXT` is tautological — emptying or mangling the constant would keep that assertion true. Their suggested replacement hard-codes a four-entry list, which does not match the eleven-entry constant, so rather than inline a duplicate the new test asserts the properties consumers rely on: non-empty, every entry lowercase and dot-prefixed, and the four extensions callers actually expect. Adds the usage example and the developers' guide entry required by AGENTS.md. Refs #485, #496. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8502694 to
15442a7
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
The `normalised` local identifier is left alone: the repository convention governs prose, and renaming a binding is not a spelling fix. Addresses a CodeRabbit finding on #503.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@docs/users-guide.md`:
- Around line 400-406: Update the Windows PATHEXT paragraph in the users guide
to avoid implying that every effective PATHEXT includes .exe: state that
cargo.exe is found with the default list, and refer to the canonical
DEFAULT_PATHEXT definition instead of “usual script suffixes.”
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 5da0d109-2f70-483c-99f3-d1ea73372433
📒 Files selected for processing (8)
docs/developers-guide.mddocs/users-guide.mdproptest-regressions/stdlib/which/pathext_tests.txtsrc/stdlib/which/cache.rssrc/stdlib/which/env.rssrc/stdlib/which/lookup/tests.rssrc/stdlib/which/mod.rssrc/stdlib/which/pathext_tests.rs
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/whitaker(auto-detected)leynos/shared-actions(auto-detected)
The note claimed `which('cargo')` finds `cargo.exe`, which holds only when
`.exe` is among the effective entries — a custom `PATHEXT` may legitimately
omit it. It also said "the usual script suffixes", which tells a reader
nothing they can check.
Both are now exact: the example is qualified, and the fallback list is
spelled out in order, since order is what `which` tries.
Addresses a CodeRabbit finding on #503.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@docs/users-guide.md`:
- Around line 405-406: Update the PATHEXT fallback wording in the documentation
to state that fallback occurs only when PATHEXT is unset or contains exclusively
empty or whitespace entries; do not describe other non-empty values as unusable.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4595d654-906d-488c-bd33-8c8ca61c18d8
📒 Files selected for processing (1)
docs/users-guide.md
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/whitaker(auto-detected)leynos/shared-actions(auto-detected)
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@docs/users-guide.md`:
- Around line 405-407: Update the PATHEXT behavior description near
parse_pathext to state that non-empty values are normalized by trimming entries,
ignoring empties, lowercasing, adding a leading dot, and de-duplicating while
preserving order, before use; retain the existing fallback description for unset
or entirely empty values.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 42a79131-5592-4a46-863b-58e3a95c4505
📒 Files selected for processing (1)
docs/users-guide.md
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/whitaker(auto-detected)leynos/shared-actions(auto-detected)
Rebuild PR #503's branch on origin/main, which absorbed the injectable environment capture this branch pioneered — EnvSnapshot::capture now delegates to capture_with_env over mockable::Env, with a Windows capture_with_pathext override — so the old EnvReader closure seam, the WhichResolver reader plumbing, process_env_reader, and the reader-based rewrites of cache.rs and lookup/tests.rs are dropped as absorbed. What remains novel, and is ported: - Widen parse_pathext and DEFAULT_PATHEXT from #[cfg(windows)] to #[cfg(any(windows, test))], expose parse_pathext pub(super), and give the fallback a single construction site, so PATHEXT normalization is compiled and lintable on the Unix CI host instead of only on Windows. - Port src/stdlib/which/pathext_tests.rs: fixed rstest cases for the normalization rules plus the properties proptest module (normalized entries, case-insensitive uniqueness, idempotence, fallback, and first-occurrence order) with its deliberately small mixed-case alphabet, together with the proptest-regressions seed file. - Document the effective PATHEXT matching, the built-in fallback list in order, and the exact fallback condition in docs/users-guide.md. - Document the which environment capture seam as it now exists (the mockable::Env provider, DefaultEnv binding, and PATHEXT override) and the full parse_pathext normalization contract in docs/developers-guide.md, next to the environment lookup seam material. Main's capture_with_pathext lookup tests are kept: they cover the Windows snapshot path, while the ported suite verifies the parser rules from the host that gates merges. Closes #485. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
d38be7d to
056a52f
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
docs/users-guide.md (1)
406-412: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winCorrect the normalization statement.
Replace “used as given”.
parse_pathexttrims entries, ignores empty entries,
lowercases ASCII text, inserts missing leading dots, and de-duplicates entries
without changing first-occurrence order.Triage:
[type:docstyle]Proposed correction
-Any other value is used as given, however unusual. The built-in list, in -order: +Any other value is normalized before use. Entries are trimmed, empty entries +are ignored, ASCII letters are lowercased, missing leading dots are added, and +duplicates are removed while first-occurrence order remains. The built-in list, +in order:🤖 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 `@docs/users-guide.md` around lines 406 - 412, Update the PATHEXT documentation around parse_pathext to replace “used as given” with the actual normalization behavior: trim entries, discard empty values, lowercase ASCII text, add missing leading dots, and de-duplicate while preserving first-occurrence order. Keep the fallback description and built-in list unchanged.Sources: Coding guidelines, Path instructions
🤖 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.
Duplicate comments:
In `@docs/users-guide.md`:
- Around line 406-412: Update the PATHEXT documentation around parse_pathext to
replace “used as given” with the actual normalization behavior: trim entries,
discard empty values, lowercase ASCII text, add missing leading dots, and
de-duplicate while preserving first-occurrence order. Keep the fallback
description and built-in list unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2b8dae92-158a-4850-901b-d1ee2beca457
📒 Files selected for processing (6)
docs/developers-guide.mddocs/users-guide.mdproptest-regressions/stdlib/which/pathext_tests.txtsrc/stdlib/which/env.rssrc/stdlib/which/mod.rssrc/stdlib/which/pathext_tests.rs
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/whitaker(auto-detected)leynos/shared-actions(auto-detected)
|
This round's two warnings, verified against the tree:
|
|
On the three failed pre-merge rows:
|
Rebuild PR #503's branch on origin/main, which absorbed the injectable environment capture this branch pioneered — EnvSnapshot::capture now delegates to capture_with_env over mockable::Env, with a Windows capture_with_pathext override — so the old EnvReader closure seam, the WhichResolver reader plumbing, process_env_reader, and the reader-based rewrites of cache.rs and lookup/tests.rs are dropped as absorbed. What remains novel, and is ported: - Widen parse_pathext and DEFAULT_PATHEXT from #[cfg(windows)] to #[cfg(any(windows, test))], expose parse_pathext pub(super), and give the fallback a single construction site, so PATHEXT normalization is compiled and lintable on the Unix CI host instead of only on Windows. - Port src/stdlib/which/pathext_tests.rs: fixed rstest cases for the normalization rules plus the properties proptest module (normalized entries, case-insensitive uniqueness, idempotence, fallback, and first-occurrence order) with its deliberately small mixed-case alphabet, together with the proptest-regressions seed file. - Document the effective PATHEXT matching, the built-in fallback list in order, and the exact fallback condition in docs/users-guide.md. - Document the which environment capture seam as it now exists (the mockable::Env provider, DefaultEnv binding, and PATHEXT override) and the full parse_pathext normalization contract in docs/developers-guide.md, next to the environment lookup seam material. Main's capture_with_pathext lookup tests are kept: they cover the Windows snapshot path, while the ported suite verifies the parser rules from the host that gates merges. Closes #485. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
056a52f to
ab3db61
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
Summary
parse_pathextand itsDEFAULT_PATHEXTfallback sat behind#[cfg(windows)]. Every rule they implement — lowercasing, inserting missing leading dots, trimming, de-duplicating, preserving declaration order, and falling back to the built-in list when the value yields nothing — went unverified on the platform where the suite actually runs.Clippy never linted the function either. On first exposure it produced two findings (
map(..).unwrap_or_else(..)and a redundant closure), both fixed here — which is a fair indication of what else was going unchecked.Approach
Ungate
parse_pathext,DEFAULT_PATHEXT, and theIndexSetimport behind#[cfg(any(windows, test))], matching the pattern used in #486. Runtime behaviour is unchanged: only the Windows snapshot consults them, and on a non-test Unix build they are still compiled out.Coverage
Ten cases, none mutating anything:
PATHEXTyields the default list"",";;;", and" ; ; ". This is the one that matters: were a blankPATHEXTto yield an empty extension list, Windows would treat nothing as executable andwhichwould report every command missingCOM,.com, and.COMbecome one entryRemoved
The two
#[cfg(windows)]tests driving this throughVarGuard::set("PATHEXT", ..). They mutated the process environment, which the AGENTS.md mandate forbids; they never ran on the Unix CI host; and their coverage is subsumed by the direct cases. NoVarGuarduse remains undersrc/.Deferred
The wider
EnvSnapshot::captureoverride plumbing.capturealready takes apath_overrideused by a dozen call sites; adding a third positionalOption<&OsStr>is churn better done alongside the broaderwhichseam work, and would draw a CodeScene argument-count finding for no present benefit. The untested normalisation was the substantive gap, and it is closed.Verification
All gates pass:
check-fmt,lint,typecheck,test(1198 nextest),markdownlint,nixie. CodeScene delta: no issues.Closes #485.
Refs #496.
🤖 Generated with Claude Code
Summary by Sourcery
Make PATHEXT normalisation logic testable on non-Windows hosts while keeping runtime behaviour unchanged.
New Features:
Bug Fixes:
Enhancements:
Tests: