fix: support Git in WSL mounted workspaces

This commit is contained in:
Codex
2026-07-10 09:56:29 +02:00
parent ebff879da6
commit 29aa159558
3 changed files with 48 additions and 6 deletions
+24 -1
View File
@@ -154,6 +154,26 @@ describe("ssh host apply-patch fs backend", () => {
});
});
describe("ssh WSL mounted workspace ownership", () => {
test("bridges the mounted workspace owner to Git for direct and child shell commands", () => {
const direct = parseSshInvocation("G14-WSL:/mnt/d/Work/demo", ["git", "rev-parse", "--show-toplevel"]);
const childShell = parseSshInvocation("G14-WSL:/mnt/d/Work/demo", ["bash", "--", "git status --short"]);
for (const invocation of [direct, childShell]) {
expect(invocation.parsed.remoteCommand).toContain("UNIDESK_TRANS_HOST_WORKSPACE_OWNER_UID");
expect(invocation.parsed.remoteCommand).toContain('export SUDO_UID="$UNIDESK_TRANS_HOST_WORKSPACE_OWNER_UID"');
expect(invocation.parsed.remoteCommand).toContain('stat -c %u .');
}
});
test("does not change ownership trust for ordinary Linux workspaces", () => {
const invocation = parseSshInvocation("D601:/home/ubuntu/workspace/demo", ["git", "status", "--short"]);
expect(invocation.parsed.remoteCommand).not.toContain("UNIDESK_TRANS_HOST_WORKSPACE_OWNER_UID");
expect(invocation.parsed.remoteCommand).not.toContain("SUDO_UID");
});
});
describe("ssh stdout bounded streaming", () => {
test("uses YAML output policy defaults and clamps env override", () => {
const policy = readCliOutputPolicy();
@@ -291,7 +311,10 @@ describe("ssh backend selection", () => {
"",
].join("\n"));
try {
const plan = sshCaptureBackendPlan(minimalConfig("198.51.100.4"), { UNIDESK_TRANS_CONFIG_PATH: configPath } as NodeJS.ProcessEnv);
const plan = sshCaptureBackendPlan(minimalConfig("198.51.100.4"), {
UNIDESK_TRANS_CONFIG_PATH: configPath,
UNIDESK_MAIN_SERVER_IP: "198.51.100.4",
} as NodeJS.ProcessEnv);
expect(plan.backend).toBe("remote-frontend-websocket");
expect(plan.remoteHost).toBe("198.51.100.4");
+22 -4
View File
@@ -1105,7 +1105,7 @@ export function parseSshInvocation(target: string, args: string[]): ParsedSshInv
throw new Error(`ssh k3s shorthand is unsupported; use route syntax instead: trans ${route.providerId}:k3s ${operationArgs.slice(1).join(" ")}`.trim());
}
const parsed = parseSshArgs(operationArgs, route.raw);
return { providerId: route.providerId, route, parsed: withTransHostProxyEnv(route, parsed) };
return { providerId: route.providerId, route, parsed: withTransHostEnvironment(route, parsed) };
}
export function parseSshRoute(target: string): ParsedSshRoute {
@@ -2469,11 +2469,29 @@ function shellScriptStdinPrefix(): string {
return `${shellScriptPrelude()}\n`;
}
function withTransHostProxyEnv(route: ParsedSshRoute, parsed: ParsedSshArgs): ParsedSshArgs {
function withTransHostEnvironment(route: ParsedSshRoute, parsed: ParsedSshArgs): ParsedSshArgs {
if (route.plane !== "host" || parsed.remoteCommand === null) return parsed;
const preludes: string[] = [];
const ownershipPrelude = transHostWorkspaceOwnershipPrelude(route.workspace);
if (ownershipPrelude !== null) preludes.push(ownershipPrelude);
const rule = readTransHostProxyEnvRule(route.providerId);
if (rule === null || rule.applyTo !== "host-posix-commands") return parsed;
return { ...parsed, remoteCommand: `${transHostProxyEnvPrelude(rule)}; ${parsed.remoteCommand}` };
if (rule !== null && rule.applyTo === "host-posix-commands") preludes.push(transHostProxyEnvPrelude(rule));
if (preludes.length === 0) return parsed;
return { ...parsed, remoteCommand: `${preludes.join("; ")}; ${parsed.remoteCommand}` };
}
function transHostWorkspaceOwnershipPrelude(workspace: string | null): string | null {
if (workspace === null || !/^\/mnt\/[A-Za-z](?:\/|$)/u.test(workspace)) return null;
return [
'if [ "$(id -u)" -eq 0 ]; then',
' UNIDESK_TRANS_HOST_WORKSPACE_OWNER_UID="$(stat -c %u . 2>/dev/null || true)"',
' case "$UNIDESK_TRANS_HOST_WORKSPACE_OWNER_UID" in',
' ""|*[!0-9]*|0) ;;',
' *) export SUDO_UID="$UNIDESK_TRANS_HOST_WORKSPACE_OWNER_UID" ;;',
' esac',
' export UNIDESK_TRANS_HOST_WORKSPACE_OWNER_UID',
'fi',
].join("\n");
}
function transHostProxyEnvPrelude(rule: TransHostProxyEnvRule): string {