diff --git a/src/utils/__tests__/shell.test.ts b/src/utils/__tests__/shell.test.ts index 9c2b23aaa55..1a9939f076c 100644 --- a/src/utils/__tests__/shell.test.ts +++ b/src/utils/__tests__/shell.test.ts @@ -1,3 +1,5 @@ +// npx jest src/utils/__tests__/shell.test.ts + import * as vscode from "vscode" import { userInfo } from "os" import { getShell } from "../shell" @@ -90,6 +92,20 @@ describe("Shell Detection Tests", () => { expect(getShell()).toBe("/bin/bash") }) + it("uses Git Bash when profile indicates Git Bash source", () => { + mockVsCodeConfig("windows", "Git Bash", { + "Git Bash": { source: "Git Bash" }, + }) + expect(getShell()).toBe("/usr/bin/bash") + }) + + it("uses Git Bash when profile name includes 'git bash'", () => { + mockVsCodeConfig("windows", "MinGW Git Bash", { + "MinGW Git Bash": {}, + }) + expect(getShell()).toBe("/usr/bin/bash") + }) + it("defaults to cmd.exe if no special profile is matched", () => { mockVsCodeConfig("windows", "CommandPrompt", { CommandPrompt: {}, diff --git a/src/utils/shell.ts b/src/utils/shell.ts index 2f7ffb3a882..d31e49fa921 100644 --- a/src/utils/shell.ts +++ b/src/utils/shell.ts @@ -7,6 +7,7 @@ const SHELL_PATHS = { POWERSHELL_LEGACY: "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", CMD: "C:\\Windows\\System32\\cmd.exe", WSL_BASH: "/bin/bash", + GIT_BASH: "/usr/bin/bash", // Unix paths MAC_DEFAULT: "/bin/zsh", LINUX_DEFAULT: "/bin/bash", @@ -28,7 +29,7 @@ type MacTerminalProfiles = Record interface WindowsTerminalProfile { path?: string - source?: "PowerShell" | "WSL" + source?: "PowerShell" | "WSL" | "Git Bash" } type WindowsTerminalProfiles = Record @@ -114,6 +115,10 @@ function getWindowsShellFromVSCode(): string | null { return SHELL_PATHS.WSL_BASH } + if (profile?.source === "Git Bash" || defaultProfileName.toLowerCase().includes("git bash")) { + return SHELL_PATHS.GIT_BASH + } + // If nothing special detected, we assume cmd return SHELL_PATHS.CMD } @@ -162,66 +167,57 @@ function getShellFromEnv(): string | null { const { env } = process if (process.platform === "win32") { - // On Windows, COMSPEC typically holds cmd.exe - return env.COMSPEC || "C:\\Windows\\System32\\cmd.exe" + // On Windows, COMSPEC typically holds cmd.exe. + return env.SHELL || env.COMSPEC || "C:\\Windows\\System32\\cmd.exe" } if (process.platform === "darwin") { - // On macOS/Linux, SHELL is commonly the environment variable + // On macOS/Linux, SHELL is commonly the environment variable. return env.SHELL || "/bin/zsh" } if (process.platform === "linux") { - // On Linux, SHELL is commonly the environment variable + // On Linux, SHELL is commonly the environment variable. return env.SHELL || "/bin/bash" } + return null } -// ----------------------------------------------------- -// 4) Publicly Exposed Shell Getter -// ----------------------------------------------------- - -export function getShell(): string { - // 1. Check VS Code config first. +function fallbackShell() { + // On Windows, if we got here, we have no config, no COMSPEC, and one + // very messed up operating system. Use CMD as a last resort. if (process.platform === "win32") { - // Special logic for Windows - const windowsShell = getWindowsShellFromVSCode() - if (windowsShell) { - return windowsShell - } - } else if (process.platform === "darwin") { - // macOS from VS Code - const macShell = getMacShellFromVSCode() - if (macShell) { - return macShell - } - } else if (process.platform === "linux") { - // Linux from VS Code - const linuxShell = getLinuxShellFromVSCode() - if (linuxShell) { - return linuxShell - } + return SHELL_PATHS.CMD } - // 2. If no shell from VS Code, try userInfo() - const userInfoShell = getShellFromUserInfo() - if (userInfoShell) { - return userInfoShell - } + // On macOS/Linux, fallback to a POSIX shell - This is the behavior of our + // old shell detection method. + return SHELL_PATHS.FALLBACK +} - // 3. If still nothing, try environment variable - const envShell = getShellFromEnv() - if (envShell) { - return envShell - } +// ----------------------------------------------------- +// 4) Publicly Exposed Shell Getter +// ----------------------------------------------------- - // 4. Finally, fall back to a default - if (process.platform === "win32") { - // On Windows, if we got here, we have no config, no COMSPEC, and one very messed up operating system. - // Use CMD as a last resort - return SHELL_PATHS.CMD - } - // On macOS/Linux, fallback to a POSIX shell - This is the behavior of our old shell detection method. - return SHELL_PATHS.FALLBACK +export function getShell() { + // 1. Check VS Code config first. + // 2. If no shell from VS Code, try userInfo(). + // 3. If still nothing, try environment variable. + // 4. Finally, fall back to a default. + let vsCodeShell: string | null = null + + switch (process.platform) { + case "win32": + vsCodeShell = getWindowsShellFromVSCode() + break + case "darwin": + vsCodeShell = getMacShellFromVSCode() + break + case "linux": + vsCodeShell = getLinuxShellFromVSCode() + break + } + + return vsCodeShell || getShellFromUserInfo() || getShellFromEnv() || fallbackShell() }