1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix syncing shell env on TCSH and CSH

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-10-21 13:48:41 -04:00
parent 97fc7cf6fb
commit 01d7fbaeec

View File

@ -8,7 +8,7 @@ import { basename } from "path";
import type { EnvironmentVariables } from "./compute-shell-environment.injectable"; import type { EnvironmentVariables } from "./compute-shell-environment.injectable";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
interface UnixShellEnvOptions { export interface UnixShellEnvOptions {
signal?: AbortSignal; signal?: AbortSignal;
} }
@ -16,7 +16,11 @@ export type ComputeUnixShellEnvironment = (shell: string, opts?: UnixShellEnvOpt
const computeUnixShellEnvironmentInjectable = getInjectable({ const computeUnixShellEnvironmentInjectable = getInjectable({
id: "compute-unix-shell-environment", id: "compute-unix-shell-environment",
instantiate: (): ComputeUnixShellEnvironment => async (shell, opts) => { instantiate: (): ComputeUnixShellEnvironment => {
const powerShellName = /^pwsh(-preview)?$/;
const nonBashLikeShellName = /^t?csh$/;
return async (shell, opts = {}) => {
const runAsNode = process.env["ELECTRON_RUN_AS_NODE"]; const runAsNode = process.env["ELECTRON_RUN_AS_NODE"];
const noAttach = process.env["ELECTRON_NO_ATTACH_CONSOLE"]; const noAttach = process.env["ELECTRON_NO_ATTACH_CONSOLE"];
const env = { const env = {
@ -25,38 +29,40 @@ const computeUnixShellEnvironmentInjectable = getInjectable({
ELECTRON_NO_ATTACH_CONSOLE: "1", ELECTRON_NO_ATTACH_CONSOLE: "1",
}; };
const mark = randomUUID().replace(/-/g, ""); const mark = randomUUID().replace(/-/g, "");
const regex = new RegExp(`${mark}(.*)${mark}`); const regex = new RegExp(`${mark}(\\{.*\\})${mark}`);
const shellName = basename(shell); const shellName = basename(shell);
let command: string; const { command, shellArgs } = (() => {
let shellArgs: string[]; if (powerShellName.test(shellName)) {
if (/^pwsh(-preview)?$/.test(shellName)) {
// Older versions of PowerShell removes double quotes sometimes so we use "double single quotes" which is how // Older versions of PowerShell removes double quotes sometimes so we use "double single quotes" which is how
// you escape single quotes inside of a single quoted string. // you escape single quotes inside of a single quoted string.
command = `& '${process.execPath}' -p '''${mark}'' + JSON.stringify(process.env) + ''${mark}'''`; return {
shellArgs = ["-Login", "-Command"]; command: `Command '${process.execPath}' -p '\\"${mark}\\" + JSON.stringify(process.env) + \\"${mark}\\"'`,
} else { shellArgs: ["-Login"],
command = `'${process.execPath}' -p '"${mark}" + JSON.stringify(process.env) + "${mark}"'`; };
}
if (shellName === "tcsh") { return {
shellArgs = ["-ic"]; command: `'${process.execPath}' -p '"${mark}" + JSON.stringify(process.env) + "${mark}"'`,
} else { shellArgs: nonBashLikeShellName.test(shellName)
shellArgs = ["-ilc"]; // tcsh and csh don't support any other options when providing the -l (login) shell option
} ? ["-l"]
} // zsh (at least, maybe others) don't load RC files when in non-interactive mode, even when using -l (login) option
: ["-li"],
};
})();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const shellProcess = spawn(shell, [...shellArgs, command], { const shellProcess = spawn(shell, shellArgs, {
detached: true, detached: true,
stdio: ["ignore", "pipe", "pipe"],
env, env,
}); });
const stdout: Buffer[] = []; const stdout: Buffer[] = [];
opts?.signal?.addEventListener("abort", () => shellProcess.kill()); opts.signal?.addEventListener("abort", () => shellProcess.kill());
shellProcess.stdout.on("data", b => stdout.push(b));
shellProcess.on("error", (err) => reject(err)); shellProcess.on("error", (err) => reject(err));
shellProcess.stdout.on("data", b => stdout.push(b));
shellProcess.on("close", (code, signal) => { shellProcess.on("close", (code, signal) => {
if (code || signal) { if (code || signal) {
return reject(new Error(`Unexpected return code from spawned shell (code: ${code}, signal: ${signal})`)); return reject(new Error(`Unexpected return code from spawned shell (code: ${code}, signal: ${signal})`));
@ -85,7 +91,9 @@ const computeUnixShellEnvironmentInjectable = getInjectable({
reject(err); reject(err);
} }
}); });
shellProcess.stdin.end(command);
}); });
};
}, },
causesSideEffects: true, causesSideEffects: true,
}); });