Skip to content

Commit 147e18d

Browse files
committed
fix(search): follow symlinks when walking docset directories
local_folder docsets are stored as symlinked directories. readdir() withFileTypes returns Dirent objects where isDirectory()/isFile() return false for symlinks — only isSymbolicLink() is true. walkFiles() was therefore skipping all symlinked content, causing files_count: 0. Fix: when entry.isSymbolicLink(), use stat() (which follows the link) to determine whether the target is a directory or file, then recurse/yield accordingly. Broken symlinks are silently skipped.
1 parent bd8af12 commit 147e18d

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

packages/core/src/search/searcher.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,17 +276,29 @@ async function* walkFiles(dir: string): AsyncGenerator<string> {
276276
for (const entry of entries) {
277277
const absPath = join(dir, entry.name);
278278

279-
if (entry.isDirectory()) {
279+
// For symlinks, stat() follows the link to get the real type.
280+
// entry.isDirectory() / entry.isFile() return false for symlinks.
281+
let isDir = entry.isDirectory();
282+
let isFile = entry.isFile();
283+
if (entry.isSymbolicLink()) {
284+
try {
285+
const s = await stat(absPath);
286+
isDir = s.isDirectory();
287+
isFile = s.isFile();
288+
} catch {
289+
continue; // broken symlink — skip
290+
}
291+
}
292+
293+
if (isDir) {
280294
if (!IGNORED_NAMES.has(entry.name)) {
281295
yield* walkFiles(absPath);
282296
}
283-
} else if (entry.isFile()) {
297+
} else if (isFile) {
284298
if (!IGNORED_FILES.has(entry.name)) {
285299
yield absPath;
286300
}
287301
}
288-
// symlinks: follow only if they point to files (readdir withFileTypes
289-
// resolves symlinks on most platforms)
290302
}
291303
}
292304

0 commit comments

Comments
 (0)