Limit recursion when looking for .gitignore files (#8103)

Co-authored-by: cornmander <shikhman@google.com>
This commit is contained in:
Billy Biggs
2025-09-09 14:45:37 -07:00
committed by GitHub
parent da58b93026
commit de5a31c3b6
+35 -24
View File
@@ -18,6 +18,7 @@ export class GitIgnoreParser implements GitIgnoreFilter {
private projectRoot: string; private projectRoot: string;
private ig: Ignore = ignore(); private ig: Ignore = ignore();
private patterns: string[] = []; private patterns: string[] = [];
private readonly maxScannedDirs = 200;
constructor(projectRoot: string) { constructor(projectRoot: string) {
this.projectRoot = path.resolve(projectRoot); this.projectRoot = path.resolve(projectRoot);
@@ -33,34 +34,44 @@ export class GitIgnoreParser implements GitIgnoreFilter {
this.findAndLoadGitignoreFiles(this.projectRoot); this.findAndLoadGitignoreFiles(this.projectRoot);
} }
private findAndLoadGitignoreFiles(dir: string): void { private findAndLoadGitignoreFiles(startDir: string): void {
const relativeDir = path.relative(this.projectRoot, dir); const queue: string[] = [startDir];
let scannedDirs = 0;
let queueHead = 0;
// For sub-directories, check if they are ignored before proceeding. while (queueHead < queue.length && scannedDirs < this.maxScannedDirs) {
// The root directory (relativeDir === '') should not be checked. const dir = queue[queueHead];
if (relativeDir && this.isIgnored(relativeDir)) { queueHead++;
return; scannedDirs++;
}
// Load patterns from .gitignore in the current directory const relativeDir = path.relative(this.projectRoot, dir);
const gitignorePath = path.join(dir, '.gitignore');
if (fs.existsSync(gitignorePath)) {
this.loadPatterns(path.relative(this.projectRoot, gitignorePath));
}
// Recurse into subdirectories // For sub-directories, check if they are ignored before proceeding.
try { // The root directory (relativeDir === '') should not be checked.
const entries = fs.readdirSync(dir, { withFileTypes: true }); if (relativeDir && this.isIgnored(relativeDir)) {
for (const entry of entries) { continue;
if (entry.name === '.git') { }
continue;
} // Load patterns from .gitignore in the current directory
if (entry.isDirectory()) { const gitignorePath = path.join(dir, '.gitignore');
this.findAndLoadGitignoreFiles(path.join(dir, entry.name)); if (fs.existsSync(gitignorePath)) {
} this.loadPatterns(path.relative(this.projectRoot, gitignorePath));
}
// Recurse into subdirectories
try {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.name === '.git') {
continue;
}
if (entry.isDirectory()) {
queue.push(path.join(dir, entry.name));
}
}
} catch (_error) {
// ignore readdir errors
} }
} catch (_error) {
// ignore readdir errors
} }
} }