Conversation
eea2173 to
161aa97
Compare
|
A configured shell silently fell back to Windows PowerShell 5.1 when it came from a Store/MSIX install. Those expose the executable as a Windows app-execution alias, a zero-byte AppExecLink reparse point that stat and which cannot see, even though CreateProcess resolves it by name. So which() returned null for pwsh, resolve() returned undefined, and select() dropped through to win()[0]. where.exe does resolve app-execution aliases, so use it as the tiebreaker when which() finds nothing: trust a known shell family the OS can locate, and keep falling back when the shell genuinely is not installed. Closes anomalyco#41426
161aa97 to
ab4a761
Compare
|
Thanks — this was useful, and three of the five landed. I've pushed the changes to the v2 version of this work (#48968), since that is where the branch now targets. Blocking call on every miss — you were right, and it's worse than "tens of ms". I measured a single if (configShell) return select(configShell, options, filter, bin) // ← returns here
const cached = input.priority === "compat" ? defaultCompatible : defaultConfiguredA configured Returning a bare name — agreed, and adopted.
So this fixes existence checks and anything doing path arithmetic, but a caller that stats the result still gets an error — just
So a missing or blocked Test coverage — fair, fixed. A stub
|
Issue for this PR
Closes #41426
Type of change
What does this PR do?
On Windows, a configured
shell: "pwsh"is silently ignored and commands run under PowerShell 5.1 instead.When PowerShell 7 is installed from the Store/MSIX package,
pwshon PATH is a Windows app-execution alias: a zero-byteAppExecLinkreparse point, not a real executable.CreateProcessresolves it by name, butstatdoes not see it.Shell.resolve()goes throughwhich(), which stats candidates, so the alias resolves to nothing andselect()falls back towin()[0]— Windows PowerShell 5.1 — without reporting that the configured shell was not found.Measured on Windows 11 with a Store-installed alias:
When
which()finds nothing on Windows for a name we already recognise as a shell, this falls back towhere.exe, which does resolve aliases, and returns the bare name soCreateProcessperforms the lookup.where.exedistinguishes the two cases cleanly: exit 0 for an installed alias (winget), exit 1 for something genuinely absent (pwshwhen not installed,zsh,ksh).The fallback is deliberately narrow — Windows only, only after
which()has already failed, and only for names in the existing shell table — so an unrelated missing binary still resolves toundefinedas before.How did you verify your code works?
undefined, guarding the case wherewhere.exemight otherwise return a non-shell match.bun test test/shell.test.tsinpackages/corepasses (12/12), and the dependentshell/bashtool suites inpackages/opencodestill pass.wingetas a stand-in alias, and confirmedwhere.exeexits 1 for shells that are actually absent.bun typecheckpasses.Checklist