mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 14:48:28 +00:00
fix(sandbox): parse Windows bind mounts in fs-path mapping
This commit is contained in:
@@ -25,6 +25,19 @@ describe("parseSandboxBindMount", () => {
|
|||||||
writable: true,
|
writable: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("parses Windows drive-letter host paths", () => {
|
||||||
|
expect(parseSandboxBindMount("C:\\Users\\kai\\workspace:/workspace:ro")).toEqual({
|
||||||
|
hostRoot: path.resolve("C:\\Users\\kai\\workspace"),
|
||||||
|
containerRoot: "/workspace",
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
expect(parseSandboxBindMount("D:/data:/workspace-data:rw")).toEqual({
|
||||||
|
hostRoot: path.resolve("D:/data"),
|
||||||
|
containerRoot: "/workspace-data",
|
||||||
|
writable: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("resolveSandboxFsPathWithMounts", () => {
|
describe("resolveSandboxFsPathWithMounts", () => {
|
||||||
|
|||||||
@@ -23,21 +23,29 @@ type ParsedBindMount = {
|
|||||||
writable: boolean;
|
writable: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type SplitBindSpec = {
|
||||||
|
host: string;
|
||||||
|
container: string;
|
||||||
|
options: string;
|
||||||
|
};
|
||||||
|
|
||||||
export function parseSandboxBindMount(spec: string): ParsedBindMount | null {
|
export function parseSandboxBindMount(spec: string): ParsedBindMount | null {
|
||||||
const trimmed = spec.trim();
|
const trimmed = spec.trim();
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const parts = trimmed.split(":");
|
|
||||||
if (parts.length < 2) {
|
const parsed = splitBindSpec(trimmed);
|
||||||
|
if (!parsed) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const hostToken = (parts[0] ?? "").trim();
|
|
||||||
const containerToken = (parts[1] ?? "").trim();
|
const hostToken = parsed.host.trim();
|
||||||
|
const containerToken = parsed.container.trim();
|
||||||
if (!hostToken || !containerToken || !path.posix.isAbsolute(containerToken)) {
|
if (!hostToken || !containerToken || !path.posix.isAbsolute(containerToken)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const optionsToken = parts.slice(2).join(":").trim().toLowerCase();
|
const optionsToken = parsed.options.trim().toLowerCase();
|
||||||
const optionParts = optionsToken
|
const optionParts = optionsToken
|
||||||
? optionsToken
|
? optionsToken
|
||||||
.split(",")
|
.split(",")
|
||||||
@@ -52,6 +60,37 @@ 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) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
host: parts[0] ?? "",
|
||||||
|
container: parts[1] ?? "",
|
||||||
|
options: parts.slice(2).join(":"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function buildSandboxFsMounts(sandbox: SandboxContext): SandboxFsMount[] {
|
export function buildSandboxFsMounts(sandbox: SandboxContext): SandboxFsMount[] {
|
||||||
const mounts: SandboxFsMount[] = [
|
const mounts: SandboxFsMount[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user