refactor: unwrap Shell namespace + self-reexport (#22964)

This commit is contained in:
Kit Langton
2026-04-16 20:11:19 -04:00
committed by GitHub
parent c0bfccc15e
commit 54078c4cae
+30 -30
View File
@@ -8,12 +8,11 @@ import { setTimeout as sleep } from "node:timers/promises"
const SIGKILL_TIMEOUT_MS = 200 const SIGKILL_TIMEOUT_MS = 200
export namespace Shell { const BLACKLIST = new Set(["fish", "nu"])
const BLACKLIST = new Set(["fish", "nu"]) const LOGIN = new Set(["bash", "dash", "fish", "ksh", "sh", "zsh"])
const LOGIN = new Set(["bash", "dash", "fish", "ksh", "sh", "zsh"]) const POSIX = new Set(["bash", "dash", "ksh", "sh", "zsh"])
const POSIX = new Set(["bash", "dash", "ksh", "sh", "zsh"])
export async function killTree(proc: ChildProcess, opts?: { exited?: () => boolean }): Promise<void> { export async function killTree(proc: ChildProcess, opts?: { exited?: () => boolean }): Promise<void> {
const pid = proc.pid const pid = proc.pid
if (!pid || opts?.exited?.()) return if (!pid || opts?.exited?.()) return
@@ -42,9 +41,9 @@ export namespace Shell {
proc.kill("SIGKILL") proc.kill("SIGKILL")
} }
} }
} }
function full(file: string) { function full(file: string) {
if (process.platform !== "win32") return file if (process.platform !== "win32") return file
const shell = Filesystem.windowsPath(file) const shell = Filesystem.windowsPath(file)
if (path.win32.dirname(shell) !== ".") { if (path.win32.dirname(shell) !== ".") {
@@ -52,34 +51,34 @@ export namespace Shell {
return shell return shell
} }
return which(shell) || shell return which(shell) || shell
} }
function pick() { function pick() {
const pwsh = which("pwsh.exe") const pwsh = which("pwsh.exe")
if (pwsh) return pwsh if (pwsh) return pwsh
const powershell = which("powershell.exe") const powershell = which("powershell.exe")
if (powershell) return powershell if (powershell) return powershell
} }
function select(file: string | undefined, opts?: { acceptable?: boolean }) { function select(file: string | undefined, opts?: { acceptable?: boolean }) {
if (file && (!opts?.acceptable || !BLACKLIST.has(name(file)))) return full(file) if (file && (!opts?.acceptable || !BLACKLIST.has(name(file)))) return full(file)
if (process.platform === "win32") { if (process.platform === "win32") {
const shell = pick() const shell = pick()
if (shell) return shell if (shell) return shell
} }
return fallback() return fallback()
} }
export function gitbash() { export function gitbash() {
if (process.platform !== "win32") return if (process.platform !== "win32") return
if (Flag.OPENCODE_GIT_BASH_PATH) return Flag.OPENCODE_GIT_BASH_PATH if (Flag.OPENCODE_GIT_BASH_PATH) return Flag.OPENCODE_GIT_BASH_PATH
const git = which("git") const git = which("git")
if (!git) return if (!git) return
const file = path.join(git, "..", "..", "bin", "bash.exe") const file = path.join(git, "..", "..", "bin", "bash.exe")
if (Filesystem.stat(file)?.size) return file if (Filesystem.stat(file)?.size) return file
} }
function fallback() { function fallback() {
if (process.platform === "win32") { if (process.platform === "win32") {
const file = gitbash() const file = gitbash()
if (file) return file if (file) return file
@@ -89,22 +88,23 @@ export namespace Shell {
const bash = which("bash") const bash = which("bash")
if (bash) return bash if (bash) return bash
return "/bin/sh" return "/bin/sh"
} }
export function name(file: string) { export function name(file: string) {
if (process.platform === "win32") return path.win32.parse(Filesystem.windowsPath(file)).name.toLowerCase() if (process.platform === "win32") return path.win32.parse(Filesystem.windowsPath(file)).name.toLowerCase()
return path.basename(file).toLowerCase() return path.basename(file).toLowerCase()
}
export function login(file: string) {
return LOGIN.has(name(file))
}
export function posix(file: string) {
return POSIX.has(name(file))
}
export const preferred = lazy(() => select(process.env.SHELL))
export const acceptable = lazy(() => select(process.env.SHELL, { acceptable: true }))
} }
export function login(file: string) {
return LOGIN.has(name(file))
}
export function posix(file: string) {
return POSIX.has(name(file))
}
export const preferred = lazy(() => select(process.env.SHELL))
export const acceptable = lazy(() => select(process.env.SHELL, { acceptable: true }))
export * as Shell from "./shell"