mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
Fixes #11592. ## Problem WSL starts Windows programs in the current directory, translated to `\\wsl.localhost\<distro>\<cwd>`. When that path exceeds MAX_PATH, every Windows program fails to start with `Invalid argument`. pi inherits its cwd when spawning `powershell.exe`, so in a deep directory: - clipboard image paste returns `null` (the PowerShell backend fails, stderr is discarded) - copy via `powershell.exe` (WSL without WSLg) fails - opening the browser for sign-in fails (`xdg-open` on WSL runs `explorer.exe`) Reproduced on WSL (FedoraLinux-44): `powershell.exe` and `cmd.exe` work from a 225-char cwd and fail from 230. With an image on the Windows clipboard, `readClipboardImage()` returns the PNG from `/tmp` and `null` from a 245-char cwd; with this change it returns the PNG from both. `LongPathsEnabled=1` does not help. ## Changes - `runClipboardCommand` and `openBrowser` run from `/` on POSIX. These tools never use the cwd (temp files are passed by absolute path), and `/` is always the shortest UNC path. `tmpdir()` was not used because `$TMPDIR` can itself be deep. - The external editor keeps pi's cwd on purpose, so project-relative paths and integrated terminals keep working. A Windows editor such as `code` can still fail from a deep WSL directory, as with git's `core.editor`. A comment documents this. - External editor failures were silent: the UI redrew over the error immediately. pi now shows `Failed to launch external editor: <cmd>`, `External editor exited with code N; prompt unchanged`, or the signal name. This shows in the status line for the main editor and inline in the extension editor dialog. ## Testing - New tests: clipboard commands run from `/` (POSIX); an editor that cannot be launched is reported (POSIX); the existing failure test checks the message. - Verified on WSL by running the real modules: clipboard image paste from a deep cwd, and editor success, exit code 1, launch failure, and SIGTERM. - On Windows, the 3 existing `external-editor.test.ts` tests already fail on `main`: the editor command is split on spaces, so `C:\Program Files\nodejs\node.exe` breaks. Not addressed here. This PR is AI-generated.
55 lines
2.5 KiB
TypeScript
55 lines
2.5 KiB
TypeScript
import { resolve } from "node:path";
|
|
import { describe, expect, test } from "vitest";
|
|
import { runClipboardCommand } from "../src/utils/clipboard-command.ts";
|
|
|
|
describe("clipboard commands", () => {
|
|
test("preserves binary output and distinguishes empty success from failure", async () => {
|
|
expect(
|
|
await runClipboardCommand(process.execPath, ["-e", "process.stdout.write(Buffer.from([0, 255, 10]))"]),
|
|
).toEqual(Buffer.from([0, 255, 10]));
|
|
expect(await runClipboardCommand(process.execPath, ["-e", ""])).toEqual(Buffer.alloc(0));
|
|
expect(await runClipboardCommand(process.execPath, ["-e", "process.exit(1)"])).toBeUndefined();
|
|
expect(await runClipboardCommand("pi-clipboard-command-does-not-exist", [])).toBeUndefined();
|
|
});
|
|
test("sends Unicode input to clipboard writers", async () => {
|
|
const script =
|
|
"let text = ''; process.stdin.setEncoding('utf8'); process.stdin.on('data', c => text += c); process.stdin.on('end', () => process.exit(text === 'café 日本語' ? 0 : 1));";
|
|
expect(await runClipboardCommand(process.execPath, ["-e", script], { input: "café 日本語" })).toEqual(
|
|
Buffer.alloc(0),
|
|
);
|
|
});
|
|
test("times out without blocking the event loop", async () => {
|
|
let ticks = 0;
|
|
const timer = setInterval(() => ticks++, 10);
|
|
try {
|
|
expect(
|
|
await runClipboardCommand(process.execPath, ["-e", "setInterval(() => {}, 1000)"], { timeoutMs: 200 }),
|
|
).toBeUndefined();
|
|
expect(ticks).toBeGreaterThan(5);
|
|
} finally {
|
|
clearInterval(timer);
|
|
}
|
|
});
|
|
// #11179: clipboard daemons must not share pi's process group, or Ctrl+Z suspend stops them.
|
|
test.skipIf(process.platform === "win32")("runs commands outside pi's process group", async () => {
|
|
const childPgid = (await runClipboardCommand("sh", ["-c", "ps -o pgid= -p $$"]))?.toString("utf8").trim();
|
|
const ownPgid = (await runClipboardCommand("ps", ["-o", "pgid=", "-p", String(process.pid)]))
|
|
?.toString("utf8")
|
|
.trim();
|
|
expect(childPgid).toMatch(/^\d+$/);
|
|
expect(ownPgid).toMatch(/^\d+$/);
|
|
expect(childPgid).not.toBe(ownPgid);
|
|
});
|
|
// #11592: WSL cannot start Windows executables from a cwd whose UNC path exceeds MAX_PATH.
|
|
test("runs commands from the filesystem root", async () => {
|
|
const cwd = await runClipboardCommand(process.execPath, ["-e", "process.stdout.write(process.cwd())"]);
|
|
expect(cwd?.toString("utf8")).toBe(resolve("/"));
|
|
});
|
|
test("rejects output above the buffer limit", async () => {
|
|
expect(
|
|
await runClipboardCommand(process.execPath, ["-e", "process.stdout.write(Buffer.alloc(1024))"], {
|
|
maxBufferBytes: 16,
|
|
}),
|
|
).toBeUndefined();
|
|
});
|
|
});
|