From 6350dd5ace954d0c8bfba5fd2f9a101d1337c803 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 29 Apr 2026 09:54:38 +0100 Subject: [PATCH] fix: include deleted files in changed lanes --- scripts/changed-lanes.mjs | 6 +-- test/scripts/changed-lanes.test.ts | 81 +++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/scripts/changed-lanes.mjs b/scripts/changed-lanes.mjs index 3e0a95e6ead..b1cacc1f75b 100644 --- a/scripts/changed-lanes.mjs +++ b/scripts/changed-lanes.mjs @@ -236,8 +236,8 @@ export function listChangedPathsFromGit(params) { return [ ...new Set([ ...rangePaths, - ...runGitNameOnlyDiff(["--cached", "--diff-filter=ACMR"], cwd), - ...runGitNameOnlyDiff(["--diff-filter=ACMR"], cwd), + ...runGitNameOnlyDiff(["--cached", "--diff-filter=ACMRD"], cwd), + ...runGitNameOnlyDiff(["--diff-filter=ACMRD"], cwd), ...runGitLsFiles(["--others", "--exclude-standard"], cwd), ]), ].toSorted((left, right) => left.localeCompare(right)); @@ -264,7 +264,7 @@ function runGitLsFiles(extraArgs, cwd = process.cwd()) { } export function listStagedChangedPaths() { - const output = execFileSync("git", ["diff", "--cached", "--name-only", "--diff-filter=ACMR"], { + const output = execFileSync("git", ["diff", "--cached", "--name-only", "--diff-filter=ACMRD"], { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8", maxBuffer: GIT_OUTPUT_MAX_BUFFER, diff --git a/test/scripts/changed-lanes.test.ts b/test/scripts/changed-lanes.test.ts index 8ef049ca01b..90993b77b8b 100644 --- a/test/scripts/changed-lanes.test.ts +++ b/test/scripts/changed-lanes.test.ts @@ -1,5 +1,5 @@ import { execFileSync } from "node:child_process"; -import { mkdirSync, writeFileSync } from "node:fs"; +import { mkdirSync, unlinkSync, writeFileSync } from "node:fs"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { @@ -83,6 +83,85 @@ describe("scripts/changed-lanes", () => { }); }); + it("includes deleted worktree files in the default local diff", () => { + const dir = makeTempRepoRoot(tempDirs, "openclaw-changed-lanes-deleted-"); + git(dir, ["init", "-q", "--initial-branch=main"]); + mkdirSync(path.join(dir, "src", "shared"), { recursive: true }); + writeFileSync( + path.join(dir, "src", "shared", "obsolete.ts"), + "export const value = 1;\n", + "utf8", + ); + git(dir, ["add", "src/shared/obsolete.ts"]); + git(dir, [ + "-c", + "user.email=test@example.com", + "-c", + "user.name=Test User", + "commit", + "-q", + "-m", + "initial", + ]); + + unlinkSync(path.join(dir, "src", "shared", "obsolete.ts")); + + const output = execFileSync( + process.execPath, + [path.join(repoRoot, "scripts", "changed-lanes.mjs"), "--json", "--base", "HEAD"], + { + cwd: dir, + encoding: "utf8", + env: createNestedGitEnv(), + }, + ); + + expect(JSON.parse(output)).toMatchObject({ + paths: ["src/shared/obsolete.ts"], + lanes: { core: true, coreTests: true }, + }); + }); + + it("includes deleted staged files in the staged diff", () => { + const dir = makeTempRepoRoot(tempDirs, "openclaw-changed-lanes-staged-deleted-"); + git(dir, ["init", "-q", "--initial-branch=main"]); + mkdirSync(path.join(dir, "src", "shared"), { recursive: true }); + writeFileSync( + path.join(dir, "src", "shared", "obsolete.ts"), + "export const value = 1;\n", + "utf8", + ); + git(dir, ["add", "src/shared/obsolete.ts"]); + git(dir, [ + "-c", + "user.email=test@example.com", + "-c", + "user.name=Test User", + "commit", + "-q", + "-m", + "initial", + ]); + + unlinkSync(path.join(dir, "src", "shared", "obsolete.ts")); + git(dir, ["add", "src/shared/obsolete.ts"]); + + const output = execFileSync( + process.execPath, + [path.join(repoRoot, "scripts", "changed-lanes.mjs"), "--json", "--staged"], + { + cwd: dir, + encoding: "utf8", + env: createNestedGitEnv(), + }, + ); + + expect(JSON.parse(output)).toMatchObject({ + paths: ["src/shared/obsolete.ts"], + lanes: { core: true, coreTests: true }, + }); + }); + it("ignores the explicit path separator", () => { const result = detectChangedLanes(["--", "scripts/test-live-acp-bind-docker.sh"]);