import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { minimatch } from 'minimatch';
const cache = new Map();
function normalizeRelPath(path) {
    return path.replace(/\\/g, '/').replace(/^\/+/, '');
}
function matchesDirPattern(pattern, relPath, hasSlash) {
    if (!hasSlash) {
        return relPath.split('/').includes(pattern);
    }
    return relPath === pattern || relPath.startsWith(`${pattern}/`);
}
function matchesPattern(pattern, relPath, name, isDir) {
    if (pattern.dirOnly) {
        return matchesDirPattern(pattern.pattern, relPath, pattern.hasSlash);
    }
    if (!pattern.hasSlash) {
        return minimatch(name, pattern.pattern, { dot: true, nocase: process.platform === 'win32' });
    }
    return minimatch(relPath, pattern.pattern, { dot: true, nocase: process.platform === 'win32' });
}
export async function createGitignoreFilter(rootDir) {
    const gitignorePath = join(rootDir, '.gitignore');
    let mtime = 0;
    try {
        const { stat } = await import('node:fs/promises');
        mtime = (await stat(gitignorePath)).mtimeMs;
    }
    catch {
        // no .gitignore
    }
    const cached = cache.get(rootDir);
    if (cached && cached.mtime === mtime)
        return cached.filter;
    let patterns = [];
    try {
        const content = await readFile(gitignorePath, 'utf-8');
        patterns = content.split('\n')
            .map(l => l.trim())
            .filter(l => l && !l.startsWith('#'))
            .map(raw => {
            const negated = raw.startsWith('!');
            let p = negated ? raw.slice(1) : raw;
            const dirOnly = p.endsWith('/');
            if (dirOnly)
                p = p.slice(0, -1);
            p = normalizeRelPath(p);
            return { pattern: p, dirOnly, negated, hasSlash: p.includes('/') };
        });
    }
    catch {
        // no .gitignore
    }
    const filter = {
        isIgnored(relPath, name, isDir) {
            const normalizedRelPath = normalizeRelPath(relPath);
            let ignored = false;
            for (const p of patterns) {
                if (matchesPattern(p, normalizedRelPath, name, isDir))
                    ignored = !p.negated;
            }
            return ignored;
        },
    };
    cache.set(rootDir, { mtime, filter });
    return filter;
}
//# sourceMappingURL=gitignore.js.map