mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:09:34 +00:00
test: share runtime scan filters and cached test scans
This commit is contained in:
@@ -2,6 +2,18 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
export const DEFAULT_REPO_SCAN_SKIP_DIR_NAMES = new Set([".git", "dist", "node_modules"]);
|
||||
export const DEFAULT_RUNTIME_SOURCE_ROOTS = ["src", "extensions"] as const;
|
||||
export const DEFAULT_RUNTIME_SOURCE_EXTENSIONS = [".ts", ".tsx"] as const;
|
||||
export const RUNTIME_SOURCE_SKIP_PATTERNS = [
|
||||
/\.test\.tsx?$/,
|
||||
/\.test-helpers\.tsx?$/,
|
||||
/\.test-utils\.tsx?$/,
|
||||
/\.e2e\.tsx?$/,
|
||||
/\.d\.ts$/,
|
||||
/\/(?:__tests__|tests)\//,
|
||||
/\/[^/]*test-helpers(?:\.[^/]+)?\.tsx?$/,
|
||||
/\/[^/]*test-utils(?:\.[^/]+)?\.tsx?$/,
|
||||
] as const;
|
||||
|
||||
export type RepoFileScanOptions = {
|
||||
roots: readonly string[];
|
||||
@@ -10,10 +22,15 @@ export type RepoFileScanOptions = {
|
||||
skipHiddenDirectories?: boolean;
|
||||
shouldIncludeFile?: (relativePath: string) => boolean;
|
||||
};
|
||||
export type RuntimeSourceScanOptions = {
|
||||
roots?: readonly string[];
|
||||
extensions?: readonly string[];
|
||||
};
|
||||
|
||||
type PendingDir = {
|
||||
absolutePath: string;
|
||||
};
|
||||
const runtimeSourceScanCache = new Map<string, Promise<Array<string>>>();
|
||||
|
||||
function shouldSkipDirectory(
|
||||
name: string,
|
||||
@@ -29,6 +46,18 @@ function hasAllowedExtension(fileName: string, extensions: readonly string[]): b
|
||||
return extensions.some((extension) => fileName.endsWith(extension));
|
||||
}
|
||||
|
||||
function normalizeRelativePath(relativePath: string): string {
|
||||
return relativePath.replaceAll("\\", "/");
|
||||
}
|
||||
|
||||
function toSortedUnique(values: readonly string[]): Array<string> {
|
||||
return [...new Set(values)].toSorted();
|
||||
}
|
||||
|
||||
function getRuntimeScanCacheKey(repoRoot: string, roots: readonly string[]): string {
|
||||
return `${repoRoot}::${toSortedUnique(roots).join(",")}`;
|
||||
}
|
||||
|
||||
export async function listRepoFiles(
|
||||
repoRoot: string,
|
||||
options: RepoFileScanOptions,
|
||||
@@ -76,3 +105,34 @@ export async function listRepoFiles(
|
||||
files.sort((a, b) => a.localeCompare(b));
|
||||
return files;
|
||||
}
|
||||
|
||||
export function shouldSkipRuntimeSourcePath(relativePath: string): boolean {
|
||||
const normalizedPath = normalizeRelativePath(relativePath);
|
||||
return RUNTIME_SOURCE_SKIP_PATTERNS.some((pattern) => pattern.test(normalizedPath));
|
||||
}
|
||||
|
||||
export async function listRuntimeSourceFiles(
|
||||
repoRoot: string,
|
||||
options: RuntimeSourceScanOptions = {},
|
||||
): Promise<Array<string>> {
|
||||
const roots = options.roots ?? DEFAULT_RUNTIME_SOURCE_ROOTS;
|
||||
const requestedExtensions = toSortedUnique(
|
||||
options.extensions ?? DEFAULT_RUNTIME_SOURCE_EXTENSIONS,
|
||||
);
|
||||
const cacheKey = getRuntimeScanCacheKey(repoRoot, roots);
|
||||
|
||||
let pending = runtimeSourceScanCache.get(cacheKey);
|
||||
if (!pending) {
|
||||
pending = listRepoFiles(repoRoot, {
|
||||
roots,
|
||||
extensions: DEFAULT_RUNTIME_SOURCE_EXTENSIONS,
|
||||
skipHiddenDirectories: true,
|
||||
shouldIncludeFile: (relativePath) => !shouldSkipRuntimeSourcePath(relativePath),
|
||||
});
|
||||
runtimeSourceScanCache.set(cacheKey, pending);
|
||||
}
|
||||
const files = await pending;
|
||||
return files.filter((filePath) =>
|
||||
requestedExtensions.some((extension) => filePath.endsWith(extension)),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user