|
|
'use strict'; const {promisify} = require('util'); const fs = require('fs'); const path = require('path'); const fastGlob = require('fast-glob'); const gitIgnore = require('ignore'); const slash = require('slash');
const DEFAULT_IGNORE = [ '**/node_modules/**', '**/flow-typed/**', '**/coverage/**', '**/.git' ];
const readFileP = promisify(fs.readFile);
const mapGitIgnorePatternTo = base => ignore => { if (ignore.startsWith('!')) { return '!' + path.posix.join(base, ignore.slice(1)); }
return path.posix.join(base, ignore); };
const parseGitIgnore = (content, options) => { const base = slash(path.relative(options.cwd, path.dirname(options.fileName)));
return content .split(/\r?\n/) .filter(Boolean) .filter(line => !line.startsWith('#')) .map(mapGitIgnorePatternTo(base)); };
const reduceIgnore = files => { const ignores = gitIgnore(); for (const file of files) { ignores.add(parseGitIgnore(file.content, { cwd: file.cwd, fileName: file.filePath })); }
return ignores; };
const ensureAbsolutePathForCwd = (cwd, p) => { cwd = slash(cwd); if (path.isAbsolute(p)) { if (slash(p).startsWith(cwd)) { return p; }
throw new Error(`Path ${p} is not in cwd ${cwd}`); }
return path.join(cwd, p); };
const getIsIgnoredPredecate = (ignores, cwd) => { return p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p.path || p)))); };
const getFile = async (file, cwd) => { const filePath = path.join(cwd, file); const content = await readFileP(filePath, 'utf8');
return { cwd, filePath, content }; };
const getFileSync = (file, cwd) => { const filePath = path.join(cwd, file); const content = fs.readFileSync(filePath, 'utf8');
return { cwd, filePath, content }; };
const normalizeOptions = ({ ignore = [], cwd = slash(process.cwd()) } = {}) => { return {ignore, cwd}; };
module.exports = async options => { options = normalizeOptions(options);
const paths = await fastGlob('**/.gitignore', { ignore: DEFAULT_IGNORE.concat(options.ignore), cwd: options.cwd });
const files = await Promise.all(paths.map(file => getFile(file, options.cwd))); const ignores = reduceIgnore(files);
return getIsIgnoredPredecate(ignores, options.cwd); };
module.exports.sync = options => { options = normalizeOptions(options);
const paths = fastGlob.sync('**/.gitignore', { ignore: DEFAULT_IGNORE.concat(options.ignore), cwd: options.cwd });
const files = paths.map(file => getFileSync(file, options.cwd)); const ignores = reduceIgnore(files);
return getIsIgnoredPredecate(ignores, options.cwd); };
|