fix: handle Windows and UNC bind mount parsing

This commit is contained in:
Peter Steinberger
2026-02-17 02:08:56 +01:00
parent 13ae1ae056
commit 6244ef9ea8
2 changed files with 32 additions and 26 deletions

View File

@@ -1,12 +1,12 @@
import path from "node:path";
import { describe, expect, it } from "vitest";
import type { SandboxContext } from "./types.js";
import {
buildSandboxFsMounts,
parseSandboxBindMount,
resolveSandboxFsPathWithMounts,
} from "./fs-paths.js";
import { createSandboxTestContext } from "./test-fixtures.js";
import type { SandboxContext } from "./types.js";
function createSandbox(overrides?: Partial<SandboxContext>): SandboxContext {
return createSandboxTestContext({ overrides });
@@ -38,6 +38,14 @@ describe("parseSandboxBindMount", () => {
writable: true,
});
});
it("parses UNC-style host paths", () => {
expect(parseSandboxBindMount("//server/share:/workspace:ro")).toEqual({
hostRoot: path.resolve("//server/share"),
containerRoot: "/workspace",
writable: false,
});
});
});
describe("resolveSandboxFsPathWithMounts", () => {

View File

@@ -1,7 +1,7 @@
import path from "node:path";
import type { SandboxContext } from "./types.js";
import { resolveSandboxInputPath, resolveSandboxPath } from "../sandbox-paths.js";
import { SANDBOX_AGENT_WORKSPACE_MOUNT } from "./constants.js";
import type { SandboxContext } from "./types.js";
export type SandboxFsMount = {
hostRoot: string;
@@ -61,36 +61,34 @@ export function parseSandboxBindMount(spec: string): ParsedBindMount | null {
}
function splitBindSpec(spec: string): SplitBindSpec | null {
// Windows drive-letter host path: C:\\path:/container[:opts] or C:/path:/container[:opts]
if (/^[A-Za-z]:[\\/]/.test(spec)) {
const hostEnd = spec.indexOf(":", 2);
if (hostEnd === -1) {
return null;
}
const host = spec.slice(0, hostEnd);
const rest = spec.slice(hostEnd + 1);
const optionsStart = rest.indexOf(":");
if (optionsStart === -1) {
return { host, container: rest, options: "" };
}
return {
host,
container: rest.slice(0, optionsStart),
options: rest.slice(optionsStart + 1),
};
}
const parts = spec.split(":");
if (parts.length < 2) {
const separator = getHostContainerSeparatorIndex(spec);
if (separator === -1) {
return null;
}
const host = spec.slice(0, separator);
const rest = spec.slice(separator + 1);
const optionsStart = rest.indexOf(":");
if (optionsStart === -1) {
return { host, container: rest, options: "" };
}
return {
host: parts[0] ?? "",
container: parts[1] ?? "",
options: parts.slice(2).join(":"),
host,
container: rest.slice(0, optionsStart),
options: rest.slice(optionsStart + 1),
};
}
function getHostContainerSeparatorIndex(spec: string): number {
const hasDriveLetterPrefix = /^[A-Za-z]:[\\/]/.test(spec);
for (let i = hasDriveLetterPrefix ? 2 : 0; i < spec.length; i += 1) {
if (spec[i] === ":") {
return i;
}
}
return -1;
}
export function buildSandboxFsMounts(sandbox: SandboxContext): SandboxFsMount[] {
const mounts: SandboxFsMount[] = [
{