* Find bash executable path on Windows. * * We strongly prefer Git Bash (Git for Windows) and explicitly avoid WSL launchers.
(params: FindWindowsBashParams)
| 107 | * We strongly prefer Git Bash (Git for Windows) and explicitly avoid WSL launchers. |
| 108 | */ |
| 109 | function findWindowsBash(params: FindWindowsBashParams): string | null { |
| 110 | const { env, execSyncFn, existsSyncFn } = params; |
| 111 | |
| 112 | const gitRoots: string[] = [ |
| 113 | // Git for Windows default paths |
| 114 | "C:\\Program Files\\Git", |
| 115 | "C:\\Program Files (x86)\\Git", |
| 116 | // Chocolatey installation |
| 117 | "C:\\tools\\git", |
| 118 | ]; |
| 119 | |
| 120 | // User-local Git installation |
| 121 | if (env.LOCALAPPDATA) { |
| 122 | gitRoots.push(WIN_PATH.join(env.LOCALAPPDATA, "Programs", "Git")); |
| 123 | } |
| 124 | |
| 125 | // Scoop installation |
| 126 | if (env.USERPROFILE) { |
| 127 | gitRoots.push(WIN_PATH.join(env.USERPROFILE, "scoop", "apps", "git", "current")); |
| 128 | } |
| 129 | |
| 130 | // Prefer known Git for Windows install locations. |
| 131 | const commonPaths = gitRoots.flatMap((root) => [ |
| 132 | WIN_PATH.join(root, "bin", "bash.exe"), |
| 133 | WIN_PATH.join(root, "usr", "bin", "bash.exe"), |
| 134 | ]); |
| 135 | |
| 136 | for (const bashPath of commonPaths) { |
| 137 | if (existsSyncFn(bashPath) && looksLikeGitForWindowsBash(bashPath, existsSyncFn)) { |
| 138 | return bashPath; |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | // Also check if Git is in PATH and derive bash path from it. |
| 143 | try { |
| 144 | const result = execSyncFn("where git", { |
| 145 | encoding: "utf8", |
| 146 | stdio: ["pipe", "pipe", "ignore"], |
| 147 | windowsHide: true, |
| 148 | }); |
| 149 | for (const gitExePath of parseWhereOutput(result)) { |
| 150 | if (!existsSyncFn(gitExePath)) { |
| 151 | continue; |
| 152 | } |
| 153 | |
| 154 | const gitRoot = findGitRootFromGitExePath(gitExePath, existsSyncFn); |
| 155 | if (!gitRoot) { |
| 156 | continue; |
| 157 | } |
| 158 | |
| 159 | const candidateBashPaths = [ |
| 160 | WIN_PATH.join(gitRoot, "bin", "bash.exe"), |
| 161 | WIN_PATH.join(gitRoot, "usr", "bin", "bash.exe"), |
| 162 | ]; |
| 163 | |
| 164 | for (const bashPath of candidateBashPaths) { |
| 165 | if (existsSyncFn(bashPath) && looksLikeGitForWindowsBash(bashPath, existsSyncFn)) { |
| 166 | return bashPath; |
no test coverage detected