2 const fs = require('fs');
3 const path = require('path');
4 const fastGlob = require('fast-glob');
5 const gitIgnore = require('ignore');
6 const pify = require('pify');
7 const slash = require('slash');
9 const DEFAULT_IGNORE = [
11 '**/bower_components/**',
17 const readFileP = pify(fs.readFile);
19 const mapGitIgnorePatternTo = base => ignore => {
20 if (ignore.startsWith('!')) {
21 return '!' + path.posix.join(base, ignore.substr(1));
24 return path.posix.join(base, ignore);
27 const parseGitIgnore = (content, opts) => {
28 const base = slash(path.relative(opts.cwd, path.dirname(opts.fileName)));
33 .filter(l => l.charAt(0) !== '#')
34 .map(mapGitIgnorePatternTo(base));
37 const reduceIgnore = files => {
38 return files.reduce((ignores, file) => {
39 ignores.add(parseGitIgnore(file.content, {
41 fileName: file.filePath
47 const getIsIgnoredPredecate = (ignores, cwd) => {
48 return p => ignores.ignores(slash(path.relative(cwd, p)));
51 const getFile = (file, cwd) => {
52 const filePath = path.join(cwd, file);
53 return readFileP(filePath, 'utf8')
61 const getFileSync = (file, cwd) => {
62 const filePath = path.join(cwd, file);
63 const content = fs.readFileSync(filePath, 'utf8');
72 const normalizeOpts = opts => {
74 const ignore = opts.ignore || [];
75 const cwd = opts.cwd || process.cwd();
79 module.exports = o => {
80 const opts = normalizeOpts(o);
82 return fastGlob('**/.gitignore', {ignore: DEFAULT_IGNORE.concat(opts.ignore), cwd: opts.cwd})
83 .then(paths => Promise.all(paths.map(file => getFile(file, opts.cwd))))
84 .then(files => reduceIgnore(files))
85 .then(ignores => getIsIgnoredPredecate(ignores, opts.cwd));
88 module.exports.sync = o => {
89 const opts = normalizeOpts(o);
91 const paths = fastGlob.sync('**/.gitignore', {ignore: DEFAULT_IGNORE.concat(opts.ignore), cwd: opts.cwd});
92 const files = paths.map(file => getFileSync(file, opts.cwd));
93 const ignores = reduceIgnore(files);
94 return getIsIgnoredPredecate(ignores, opts.cwd);