Fix zsh integration runtime file modes (#976)

This commit is contained in:
Mohamed Boudra
2026-05-13 15:58:20 +08:00
committed by GitHub
parent 16c27d7404
commit 9d7d1e8500
2 changed files with 37 additions and 5 deletions
@@ -20,7 +20,7 @@ import {
} from "node:fs";
import { spawnSync } from "node:child_process";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { tmpdir, userInfo } from "node:os";
const hasZsh = existsSync("/bin/zsh");
@@ -216,6 +216,13 @@ function lastNonEmptyLineIsPrompt(state: ReturnType<TerminalSession["getState"]>
return last === "$";
}
function removeZshShellIntegrationRuntimeDir(): void {
rmSync(join(tmpdir(), `${userInfo().username || "unknown"}-paseo-zsh`), {
recursive: true,
force: true,
});
}
describe.skipIf(isPlatform("win32"))("terminal POSIX-only", () => {
it("sets zsh wrapper env when spawning zsh", () => {
const resolvedEnv = buildTerminalEnvironment({
@@ -233,6 +240,27 @@ describe.skipIf(isPlatform("win32"))("terminal POSIX-only", () => {
expect(existsSync(join(resolvedEnv.ZDOTDIR, "paseo-integration.zsh"))).toBe(true);
});
it("reuses zsh shell integration copied from read-only source files", () => {
const integrationSourceDir = mkdtempSync(join(tmpdir(), "paseo-zsh-readonly-source-"));
const tmpHome = mkdtempSync(join(tmpdir(), "paseo-zsh-readonly-home-"));
temporaryDirs.push(integrationSourceDir, tmpHome);
cpSync(resolveZshShellIntegrationDir(), integrationSourceDir, { recursive: true });
chmodSync(join(integrationSourceDir, ".zshenv"), 0o444);
chmodSync(join(integrationSourceDir, "paseo-integration.zsh"), 0o444);
removeZshShellIntegrationRuntimeDir();
const buildEnvironment = () =>
buildTerminalEnvironment({
shell: "/bin/zsh",
env: { HOME: tmpHome },
zshShellIntegrationDir: integrationSourceDir,
});
buildEnvironment();
expect(buildEnvironment).not.toThrow();
});
describe("send input", () => {
it("executes a simple echo command", async () => {
const session = trackSession(
+8 -4
View File
@@ -1,12 +1,13 @@
import * as pty from "node-pty";
import xterm, { type Terminal as TerminalType } from "@xterm/headless";
import { randomUUID } from "crypto";
import { chmodSync, copyFileSync, existsSync, mkdirSync, statSync } from "node:fs";
import { chmodSync, existsSync, mkdirSync, readFileSync, statSync } from "node:fs";
import { tmpdir, userInfo } from "node:os";
import { basename, dirname, join } from "node:path";
import { createRequire } from "node:module";
import { fileURLToPath } from "node:url";
import { createExternalProcessEnv } from "../server/paseo-env.js";
import { writePrivateFileAtomicSync } from "../server/private-files.js";
import type { TerminalCell, TerminalState } from "../shared/messages.js";
const { Terminal } = xterm;
@@ -202,10 +203,13 @@ function prepareZshShellIntegrationRuntimeDir(sourceDir = resolveZshShellIntegra
const runtimeDir = resolveZshShellIntegrationRuntimeDir();
mkdirSync(runtimeDir, { recursive: true, mode: 0o700 });
chmodSync(runtimeDir, 0o700);
copyFileSync(join(readableSourceDir, ".zshenv"), join(runtimeDir, ".zshenv"));
copyFileSync(
join(readableSourceDir, "paseo-integration.zsh"),
writePrivateFileAtomicSync(
join(runtimeDir, ".zshenv"),
readFileSync(join(readableSourceDir, ".zshenv")),
);
writePrivateFileAtomicSync(
join(runtimeDir, "paseo-integration.zsh"),
readFileSync(join(readableSourceDir, "paseo-integration.zsh")),
);
return runtimeDir;
}