Skip to content

fix windows PATHEXT resolution for .cmd/.bat wrappers#269

Open
F0rty-Tw0 wants to merge 1 commit intortk-ai:developfrom
F0rty-Tw0:bug/212/cant-resolve-cmd-bat-wrappers
Open

fix windows PATHEXT resolution for .cmd/.bat wrappers#269
F0rty-Tw0 wants to merge 1 commit intortk-ai:developfrom
F0rty-Tw0:bug/212/cant-resolve-cmd-bat-wrappers

Conversation

@F0rty-Tw0
Copy link

What changed

  • Added which crate to resolve binary paths with proper PATH+PATHEXT handling before spawning
  • New resolve_binary(), resolved_command(), and tool_exists() helpers in src/utils.rs
  • Replaced Command::new(...) with resolved_command(...) across all 16+ command modules (vitest, eslint, tsc, pnpm, playwright, prisma, next, pip, pytest, ruff, golangci-lint, etc.)
  • Removed duplicate which_command() / tool_exists() helpers from individual modules (pip_cmd.rs, pytest_cmd.rs, ccusage.rs)
  • Added 213 lines of tests including Windows-specific .CMD/.BAT wrapper resolution
  • Added troubleshooting guide for Windows "program not found" errors
  • Translated French comments to English in utils.rs

Impact on existing code

  • Every command module that spawns an external tool now goes through resolved_command() instead of raw Command::new(). On non-Windows this resolves to the same binary path, so behavior is unchanged. On Windows, .CMD/.BAT/.PS1 shims installed by npm/pnpm are now found correctly.
  • The which crate adds three small transitive dependencies (env_home, winsafe, rustix — rustix was already present).
  • Modules that had their own which_command() helpers (pip, pytest, ccusage) now use the shared tool_exists() from utils, removing ~40 lines of duplicated code.

Test plan

  • On Windows: run rtk vitest run, rtk lint src/, rtk tsc with Node.js tools installed via pnpm/npm — should no longer fail with "program not found"
  • On macOS/Linux: run cargo test --all to confirm no regressions
  • Verify resolve_binary("cargo") returns a valid path in CI across all platforms

Closes #212

@pszymkowiak
Copy link
Collaborator

Hi, this PR has conflicts with master. Could you rebase on current master? Thanks!

@F0rty-Tw0 F0rty-Tw0 force-pushed the bug/212/cant-resolve-cmd-bat-wrappers branch from de135a4 to a5eea5a Compare March 2, 2026 09:40
@F0rty-Tw0
Copy link
Author

Hi, this PR has conflicts with master. Could you rebase on current master? Thanks!

Should be done, plus updated the new commands with the utils.

@F0rty-Tw0 F0rty-Tw0 force-pushed the bug/212/cant-resolve-cmd-bat-wrappers branch from fbf2bec to 6a4b6f0 Compare March 4, 2026 13:57
@FlorianBruniaux
Copy link
Collaborator

Hi @F0rty-Tw0, the approach is correct and the 28-file scope is justified given the goal. Centralizing binary resolution into resolved_command() is the right call and the fallback ensures nothing breaks on macOS/Linux.

Two things before we can merge:

  1. In release mode, if which fails to find the binary, resolved_command() silently falls back to Command::new(name), which is the original broken behavior. The warning is only emitted in debug builds. Consider making it unconditional on Windows at least, so users have a signal when the .cmd wrapper isn't being found.

  2. init.rs shows up in the changed files but a PATHEXT fix doesn't obviously need to touch it. Could you clarify what changed there? If it's unrelated, a separate PR would keep the diff reviewable.

The tool_exists() helper, the removal of duplicated which calls across modules, and the troubleshooting doc addition are all good.

carsonm-etched pushed a commit to cmolder/rtk that referenced this pull request Mar 6, 2026
1. Remove `assert!` and `expect` when parsing action count. By
   default we only use the first action count found. Also add
   debug prints for weird cases.
2. Use `resolved_command` in rtk-ai#269
3. Return `Result` from all filter functions, and fall back to
   printing raw output if there is an error

Other changes:
1. Add `run_bazel_filtered<F>` generic function to match Cargo and
   reduce code reuse
2. Merge stdout and stderr in `filter_bazel_query` (should probably
   refactor `bazel query` some more)
@pszymkowiak
Copy link
Collaborator

Review: LGTM ✅ — needs rebase

Verified locally — cargo fmt clean, cargo clippy clean, 506/506 tests pass (1 pre-existing failure unrelated to this PR).

Clean approach:

  • resolved_command() as a drop-in Command::new() replacement with graceful fallback
  • Proper Windows PATHEXT handling via which crate
  • Good test coverage including #[cfg(target_os = "windows")] tests with temp .cmd wrappers
  • Removes duplicated which_command() / tool_exists() helpers from pip/pytest/ccusage

Action needed: Rebase on master — conflicts in Cargo.lock and Cargo.toml (version/dependency updates, should be trivial to resolve).

git fetch origin master
git rebase origin/master

Resolve Cargo.toml conflict (keep both: your which = "8" + upstream version bump)

Regenerate Cargo.lock with cargo update

git push --force-with-lease

@F0rty-Tw0 F0rty-Tw0 force-pushed the bug/212/cant-resolve-cmd-bat-wrappers branch from a010a3e to f743361 Compare March 6, 2026 10:55
@F0rty-Tw0
Copy link
Author

Hi @F0rty-Tw0, the approach is correct and the 28-file scope is justified given the goal. Centralizing binary resolution into resolved_command() is the right call and the fallback ensures nothing breaks on macOS/Linux.

Two things before we can merge:

  1. In release mode, if which fails to find the binary, resolved_command() silently falls back to Command::new(name), which is the original broken behavior. The warning is only emitted in debug builds. Consider making it unconditional on Windows at least, so users have a signal when the .cmd wrapper isn't being found.
  2. init.rs shows up in the changed files but a PATHEXT fix doesn't obviously need to touch it. Could you clarify what changed there? If it's unrelated, a separate PR would keep the diff reviewable.

The tool_exists() helper, the removal of duplicated which calls across modules, and the troubleshooting doc addition are all good.

Should all be set, please check.
Some formatting happened in init.rs - fixed

@pszymkowiak - done

@F0rty-Tw0 F0rty-Tw0 force-pushed the bug/212/cant-resolve-cmd-bat-wrappers branch from babb108 to 15d4159 Compare March 6, 2026 13:12
carsonm-etched pushed a commit to cmolder/rtk that referenced this pull request Mar 8, 2026
1. Remove `assert!` and `expect` when parsing action count. By
   default we only use the first action count found. Also add
   debug prints for weird cases.
2. Use `resolved_command` in rtk-ai#269
3. Return `Result` from all filter functions, and fall back to
   printing raw output if there is an error

Other changes:
1. Add `run_bazel_filtered<F>` generic function to match Cargo and
   reduce code reuse
2. Merge stdout and stderr in `filter_bazel_query` (should probably
   refactor `bazel query` some more)
@DylanDelobel
Copy link

Tried the build with cargo install --git https://github.com/F0rty-Tw0/rtk --branch bug/212/cant-resolve-cmd-bat-wrappers

Working nicely for me 🎉

@pszymkowiak
Copy link
Collaborator

Hey @F0rty-Tw0, sorry for the confusion — there was a duplicate PR (#492) opened for the same fix. With so many PRs in flight right now, things got mixed up. Your PR was here first and already LGTM'd, so we're going with yours.

Could you rebase on develop (our new integration branch) so we can merge? Thanks for your patience and great work on this!

@F0rty-Tw0
Copy link
Author

@pszymkowiak no problem at all.

I'm on it today.

@F0rty-Tw0 F0rty-Tw0 changed the base branch from master to develop March 11, 2026 09:42
@F0rty-Tw0 F0rty-Tw0 force-pushed the bug/212/cant-resolve-cmd-bat-wrappers branch from 15d4159 to 89c2153 Compare March 11, 2026 10:47
@F0rty-Tw0
Copy link
Author

@pszymkowiak we should be set now. Let me know if anything else is missing.

- add PATHEXT-aware command resolution via which\n- migrate affected command runners to resolved_command\n- add regression coverage for wrapper/fallback behavior
@F0rty-Tw0 F0rty-Tw0 force-pushed the bug/212/cant-resolve-cmd-bat-wrappers branch from 6648d40 to 66eee97 Compare March 11, 2026 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: RTK can't resolve .CMD/.BAT wrappers on Windows (PATHEXT not honored)

4 participants