(absDir: string)
| 437 | }; |
| 438 | |
| 439 | function walk(absDir: string): void { |
| 440 | let realDir: string; |
| 441 | try { |
| 442 | realDir = fs.realpathSync(absDir); |
| 443 | } catch { |
| 444 | return; |
| 445 | } |
| 446 | if (visited.has(realDir)) return; // symlink-cycle guard |
| 447 | visited.add(realDir); |
| 448 | |
| 449 | let entries: fs.Dirent[]; |
| 450 | try { |
| 451 | entries = fs.readdirSync(absDir, { withFileTypes: true }); |
| 452 | } catch { |
| 453 | return; |
| 454 | } |
| 455 | for (const entry of entries) { |
| 456 | if (entry.name === '.git' || isCodeGraphDataDir(entry.name)) continue; |
| 457 | const abs = path.join(absDir, entry.name); |
| 458 | const rel = normalizePath(path.relative(rootDir, abs)); |
| 459 | if (!rel || rel.startsWith('..')) continue; |
| 460 | if (entry.isSymbolicLink()) { |
| 461 | try { |
| 462 | const st = fs.statSync(fs.realpathSync(abs)); |
| 463 | consider(abs, rel, st.isDirectory()); |
| 464 | } catch { |
| 465 | // broken symlink — skip |
| 466 | } |
| 467 | continue; |
| 468 | } |
| 469 | consider(abs, rel, entry.isDirectory()); |
| 470 | } |
| 471 | } |
| 472 | |
| 473 | for (const root of roots) { |
| 474 | walk(root === '' ? rootDir : path.join(rootDir, root)); |
no test coverage detected