mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(scripts): bound check-file-utils git lookup (#111582)
Co-authored-by: Vincent Koc <vincentkoc@ieee.org> Co-authored-by: lijing <li.jing25@xydigit.com>
This commit is contained in:
@@ -14,6 +14,8 @@ export const REPO_SCAN_SKIPPED_DIR_NAMES: ReadonlySet<string> = new Set([
|
||||
"node_modules",
|
||||
"vendor",
|
||||
]);
|
||||
// Bound the Git lookup before falling back to direct filesystem traversal.
|
||||
const GIT_LS_FILES_TIMEOUT_MS = 30_000;
|
||||
|
||||
export function isCodeFile(filePath: string): boolean {
|
||||
if (filePath.endsWith(".d.ts")) {
|
||||
@@ -89,6 +91,8 @@ export function listRepoFilesSync(
|
||||
return execFileSync("git", ["-C", repoRoot, "ls-files", "--", ...roots], {
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "pipe", "ignore"],
|
||||
timeout: GIT_LS_FILES_TIMEOUT_MS,
|
||||
killSignal: "SIGKILL",
|
||||
})
|
||||
.split(/\r?\n/u)
|
||||
.filter(Boolean)
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
// Check File Utils tests cover check file utils script behavior.
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
collectFilesSync,
|
||||
isCodeFile,
|
||||
listRepoFilesSync,
|
||||
relativeToCwd,
|
||||
toPosixPath,
|
||||
} from "../../scripts/check-file-utils.js";
|
||||
import { createScriptTestHarness } from "./test-helpers.js";
|
||||
|
||||
const execFileSyncMock = vi.hoisted(() => vi.fn(() => ""));
|
||||
|
||||
vi.mock("node:child_process", async (importOriginal) => {
|
||||
const original = (await importOriginal()) as typeof import("node:child_process");
|
||||
return { ...original, execFileSync: execFileSyncMock };
|
||||
});
|
||||
|
||||
const { createTempDir } = createScriptTestHarness();
|
||||
|
||||
describe("scripts/check-file-utils isCodeFile", () => {
|
||||
@@ -64,3 +72,45 @@ describe("scripts/check-file-utils relativeToCwd", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("scripts/check-file-utils listRepoFilesSync", () => {
|
||||
afterEach(() => {
|
||||
execFileSyncMock.mockReset();
|
||||
});
|
||||
|
||||
it("bounds git ls-files with a timeout and kill signal", () => {
|
||||
execFileSyncMock.mockReturnValue("src/keep.ts\nsrc/skip.d.ts\n");
|
||||
|
||||
expect(
|
||||
listRepoFilesSync("/fake/repo", {
|
||||
includeFile: (filePath) => isCodeFile(filePath),
|
||||
}),
|
||||
).toEqual(["src/keep.ts"]);
|
||||
expect(execFileSyncMock).toHaveBeenCalledWith(
|
||||
"git",
|
||||
expect.arrayContaining(["-C", "/fake/repo", "ls-files", "--"]),
|
||||
expect.objectContaining({
|
||||
timeout: 30_000,
|
||||
killSignal: "SIGKILL",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("falls back to filesystem traversal when git ls-files times out", () => {
|
||||
const error: NodeJS.ErrnoException & { signal?: string } = new Error("Command timed out");
|
||||
error.code = "ETIMEDOUT";
|
||||
error.signal = "SIGKILL";
|
||||
execFileSyncMock.mockImplementation(() => {
|
||||
throw error;
|
||||
});
|
||||
const rootDir = createTempDir("openclaw-check-file-utils-fallback-");
|
||||
fs.mkdirSync(path.join(rootDir, "src"), { recursive: true });
|
||||
fs.writeFileSync(path.join(rootDir, "src", "keep.ts"), "");
|
||||
|
||||
expect(
|
||||
listRepoFilesSync(rootDir, {
|
||||
includeFile: (filePath) => filePath.endsWith(".ts"),
|
||||
}),
|
||||
).toEqual(["src/keep.ts"]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user