| 'use strict'; | 
| const fs = require('fs'); | 
| const path = require('path'); | 
| const fastGlob = require('fast-glob'); | 
| const gitIgnore = require('ignore'); | 
| const pify = require('pify'); | 
| const slash = require('slash'); | 
|   | 
| const DEFAULT_IGNORE = [ | 
|     '**/node_modules/**', | 
|     '**/bower_components/**', | 
|     '**/flow-typed/**', | 
|     '**/coverage/**', | 
|     '**/.git' | 
| ]; | 
|   | 
| const readFileP = pify(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.charAt(0) !== '#') | 
|         .map(mapGitIgnorePatternTo(base)); | 
| }; | 
|   | 
| const reduceIgnore = files => { | 
|     return files.reduce((ignores, file) => { | 
|         ignores.add(parseGitIgnore(file.content, { | 
|             cwd: file.cwd, | 
|             fileName: file.filePath | 
|         })); | 
|         return ignores; | 
|     }, gitIgnore()); | 
| }; | 
|   | 
| const getIsIgnoredPredecate = (ignores, cwd) => { | 
|     return p => ignores.ignores(slash(path.relative(cwd, p))); | 
| }; | 
|   | 
| const getFile = (file, cwd) => { | 
|     const filePath = path.join(cwd, file); | 
|     return readFileP(filePath, 'utf8') | 
|         .then(content => ({ | 
|             content, | 
|             cwd, | 
|             filePath | 
|         })); | 
| }; | 
|   | 
| const getFileSync = (file, cwd) => { | 
|     const filePath = path.join(cwd, file); | 
|     const content = fs.readFileSync(filePath, 'utf8'); | 
|   | 
|     return { | 
|         content, | 
|         cwd, | 
|         filePath | 
|     }; | 
| }; | 
|   | 
| const normalizeOptions = (options = {}) => { | 
|     const ignore = options.ignore || []; | 
|     const cwd = options.cwd || process.cwd(); | 
|     return {ignore, cwd}; | 
| }; | 
|   | 
| module.exports = options => { | 
|     options = normalizeOptions(options); | 
|   | 
|     return fastGlob('**/.gitignore', { | 
|         ignore: DEFAULT_IGNORE.concat(options.ignore), | 
|         cwd: options.cwd | 
|     }) | 
|         .then(paths => Promise.all(paths.map(file => getFile(file, options.cwd)))) | 
|         .then(files => reduceIgnore(files)) | 
|         .then(ignores => 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); | 
| }; |