Przeglądaj źródła

Merge pull request #710 from mhenke/fix/568-windows-attach-dir

fix(multiplexer): normalize Windows backslash paths in attach --dir (#568)
Alvin 1 miesiąc temu
rodzic
commit
54215445f5

+ 7 - 2
src/multiplexer/herdr/index.ts

@@ -19,6 +19,7 @@ import {
   buildOpencodeAttachCommand,
   findBinary,
   gracefulClosePane,
+  normalizePathForShell,
 } from '../shared';
 import type { Multiplexer, PaneResult } from '../types';
 
@@ -74,6 +75,10 @@ export class HerdrMultiplexer implements Multiplexer {
     }
 
     try {
+      // Normalize Windows backslashes→/ so sh -lc (MSYS2) doesn't
+      // corrupt --cwd (issue #568).
+      const attachDir = normalizePathForShell(directory);
+
       // 1. Split the parent pane to create a new one
       const splitArgs = [
         herdr,
@@ -83,7 +88,7 @@ export class HerdrMultiplexer implements Multiplexer {
         '--direction',
         this.paneDirection,
         '--cwd',
-        directory,
+        attachDir,
         '--no-focus',
       ];
 
@@ -125,7 +130,7 @@ export class HerdrMultiplexer implements Multiplexer {
       const opencodeCmd = buildOpencodeAttachCommand(
         sessionId,
         serverUrl,
-        directory,
+        attachDir,
       );
 
       log('[herdr] spawnPane: running attach command', {

+ 43 - 2
src/multiplexer/shared.test.ts

@@ -41,8 +41,7 @@ describe('gracefulClosePane', () => {
       };
     });
 
-    const { gracefulClosePane } =
-      await importShared();
+    const { gracefulClosePane } = await importShared();
     const ok = await gracefulClosePane('tmux', '%1', {
       ctrlC: ['send-keys', '-t', '%1', 'C-c'],
       close: ['kill-pane', '-t', '%1'],
@@ -103,3 +102,45 @@ describe('gracefulClosePane', () => {
     expect(ok).toBe(false);
   });
 });
+
+describe('buildOpencodeAttachCommand', () => {
+  test('normalizes Windows backslash paths to forward slashes', async () => {
+    const original = process.platform;
+    Object.defineProperty(process, 'platform', {
+      value: 'win32',
+      configurable: true,
+    });
+    try {
+      const { buildOpencodeAttachCommand } = await importShared();
+      const cmd = buildOpencodeAttachCommand(
+        'sess',
+        'url',
+        'C:\\Users\\foo\\repo',
+      );
+      expect(cmd).toContain('C:/Users/foo/repo');
+    } finally {
+      Object.defineProperty(process, 'platform', {
+        value: original,
+        configurable: true,
+      });
+    }
+  });
+
+  test('leaves non-Windows paths unchanged', async () => {
+    const original = process.platform;
+    Object.defineProperty(process, 'platform', {
+      value: 'linux',
+      configurable: true,
+    });
+    try {
+      const { buildOpencodeAttachCommand } = await importShared();
+      const cmd = buildOpencodeAttachCommand('sess', 'url', '/home/user/repo');
+      expect(cmd).toContain('/home/user/repo');
+    } finally {
+      Object.defineProperty(process, 'platform', {
+        value: original,
+        configurable: true,
+      });
+    }
+  });
+});

+ 9 - 1
src/multiplexer/shared.ts

@@ -12,11 +12,19 @@ export function quoteShellArg(value: string): string {
   return `'${value.replace(/'/g, `'\\''`)}'`;
 }
 
+/** Normalize Windows backslashes to / so sh -lc (MSYS2/Git Bash) doesn't treat them as escape chars. */
+export function normalizePathForShell(directory: string): string {
+  return process.platform === 'win32'
+    ? directory.replace(/\\/g, '/')
+    : directory;
+}
+
 export function buildOpencodeAttachCommand(
   sessionId: string,
   serverUrl: string,
   directory: string,
 ): string {
+  const attachDir = normalizePathForShell(directory);
   return [
     'opencode',
     'attach',
@@ -24,7 +32,7 @@ export function buildOpencodeAttachCommand(
     '--session',
     quoteShellArg(sessionId),
     '--dir',
-    quoteShellArg(directory),
+    quoteShellArg(attachDir),
   ].join(' ');
 }