refactor(server): name containment matcher options

This commit is contained in:
paseo-bot[bot]
2026-11-04 04:41:09 +00:00
parent c65d0656c9
commit 29d9872dc6
5 changed files with 35 additions and 18 deletions
@@ -53,7 +53,7 @@ export function createObserverPaths(platform: NodeJS.Platform): ObserverPaths {
isInside,
collapse,
createIgnoreMatcher(roots) {
return createPathContainmentMatcher(roots, platform === "win32");
return createPathContainmentMatcher({ roots, compareAsWindows: platform === "win32" });
},
normalizeIgnoredRoots(root, paths) {
const inside = paths
@@ -81,7 +81,10 @@ export class GitObservationPaths {
excluded.push(this.windows ? subtree.toLowerCase() : subtree);
}
}
const isExcluded = createPathContainmentMatcher(excluded, this.windows);
const isExcluded = createPathContainmentMatcher({
roots: excluded,
compareAsWindows: this.windows,
});
return (candidate) => {
const normalized = this.normalizeEventPath(candidate);
const comparable = this.windows ? normalized.toLowerCase() : normalized;
@@ -2045,10 +2045,10 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService {
}
private pruneKnownDirectories(target: WorkingTreeWatchTarget): void {
const isIgnored = createPathContainmentMatcher(
target.ignoredDirectories,
looksLikeDefiniteWindowsPath(target.watchPath),
);
const isIgnored = createPathContainmentMatcher({
roots: target.ignoredDirectories,
compareAsWindows: looksLikeDefiniteWindowsPath(target.watchPath),
});
for (const directory of target.knownDirectories) {
if (isIgnored(directory)) {
target.knownDirectories.delete(directory);
+17 -8
View File
@@ -101,7 +101,10 @@ describe("path equivalence", () => {
describe("indexed path containment", () => {
test("preserves POSIX case and component boundaries", () => {
const matches = createPathContainmentMatcher(["/repo/Build/", "/repo/cache"], false);
const matches = createPathContainmentMatcher({
roots: ["/repo/Build/", "/repo/cache"],
compareAsWindows: false,
});
expect(matches("/repo/Build/nested/file")).toBe(true);
expect(matches("/repo/cache")).toBe(true);
expect(matches("/repo/Build-sibling/file")).toBe(false);
@@ -110,10 +113,10 @@ describe("indexed path containment", () => {
});
test("normalizes Windows case, separators and extended namespaces", () => {
const matches = createPathContainmentMatcher(
["C:/Repo/Build", String.raw`\\server\share\cache`],
true,
);
const matches = createPathContainmentMatcher({
roots: ["C:/Repo/Build", String.raw`\\server\share\cache`],
compareAsWindows: true,
});
expect(matches(String.raw`\\?\C:\REPO\build\file`)).toBe(true);
expect(matches(String.raw`\\?\UNC\SERVER\SHARE\Cache\file`)).toBe(true);
expect(matches("C:/Repo/Build-Sibling/file")).toBe(false);
@@ -121,8 +124,14 @@ describe("indexed path containment", () => {
});
test("handles filesystem roots and empty sets", () => {
expect(createPathContainmentMatcher(["/"], false)("/repo/file")).toBe(true);
expect(createPathContainmentMatcher(["C:/"], true)("c:/repo/file")).toBe(true);
expect(createPathContainmentMatcher([], false)("/repo/file")).toBe(false);
expect(
createPathContainmentMatcher({ roots: ["/"], compareAsWindows: false })("/repo/file"),
).toBe(true);
expect(
createPathContainmentMatcher({ roots: ["C:/"], compareAsWindows: true })("c:/repo/file"),
).toBe(true);
expect(createPathContainmentMatcher({ roots: [], compareAsWindows: false })("/repo/file")).toBe(
false,
);
});
});
+9 -4
View File
@@ -72,11 +72,16 @@ export function stopPathContainmentMetrics(): number {
return checks;
}
interface PathContainmentOptions {
roots: Iterable<string>;
compareAsWindows: boolean;
}
/** Compile lexical subtree membership without scanning unrelated roots per candidate. */
export function createPathContainmentMatcher(
roots: Iterable<string>,
compareAsWindows: boolean,
): (candidate: string) => boolean {
export function createPathContainmentMatcher({
roots,
compareAsWindows,
}: PathContainmentOptions): (candidate: string) => boolean {
const pathApi = compareAsWindows ? nodePath.win32 : nodePath.posix;
const indexed = new Set(
Array.from(roots, (root) => normalizePathForComparison(root, compareAsWindows)),