mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:50:43 +00:00
refactor: delete unused repo scan helper
This commit is contained in:
@@ -1,138 +0,0 @@
|
||||
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[];
|
||||
extensions: readonly string[];
|
||||
skipDirNames?: ReadonlySet<string>;
|
||||
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,
|
||||
options: Pick<RepoFileScanOptions, "skipDirNames" | "skipHiddenDirectories">,
|
||||
): boolean {
|
||||
if (options.skipHiddenDirectories && name.startsWith(".")) {
|
||||
return true;
|
||||
}
|
||||
return (options.skipDirNames ?? DEFAULT_REPO_SCAN_SKIP_DIR_NAMES).has(name);
|
||||
}
|
||||
|
||||
function hasAllowedExtension(fileName: string, extensions: readonly string[]): boolean {
|
||||
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,
|
||||
): Promise<Array<string>> {
|
||||
const files: Array<string> = [];
|
||||
const pending: Array<PendingDir> = [];
|
||||
|
||||
for (const root of options.roots) {
|
||||
const absolutePath = path.join(repoRoot, root);
|
||||
try {
|
||||
const stats = await fs.stat(absolutePath);
|
||||
if (stats.isDirectory()) {
|
||||
pending.push({ absolutePath });
|
||||
}
|
||||
} catch {
|
||||
// Skip missing roots. Useful when the bundled plugin tree is absent.
|
||||
}
|
||||
}
|
||||
|
||||
while (pending.length > 0) {
|
||||
const current = pending.pop();
|
||||
if (!current) {
|
||||
continue;
|
||||
}
|
||||
const entries = await fs.readdir(current.absolutePath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
if (!shouldSkipDirectory(entry.name, options)) {
|
||||
pending.push({ absolutePath: path.join(current.absolutePath, entry.name) });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!entry.isFile() || !hasAllowedExtension(entry.name, options.extensions)) {
|
||||
continue;
|
||||
}
|
||||
const filePath = path.join(current.absolutePath, entry.name);
|
||||
const relativePath = path.relative(repoRoot, filePath);
|
||||
if (options.shouldIncludeFile && !options.shouldIncludeFile(relativePath)) {
|
||||
continue;
|
||||
}
|
||||
files.push(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
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)),
|
||||
);
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
|
||||
export type SecretFiles = {
|
||||
type SecretFiles = {
|
||||
passwordFile?: string;
|
||||
tokenFile?: string;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createEditorSubmitHandler } from "./tui-submit.js";
|
||||
|
||||
type MockFn = ReturnType<typeof vi.fn>;
|
||||
|
||||
export type SubmitHarness = {
|
||||
type SubmitHarness = {
|
||||
editor: {
|
||||
setText: MockFn;
|
||||
addToHistory: MockFn;
|
||||
|
||||
Reference in New Issue
Block a user