mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix(remote): hand remote/docker launch commands to bash verbatim
respawn-pane runs `bash -c "<ssh …>"` through the local sh, so every `$` in
the remote command is expanded on the Codeman host. withRemoteTmuxPath
(`export PATH="$HOME/.local/bin:…:$PATH"; tmux …`, 5b9445de) therefore sends
the Codeman host's home and PATH to the remote host: a remote user with a
different home (tmux in ~/.nix-profile/bin) gets "tmux: command not found" and
every new remote pane exits 127. `${SHELL:-/bin/sh}` in the remote launch was
the local shell for the same reason.
Remote and docker commands are already quoted for the far end, so they now go
to `bash -c` single-quoted (bashCArg); local commands keep the double-quoted
form. Two tests run the captured respawn-pane line (create and respawn)
through a real sh with a foreign HOME/PATH and check that ssh gets `$HOME` and
`$PATH` unexpanded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 2818e9455489b9acd65841258df4cd035609954c)
This commit is contained in:
1 parent
46b85fa6d0
commit
21256202ba
2 files changed
+90
-2
No files matched your search
+16
-2
@@ -2661,7 +2661,7 @@ export class TmuxManager extends EventEmitter implements TerminalMultiplexer {
|
||||
// pane launch in /tmp, then cd inside bash against the current mount table.
|
||||
const launchCmd = remote || docker ? fullCmd : `cd ${JSON.stringify(workingDir)} && ${fullCmd}`;
|
||||
execSync(
|
||||
`${this.tmux()} respawn-pane -k -c ${TMUX_LAUNCH_CWD} -t "${muxName}" bash -c ${JSON.stringify(launchCmd)}`,
|
||||
`${this.tmux()} respawn-pane -k -c ${TMUX_LAUNCH_CWD} -t "${muxName}" bash -c ${bashCArg(launchCmd, !!(remote || docker))}`,
|
||||
{
|
||||
timeout: EXEC_TIMEOUT_MS,
|
||||
stdio: 'ignore',
|
||||
@@ -2914,7 +2914,7 @@ export class TmuxManager extends EventEmitter implements TerminalMultiplexer {
|
||||
// -c /tmp + cd bounce — see createSession() for rationale (stale FUSE state).
|
||||
const launchCmd = remote || docker ? fullCmd : `cd ${JSON.stringify(workingDir)} && ${fullCmd}`;
|
||||
await execAsync(
|
||||
`${this.tmux()} respawn-pane -k -c ${TMUX_LAUNCH_CWD} -t "${muxName}" bash -c ${JSON.stringify(launchCmd)}`,
|
||||
`${this.tmux()} respawn-pane -k -c ${TMUX_LAUNCH_CWD} -t "${muxName}" bash -c ${bashCArg(launchCmd, !!(remote || docker))}`,
|
||||
{
|
||||
timeout: EXEC_TIMEOUT_MS,
|
||||
}
|
||||
@@ -4663,6 +4663,20 @@ export class TmuxManager extends EventEmitter implements TerminalMultiplexer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `bash -c` argument of a pane launch (`respawn-pane … bash -c <arg>`, run through the
|
||||
* local sh). A remote or docker command is already quoted for the shell at the far end and
|
||||
* must reach bash verbatim, so it goes in single quotes. Double quotes (JSON.stringify) let
|
||||
* the local sh expand every `$` first: the PATH bootstrap of `withRemoteTmuxPath`
|
||||
* (`$HOME/.local/bin:…:$PATH`) arrived on the remote host as this host's home and PATH, so
|
||||
* a remote user with another home found no tmux and every new remote pane exited 127.
|
||||
* `${SHELL:-/bin/sh}` in the remote launch was the local shell for the same reason.
|
||||
* Local commands keep their double-quoted form.
|
||||
*/
|
||||
function bashCArg(launchCmd: string, verbatim: boolean): string {
|
||||
return verbatim ? shellescape(launchCmd) : JSON.stringify(launchCmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shell-escape a string for use as a single argument.
|
||||
* Wraps in single quotes, escaping any embedded single quotes.
|
||||
|
||||
Reference in new issue
Block a user