mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-06 08:24:46 +00:00
fix(server): keep the Git-ignore ancestor walk for symlinked entries
A symlink resolves to a path whose ancestors were never checked during traversal, so a link into an ignored directory was discovered. Named children keep the single-entry check.
This commit is contained in:
@@ -170,6 +170,26 @@ describe("searchDirectoryEntries", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it.skipIf(isWindows)(
|
||||
"prunes a symlink whose target is inside a Git-ignored directory",
|
||||
async () => {
|
||||
initGitRepo(searchRoot, "generated/\n");
|
||||
mkdirSync(path.join(searchRoot, "generated", "output"), { recursive: true });
|
||||
symlinkSync(path.join(searchRoot, "generated", "output"), path.join(searchRoot, "linked"));
|
||||
|
||||
await expect(
|
||||
searchDirectoryEntries({
|
||||
root: searchRoot,
|
||||
query: "linked",
|
||||
pathFormat: "relative",
|
||||
includeFiles: false,
|
||||
includeDirectories: true,
|
||||
respectGitIgnore: true,
|
||||
}),
|
||||
).resolves.toEqual([]);
|
||||
},
|
||||
);
|
||||
|
||||
it("configures raw blank queries independently from explicit root aliases", async () => {
|
||||
const rootEntries = [
|
||||
{ path: "projects", kind: "directory" as const },
|
||||
|
||||
@@ -337,10 +337,7 @@ function staysInsideRoot(entry: ChildEntry, root: string): boolean {
|
||||
}
|
||||
|
||||
function shouldDiscover(entry: ChildEntry, input: SearchInput): boolean {
|
||||
// Traversal only descends through entries that already passed this check, so every ancestor
|
||||
// is known discoverable and only the entry itself can be newly ignored. Walking the ancestor
|
||||
// chain here would re-derive that answer once per level, for every entry scanned.
|
||||
if (input.gitIgnoredPaths.has(entry.resolvedPath)) return false;
|
||||
if (isNewlyGitIgnored(entry, input)) return false;
|
||||
if (entry.kind === "file") {
|
||||
return input.includeFiles && !entry.name.startsWith(".");
|
||||
}
|
||||
@@ -349,6 +346,14 @@ function shouldDiscover(entry: ChildEntry, input: SearchInput): boolean {
|
||||
return input.hiddenDirectoryNames.has(entry.name);
|
||||
}
|
||||
|
||||
// Traversal only descends through entries that already passed this check, so every ancestor of
|
||||
// a named child is known discoverable and only the entry itself can be newly ignored. A symlink
|
||||
// resolves to a path with different ancestors, so it still needs the full walk.
|
||||
function isNewlyGitIgnored(entry: ChildEntry, input: SearchInput): boolean {
|
||||
if (entry.viaSymlink) return isGitIgnoredPath(entry.resolvedPath, input);
|
||||
return input.gitIgnoredPaths.has(entry.resolvedPath);
|
||||
}
|
||||
|
||||
function isGitIgnoredPath(absolutePath: string, input: SearchInput): boolean {
|
||||
let candidate = absolutePath;
|
||||
while (candidate !== input.root && isPathInsideRoot(input.root, candidate)) {
|
||||
|
||||
Reference in New Issue
Block a user