Skip to content

Commit 257c677

Browse files
committed
fix(core): capture native cwd from Git Bash on Windows
1 parent 8098861 commit 257c677

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

‎packages/core/src/tests/tool-handlers.test.ts‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ for (const replacement of ["deleted", "file"]) {
249249
const subdir = path.join(workspace, "child");
250250
fs.mkdirSync(subdir);
251251
const context = createContext(`bash-cwd-${replacement}`, workspace);
252-
assert.equal((await handleBashTool({ command: "cd child" }, context)).ok, true);
252+
const changed = await handleBashTool({ command: "cd child" }, context);
253+
assert.equal(changed.ok, true);
254+
assert.equal(fs.realpathSync(String(changed.metadata?.cwd)), fs.realpathSync(subdir));
253255
const retained = await handleBashTool({ command: "pwd" }, context);
254256
assert.equal(fs.realpathSync(String(retained.metadata?.startCwd)), fs.realpathSync(subdir));
255257
fs.rmdirSync(subdir);
@@ -260,6 +262,25 @@ for (const replacement of ["deleted", "file"]) {
260262
});
261263
}
262264

265+
test(
266+
"Bash preserves Git Bash virtual mount cwd as a native Windows directory",
267+
{ skip: process.platform !== "win32" },
268+
async () => {
269+
const context = createContext("bash-virtual-cwd", createTempWorkspace());
270+
const changed = await handleBashTool({ command: "cd /tmp && pwd -W" }, context);
271+
assert.equal(changed.ok, true);
272+
const nativeCwd = String(changed.metadata?.cwd);
273+
assert.equal(path.isAbsolute(nativeCwd), true);
274+
assert.equal(fs.statSync(nativeCwd).isDirectory(), true);
275+
assert.equal(fs.realpathSync(nativeCwd), fs.realpathSync((changed.output ?? "").trim()));
276+
277+
const retained = await handleBashTool({ command: "pwd -W" }, context);
278+
assert.equal(retained.ok, true);
279+
assert.equal(fs.realpathSync(String(retained.metadata?.startCwd)), fs.realpathSync(nativeCwd));
280+
assert.equal(fs.realpathSync((retained.output ?? "").trim()), fs.realpathSync(nativeCwd));
281+
}
282+
);
283+
263284
test("Bash reports an invalid project root as a spawn failure", { timeout: 3_000 }, async () => {
264285
const root = path.join(createTempWorkspace(), "missing");
265286
const result = await handleBashTool({ command: "pwd" }, createContext("bash-invalid-root", root));

‎packages/core/src/tools/bash-handler.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ function buildShellCommand(command: string): {
147147
const initCommand = buildShellInitCommand(shellPath);
148148
const disableExtglobCommand = buildDisableExtglobCommand(shellPath);
149149
const normalizedCommand = rewriteWindowsNullRedirect(command);
150+
// Git Bash mounts such as /tmp and /usr cannot be mapped by replacing
151+
// separators or drive prefixes. Ask Bash for the native path while it is alive.
152+
const cwdExpression = process.platform === "win32" ? '"$(builtin pwd -W)"' : '"$PWD"';
150153
const wrappedParts = [];
151154
if (initCommand) {
152155
wrappedParts.push(initCommand);
@@ -157,7 +160,7 @@ function buildShellCommand(command: string): {
157160
wrappedParts.push(
158161
normalizedCommand,
159162
"__DEEPCODE_STATUS__=$?",
160-
`printf '%s%s\\n' "${marker}" "$PWD"`,
163+
`printf '%s%s\\n' "${marker}" ${cwdExpression}`,
161164
"exit $__DEEPCODE_STATUS__"
162165
);
163166
const wrappedCommand = `{ ${wrappedParts.join("; ")}; } < /dev/null`;

0 commit comments

Comments
 (0)