copilot-api / src /lib /shell.ts
imseldrith's picture
Initial upload from Colab
9e27976 verified
import { execSync } from "node:child_process"
import process from "node:process"
type ShellName = "bash" | "zsh" | "fish" | "powershell" | "cmd" | "sh"
type EnvVars = Record<string, string | undefined>
function getShell(): ShellName {
const { platform, ppid, env } = process
if (platform === "win32") {
try {
const command = `wmic process get ParentProcessId,Name | findstr "${ppid}"`
const parentProcess = execSync(command, { stdio: "pipe" }).toString()
if (parentProcess.toLowerCase().includes("powershell.exe")) {
return "powershell"
}
} catch {
return "cmd"
}
return "cmd"
} else {
const shellPath = env.SHELL
if (shellPath) {
if (shellPath.endsWith("zsh")) return "zsh"
if (shellPath.endsWith("fish")) return "fish"
if (shellPath.endsWith("bash")) return "bash"
}
return "sh"
}
}
/**
* Generates a copy-pasteable script to set multiple environment variables
* and run a subsequent command.
* @param {EnvVars} envVars - An object of environment variables to set.
* @param {string} commandToRun - The command to run after setting the variables.
* @returns {string} The formatted script string.
*/
export function generateEnvScript(
envVars: EnvVars,
commandToRun: string = "",
): string {
const shell = getShell()
const filteredEnvVars = Object.entries(envVars).filter(
([, value]) => value !== undefined,
) as Array<[string, string]>
let commandBlock: string
switch (shell) {
case "powershell": {
commandBlock = filteredEnvVars
.map(([key, value]) => `$env:${key} = ${value}`)
.join("; ")
break
}
case "cmd": {
commandBlock = filteredEnvVars
.map(([key, value]) => `set ${key}=${value}`)
.join(" & ")
break
}
case "fish": {
commandBlock = filteredEnvVars
.map(([key, value]) => `set -gx ${key} ${value}`)
.join("; ")
break
}
default: {
// bash, zsh, sh
const assignments = filteredEnvVars
.map(([key, value]) => `${key}=${value}`)
.join(" ")
commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : ""
break
}
}
if (commandBlock && commandToRun) {
const separator = shell === "cmd" ? " & " : " && "
return `${commandBlock}${separator}${commandToRun}`
}
return commandBlock || commandToRun
}