diff options
Diffstat (limited to 'packages/core/src/utils/gitIgnoreParser.ts')
| -rw-r--r-- | packages/core/src/utils/gitIgnoreParser.ts | 77 |
1 files changed, 19 insertions, 58 deletions
diff --git a/packages/core/src/utils/gitIgnoreParser.ts b/packages/core/src/utils/gitIgnoreParser.ts index 098281ca..ae1a7a01 100644 --- a/packages/core/src/utils/gitIgnoreParser.ts +++ b/packages/core/src/utils/gitIgnoreParser.ts @@ -6,18 +6,17 @@ import * as fs from 'fs/promises'; import * as path from 'path'; -import { minimatch } from 'minimatch'; +import ignore, { Ignore } from 'ignore'; import { isGitRepository } from './gitUtils.js'; export interface GitIgnoreFilter { isIgnored(filePath: string): boolean; - getIgnoredPatterns(): string[]; } export class GitIgnoreParser implements GitIgnoreFilter { - private ignorePatterns: string[] = []; private projectRoot: string; private isGitRepo: boolean = false; + private ig: Ignore = ignore(); constructor(projectRoot: string) { this.projectRoot = path.resolve(projectRoot); @@ -32,13 +31,13 @@ export class GitIgnoreParser implements GitIgnoreFilter { ]; // Always ignore .git directory regardless of .gitignore content - this.ignorePatterns = ['.git/**', '.git']; + this.addPatterns(['.git']); for (const gitIgnoreFile of gitIgnoreFiles) { try { const content = await fs.readFile(gitIgnoreFile, 'utf-8'); - const patterns = this.parseGitIgnoreContent(content); - this.ignorePatterns.push(...patterns); + const patterns = content.split('\n').map((p) => p.trim()); + this.addPatterns(patterns); } catch (_error) { // File doesn't exist or can't be read, continue silently } @@ -46,71 +45,33 @@ export class GitIgnoreParser implements GitIgnoreFilter { } } - private parseGitIgnoreContent(content: string): string[] { - return content - .split('\n') - .map((line) => line.trim()) - .filter((line) => line && !line.startsWith('#')) - .map((pattern) => { - // Handle negation patterns (!) - for now we'll skip them - if (pattern.startsWith('!')) { - return null; - } - - // Convert gitignore patterns to minimatch-compatible patterns - if (pattern.endsWith('/')) { - // Directory pattern - match directory and all contents - const dirPattern = pattern.slice(0, -1); // Remove trailing slash - return [dirPattern, dirPattern + '/**']; - } - - // If pattern doesn't contain /, it should match at any level - if (!pattern.includes('/') && !pattern.startsWith('**/')) { - return '**/' + pattern; - } - - return pattern; - }) - .filter((pattern) => pattern !== null) - .flat() as string[]; + private addPatterns(patterns: string[]) { + this.ig.add(patterns); } isIgnored(filePath: string): boolean { - // If not a git repository, nothing is ignored if (!this.isGitRepo) { return false; } - // Normalize the input path (handle ./ prefixes) - let cleanPath = filePath; - if (cleanPath.startsWith('./')) { - cleanPath = cleanPath.slice(2); - } - - // Convert to relative path from project root - const relativePath = path.relative( - this.projectRoot, - path.resolve(this.projectRoot, cleanPath), - ); + const relativePath = path.isAbsolute(filePath) + ? path.relative(this.projectRoot, filePath) + : filePath; - // Handle paths that go outside project root - if (relativePath.startsWith('..')) { + if (relativePath === '' || relativePath.startsWith('..')) { return false; } - // Normalize path separators for cross-platform compatibility - const normalizedPath = relativePath.replace(/\\/g, '/'); + let normalizedPath = relativePath.replace(/\\/g, '/'); + if (normalizedPath.startsWith('./')) { + normalizedPath = normalizedPath.substring(2); + } - return this.ignorePatterns.some((pattern) => - minimatch(normalizedPath, pattern, { - dot: true, - matchBase: false, - flipNegate: false, - }), - ); + const ignored = this.ig.ignores(normalizedPath); + return ignored; } - getIgnoredPatterns(): string[] { - return [...this.ignorePatterns]; + getGitRepoRoot(): string { + return this.projectRoot; } } |
