



















@@ -63,7 +63,11 @@ function makeFakeGit(
6363"process.exit(response.status ?? 0);",
6464].join("\n");
6565writeFileSync(gitPath, `${script}\n`, "utf8");
66-writeFileSync(`${gitPath}.cmd`, `@echo off\r\n"${process.execPath}" "%~dp0git" %*\r\n`, "utf8");
66+writeFileSync(
67+`${gitPath}.cmd`,
68+`@echo off\r\n"${process.execPath}" "%~dp0git" %*\r\n`,
69+"utf8",
70+);
6771chmodSync(gitPath, 0o755);
6872return binDir;
6973}
@@ -283,35 +287,40 @@ describe("scripts/crabbox-wrapper", () => {
283287]);
284288});
285289286-it("finds a Crabbox checkout next to the Git common dir in linked worktrees", () => {
287-const fakeWorkspaceParent = mkdtempSync(path.join(tmpdir(), "openclaw-linked-worktree-"));
288-tempDirs.push(fakeWorkspaceParent);
289-const gitCommonDir = path.join(fakeWorkspaceParent, "openclaw", ".git");
290-const crabboxBinDir = path.join(fakeWorkspaceParent, "crabbox", "bin");
291-mkdirSync(gitCommonDir, { recursive: true });
292-writeFakeCrabbox(crabboxBinDir, "provider: aws\n");
293-const gitResponses = {
294-["rev-parse\u0000--git-common-dir"]: { stdout: `${gitCommonDir}\n` },
295-};
296-const gitBinDir = makeFakeGit(gitResponses);
297-298-const result = spawnSync(
299-process.execPath,
300-["scripts/crabbox-wrapper.mjs", "run", "--provider", "aws", "--", "echo ok"],
301-{
302-cwd: repoRoot,
303-encoding: "utf8",
304-env: {
305- ...process.env,
306-OPENCLAW_FAKE_GIT_RESPONSES: JSON.stringify(gitResponses),
307-PATH: [gitBinDir, path.dirname(process.execPath)].join(path.delimiter),
290+const itWithPosixLinkedWorktreeFixture = process.platform === "win32" ? it.skip : it;
291+292+itWithPosixLinkedWorktreeFixture(
293+"finds a Crabbox checkout next to the Git common dir in linked worktrees",
294+() => {
295+const fakeWorkspaceParent = mkdtempSync(path.join(tmpdir(), "openclaw-linked-worktree-"));
296+tempDirs.push(fakeWorkspaceParent);
297+const gitCommonDir = path.join(fakeWorkspaceParent, "openclaw", ".git");
298+const crabboxBinDir = path.join(fakeWorkspaceParent, "crabbox", "bin");
299+mkdirSync(gitCommonDir, { recursive: true });
300+writeFakeCrabbox(crabboxBinDir, "provider: aws\n");
301+const gitResponses = {
302+["rev-parse\u0000--git-common-dir"]: { stdout: `${gitCommonDir}\n` },
303+};
304+const gitBinDir = makeFakeGit(gitResponses);
305+306+const result = spawnSync(
307+process.execPath,
308+["scripts/crabbox-wrapper.mjs", "run", "--provider", "aws", "--", "echo ok"],
309+{
310+cwd: repoRoot,
311+encoding: "utf8",
312+env: {
313+ ...process.env,
314+OPENCLAW_FAKE_GIT_RESPONSES: JSON.stringify(gitResponses),
315+PATH: [gitBinDir, path.dirname(process.execPath)].join(path.delimiter),
316+},
308317},
309-},
310-);
318+);
311319312-expect(result.status).toBe(0);
313-expect(parseFakeCrabboxOutput(result).args).toContain("aws");
314-});
320+expect(result.status).toBe(0);
321+expect(parseFakeCrabboxOutput(result).args).toContain("aws");
322+},
323+);
315324316325it("accepts advertised providers from wrapped Crabbox help", () => {
317326const result = runWrapper(
@@ -355,18 +364,14 @@ describe("scripts/crabbox-wrapper", () => {
355364}
356365357366it("falls back to normal sync decisions when git is missing from PATH", () => {
358-const binDir = makeFakeCrabbox(
367+const result = runWrapper(
359368"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
360-);
361-const result = spawnSync(
362-process.execPath,
363-["scripts/crabbox-wrapper.mjs", "run", "--provider", "aws", "--", "echo ok"],
369+["run", "--provider", "aws", "--", "echo ok"],
364370{
365-cwd: repoRoot,
366-encoding: "utf8",
367-env: {
368- ...process.env,
369-PATH: [binDir, path.dirname(process.execPath)].join(path.delimiter),
371+gitResponses: {
372+["rev-parse\u0000--git-common-dir"]: { status: 1 },
373+["config\u0000--bool\u0000core.sparseCheckout"]: { status: 1 },
374+["sparse-checkout\u0000list"]: { status: 1 },
370375},
371376},
372377);
@@ -493,6 +498,35 @@ describe("scripts/crabbox-wrapper", () => {
493498expect(parseFakeCrabboxOutput(result).cwd).toContain("openclaw-crabbox-sync-");
494499});
495500501+it("uses a temporary full checkout when clean sparse AWS syncs reuse a lease", () => {
502+const result = runWrapper(
503+"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
504+[
505+"run",
506+"--provider",
507+"aws",
508+"--target",
509+"windows",
510+"--id",
511+"cbx_existing",
512+"--",
513+"corepack",
514+"pnpm",
515+"build",
516+],
517+{
518+gitResponses: {
519+["config\u0000--bool\u0000core.sparseCheckout"]: { stdout: "true\n" },
520+["status\u0000--porcelain=v1"]: { stdout: "" },
521+},
522+},
523+);
524+525+expect(result.status).toBe(0);
526+expect(result.stderr).toContain("syncing from temporary full checkout");
527+expect(parseFakeCrabboxOutput(result).cwd).toContain("openclaw-crabbox-sync-");
528+});
529+496530it("bootstraps Git metadata for sparse changed gates on remote raw syncs", () => {
497531const result = runWrapper(
498532"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
@@ -626,7 +660,7 @@ describe("scripts/crabbox-wrapper", () => {
626660expect(parseFakeCrabboxOutput(result).cwd).toBe(repoRoot);
627661});
628662629-it("keeps existing AWS leases on the original sparse checkout", () => {
663+it("uses a temporary full checkout when existing AWS leases sync clean sparse worktrees", () => {
630664const result = runWrapper(
631665"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
632666["run", "--provider", "aws", "--id", "cbx_existing", "--", "echo ok"],
@@ -639,8 +673,8 @@ describe("scripts/crabbox-wrapper", () => {
639673);
640674641675expect(result.status).toBe(0);
642-expect(result.stderr).not.toContain("syncing from temporary full checkout");
643-expect(parseFakeCrabboxOutput(result).cwd).toBe(repoRoot);
676+expect(result.stderr).toContain("syncing from temporary full checkout");
677+expect(parseFakeCrabboxOutput(result).cwd).toContain("openclaw-crabbox-sync-");
644678});
645679646680it("uses a temporary full checkout when clean sparse branches differ from the Blacksmith ref", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。