Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/specs/dor-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

**Both launchers must set `ELECTRON_RUN_AS_NODE=1` themselves** before `exec "$DORMOUSE_NODE" "$DORMOUSE_CLI_JS"`, or under VS Code `dor` silently does nothing and **exits 0** (rationale). **Dormouse-launched terminals must rely on injected env, never on a globally installed Node**; each launcher's `PATH`-`node` fallback is for developer/manual use. **Both launchers must return the CLI's exit status** (`dor/test/launcher.test.mjs`, including `dor.cmd` on Windows).

**Must supply the current directory as `PWD` from the Windows launcher**, replacing stale inherited values.

Public PTY env:

- `DORMOUSE_NODE` — Node runtime the launcher execs; `process.execPath` under VS Code; standalone on Windows: `docs/specs/standalone.md` -> "Windows node subsystem".
Expand All @@ -33,7 +35,7 @@ The CLI also reads `DORMOUSE_AGENT_BROWSER_BIN` and `DORMOUSE_PLAYWRIGHT_BIN`, t

**On Windows the `PATH` prepend must survive Git Bash / MSYS login:** the PTY core strips `ORIGINAL_PATH` from the child env on win32, so a login shell cannot rebuild a pre-prepend `PATH` from it (rationale). No-op for cmd.exe / PowerShell, which never read it.

**A caller cwd must leave the MSYS drive form before it goes on the wire.** Git Bash exports `PWD` as a POSIX path (`/c/Users/…`) that win32 `path.resolve` would mangle into `C:\c\Users\…` and match no Surface.
**Must convert MSYS drive paths to native Windows paths before sending a caller cwd.**

Source of truth: `scripts/stage-dor-cli.mjs`, `dor/bin/dor`, `dor/bin/dor.cmd`, `withoutInheritedMsysOriginalPath` in `standalone/sidecar/pty-core.js`, `callerWorkingDirectory` in `dor/src/commands/shared.ts`.

Expand Down
3 changes: 3 additions & 0 deletions dor/bin/dor.cmd
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
@echo off
setlocal
rem PowerShell and cmd do not maintain an inherited POSIX PWD.
rem The CLI reads it for relative paths and new terminals.
set "PWD=%CD%"
if "%DORMOUSE_NODE%"=="" goto fallback
if "%DORMOUSE_CLI_JS%"=="" goto fallback
rem Under VS Code, DORMOUSE_NODE is the editor's Electron binary; it only
Expand Down
22 changes: 18 additions & 4 deletions dor/test/launcher.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
import { spawnSync } from 'node:child_process';
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

// The staged launchers, run exactly as a terminal runs `dor`. DORMOUSE_CLI_JS
Expand All @@ -13,7 +13,7 @@ const binDir = fileURLToPath(new URL('../bin/', import.meta.url));
const isWindows = process.platform === 'win32';

async function withStubCli(run) {
const dir = await mkdtemp(join(tmpdir(), 'dor-launcher-'));
const dir = await mkdtemp(join(tmpdir(), 'dor launcher-'));
const cliJs = join(dir, 'cli.mjs');
await writeFile(cliJs, 'process.exit(Number(process.argv[2]));\n');
try {
Expand All @@ -23,12 +23,13 @@ async function withStubCli(run) {
}
}

function runLauncher(cliJs, code) {
const env = { ...process.env, DORMOUSE_NODE: process.execPath, DORMOUSE_CLI_JS: cliJs };
function runLauncher(cliJs, code, options = {}) {
const env = { ...process.env, DORMOUSE_NODE: process.execPath, DORMOUSE_CLI_JS: cliJs, ...options.env };
if (isWindows) {
// Node refuses to spawn a .cmd directly; go through cmd.exe as a shell does.
return spawnSync('cmd.exe', ['/d', '/s', '/c', `""${join(binDir, 'dor.cmd')}" ${code}"`], {
env,
cwd: options.cwd,
windowsVerbatimArguments: true,
});
}
Expand All @@ -44,3 +45,16 @@ for (const code of [0, 7]) {
});
});
}

for (const inheritedPwd of ['C:\\stale\\parent', undefined]) {
test('dor.cmd supplies the caller directory despite ' + (inheritedPwd ? 'stale' : 'missing') + ' PWD', { skip: !isWindows }, async () => {
await withStubCli(async (cliJs) => {
await writeFile(cliJs, 'console.log(JSON.stringify({cwd: process.cwd(), pwd: process.env.PWD}));\n');
const cwd = dirname(cliJs);
const result = runLauncher(cliJs, 0, { cwd, env: { PWD: inheritedPwd } });
assert.equal(result.status, 0, String(result.stderr));
const actual = JSON.parse(String(result.stdout));
assert.equal(actual.pwd.toLowerCase(), actual.cwd.toLowerCase());
});
});
}
Loading