gitignore.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. 'use strict';
  2. const fs = require('fs');
  3. const path = require('path');
  4. const glob = require('glob');
  5. const gitIgnore = require('ignore');
  6. const pify = require('pify');
  7. const slash = require('slash');
  8. const globP = pify(glob);
  9. const readFileP = pify(fs.readFile);
  10. const mapGitIgnorePatternTo = base => ignore => {
  11. if (ignore.startsWith('!')) {
  12. return '!' + path.posix.join(base, ignore.substr(1));
  13. }
  14. return path.posix.join(base, ignore);
  15. };
  16. const parseGitIgnore = (content, opts) => {
  17. const base = slash(path.relative(opts.cwd, path.dirname(opts.fileName)));
  18. return content
  19. .split(/\r?\n/)
  20. .filter(Boolean)
  21. .filter(l => l.charAt(0) !== '#')
  22. .map(mapGitIgnorePatternTo(base));
  23. };
  24. const reduceIgnore = files => {
  25. return files.reduce((ignores, file) => {
  26. ignores.add(parseGitIgnore(file.content, {
  27. cwd: file.cwd,
  28. fileName: file.filePath
  29. }));
  30. return ignores;
  31. }, gitIgnore());
  32. };
  33. const getIsIgnoredPredecate = (ignores, cwd) => {
  34. return p => ignores.ignores(slash(path.relative(cwd, p)));
  35. };
  36. const getFile = (file, cwd) => {
  37. const filePath = path.join(cwd, file);
  38. return readFileP(filePath, 'utf8')
  39. .then(content => ({
  40. content,
  41. cwd,
  42. filePath
  43. }));
  44. };
  45. const getFileSync = (file, cwd) => {
  46. const filePath = path.join(cwd, file);
  47. const content = fs.readFileSync(filePath, 'utf8');
  48. return {
  49. content,
  50. cwd,
  51. filePath
  52. };
  53. };
  54. const normalizeOpts = opts => {
  55. opts = opts || {};
  56. const ignore = opts.ignore || [];
  57. const cwd = opts.cwd || process.cwd();
  58. return {ignore, cwd};
  59. };
  60. module.exports = o => {
  61. const opts = normalizeOpts(o);
  62. return globP('**/.gitignore', {ignore: opts.ignore, cwd: opts.cwd})
  63. .then(paths => Promise.all(paths.map(file => getFile(file, opts.cwd))))
  64. .then(files => reduceIgnore(files))
  65. .then(ignores => getIsIgnoredPredecate(ignores, opts.cwd));
  66. };
  67. module.exports.sync = o => {
  68. const opts = normalizeOpts(o);
  69. const paths = glob.sync('**/.gitignore', {ignore: opts.ignore, cwd: opts.cwd});
  70. const files = paths.map(file => getFileSync(file, opts.cwd));
  71. const ignores = reduceIgnore(files);
  72. return getIsIgnoredPredecate(ignores, opts.cwd);
  73. };