mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-05 16:04:43 +00:00
refactor(server): name containment matcher options
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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)),
|
||||
|
||||
Reference in New Issue
Block a user