From f5a95203a46a32968c1107571cd4b2061b49c6e9 Mon Sep 17 00:00:00 2001 From: Qiiks Date: Sat, 11 Apr 2026 16:06:42 +0530 Subject: [PATCH] fix(shell-env): check SHELL before PSModulePath for shell detection On Windows, PSModulePath is always set by the system even when the active shell is Git Bash (via SHELL env var). This caused the non-interactive-env hook to generate PowerShell syntax ($env:VAR=val) for bash shells, resulting in 15+ errors per command. The fix prioritizes SHELL over PSModulePath since an explicit SHELL variable indicates the user's chosen shell, while PSModulePath is just a system-wide module path that doesn't indicate the active shell. Fixes: #3338 --- src/shared/shell-env.test.ts | 17 ++++++++++++++--- src/shared/shell-env.ts | 16 ++++++++++------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/shared/shell-env.test.ts b/src/shared/shell-env.test.ts index c0e53306f..60a4aaba4 100644 --- a/src/shared/shell-env.test.ts +++ b/src/shared/shell-env.test.ts @@ -45,7 +45,8 @@ describe("shell-env", () => { expect(result).toBe("unix") }) - test("#given PSModulePath is set #when detectShellType is called #then returns powershell", () => { + test("#given PSModulePath is set without SHELL #when detectShellType is called #then returns powershell", () => { + delete process.env.SHELL process.env.PSModulePath = "C:\\Program Files\\PowerShell\\Modules" Object.defineProperty(process, "platform", { value: "win32" }) @@ -74,14 +75,24 @@ describe("shell-env", () => { expect(result).toBe("unix") }) - test("#given PSModulePath takes priority over SHELL #when both are set #then returns powershell", () => { + test("#given SHELL takes priority over PSModulePath #when both are set #then returns unix", () => { process.env.PSModulePath = "C:\\Program Files\\PowerShell\\Modules" process.env.SHELL = "/bin/bash" Object.defineProperty(process, "platform", { value: "win32" }) const result = detectShellType() - expect(result).toBe("powershell") + expect(result).toBe("unix") + }) + + test("#given SHELL set to Git Bash on Windows with PSModulePath #when detectShellType is called #then returns unix", () => { + process.env.PSModulePath = "C:\\Program Files\\PowerShell\\Modules" + process.env.SHELL = "C:\\Program Files\\Git\\bin\\bash.exe" + Object.defineProperty(process, "platform", { value: "win32" }) + + const result = detectShellType() + + expect(result).toBe("unix") }) }) diff --git a/src/shared/shell-env.ts b/src/shared/shell-env.ts index 2ffa59ac2..d34ee3254 100644 --- a/src/shared/shell-env.ts +++ b/src/shared/shell-env.ts @@ -4,15 +4,15 @@ export type ShellType = "unix" | "powershell" | "cmd" | "csh" * Detect the current shell type based on environment variables. * * Detection priority: - * 1. PSModulePath → PowerShell - * 2. SHELL env var → Unix shell + * 1. SHELL env var → Unix shell (explicit user choice takes precedence) + * 2. PSModulePath → PowerShell * 3. Platform fallback → win32: cmd, others: unix + * + * Note: SHELL is checked before PSModulePath because on Windows, PSModulePath + * is always set by the system even when the active shell is Git Bash or WSL. + * An explicit SHELL variable indicates the user's chosen shell overrides that. */ export function detectShellType(): ShellType { - if (process.env.PSModulePath) { - return "powershell" - } - if (process.env.SHELL) { const shell = process.env.SHELL if (shell.includes("csh") || shell.includes("tcsh")) { @@ -21,6 +21,10 @@ export function detectShellType(): ShellType { return "unix" } + if (process.env.PSModulePath) { + return "powershell" + } + return process.platform === "win32" ? "cmd" : "unix" }