Skip to content

Commit

Permalink
Refactor gitignore handling
Browse files Browse the repository at this point in the history
  • Loading branch information
schnittstabil committed May 3, 2017
1 parent 39a62f3 commit a1ae203
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 71 deletions.
41 changes: 41 additions & 0 deletions gitignore.js
@@ -0,0 +1,41 @@
'use strict';
const fs = require('fs');
const path = require('path');
const gitIgnore = require('ignore');
const globby = require('globby');
const slash = require('slash');

const mapGitIgnorePatternTo = base => ignore => {
if (ignore.startsWith('!')) {
return '!' + path.posix.join(base, ignore.substr(1));
}

return path.posix.join(base, ignore);
};

const parseGitIgnore = (content, opts) => {
const base = slash(path.relative(opts.cwd, path.dirname(opts.fileName)));

return content
.split(/\r?\n/)
.filter(Boolean)
.filter(l => l.charAt(0) !== '#')
.map(mapGitIgnorePatternTo(base));
};

const getGitIgnoreFilter = opts => {
const ignore = opts.ignores || [];
const cwd = opts.cwd || process.cwd();

const i = globby.sync('**/.gitignore', {ignore, cwd})
.reduce((ignores, file) => {
const fileName = path.join(cwd, file);
const content = fs.readFileSync(fileName, 'utf8');
ignores.add(parseGitIgnore(content, {cwd, fileName}));
return ignores;
}, gitIgnore());

return p => !i.ignores(slash(path.relative(cwd, p)));
};

exports.getGitIgnoreFilter = getGitIgnoreFilter;
39 changes: 2 additions & 37 deletions options-manager.js
@@ -1,16 +1,14 @@
'use strict';
const fs = require('fs');
const os = require('os');
const path = require('path');
const arrify = require('arrify');
const deepAssign = require('deep-assign');
const globby = require('globby');
const gitIgnore = require('ignore');
const multimatch = require('multimatch');
const pathExists = require('path-exists');
const pkgConf = require('pkg-conf');
const resolveFrom = require('resolve-from');
const slash = require('slash');

const getGitIgnoreFilter = require('./gitignore').getGitIgnoreFilter;

const DEFAULT_IGNORE = [
'**/node_modules/**',
Expand Down Expand Up @@ -233,39 +231,6 @@ const getIgnores = opts => {
return opts;
};

const mapGitIgnorePatternTo = base => ignore => {
if (ignore.startsWith('!')) {
return '!' + path.posix.join(base, ignore.substr(1));
}

return path.posix.join(base, ignore);
};

const parseGitIgnore = (content, opts) => {
const base = slash(path.relative(opts.cwd, path.dirname(opts.fileName)));

return content
.split(/\r?\n/)
.filter(Boolean)
.filter(l => l.charAt(0) !== '#')
.map(mapGitIgnorePatternTo(base));
};

const getGitIgnoreFilter = opts => {
const ignore = opts.ignores || [];
const cwd = opts.cwd || process.cwd();

const i = globby.sync('**/.gitignore', {ignore, cwd})
.reduce((ignores, file) => {
const fileName = path.join(cwd, file);
const content = fs.readFileSync(fileName, 'utf8');
ignores.add(parseGitIgnore(content, {cwd, fileName}));
return ignores;
}, gitIgnore());

return p => !i.ignores(slash(path.relative(cwd, p)));
};

const preprocess = opts => {
opts = mergeWithPkgConf(opts);
opts = normalizeOpts(opts);
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -30,6 +30,7 @@
"coveralls": "nyc report --reporter=text-lcov | coveralls"
},
"files": [
"gitignore-filter.js",
"index.js",
"cli.js",
"options-manager.js",
Expand Down
43 changes: 43 additions & 0 deletions test/gitignore.js
@@ -0,0 +1,43 @@
import path from 'path';
import test from 'ava';
import proxyquire from 'proxyquire';

process.chdir(__dirname);

const manager = proxyquire('../options-manager', {
'resolve-from': (cwd, path) => `cwd/${path}`
});

test('gitignore', t => {
const cwd = path.join(__dirname, 'fixtures/gitignore/test');
const filter = manager.getGitIgnoreFilter({cwd});
const actual = ['foo.js', 'bar.js'].filter(filter);
const expected = ['bar.js'];
t.deepEqual(actual, expected);
});

test('ignore ignored .gitignore', t => {
const opts = {
cwd: path.join(__dirname, 'fixtures/gitignore'),
ignores: ['**/test/**']
};

const filter = manager.getGitIgnoreFilter(opts);
const actual = ['foo.js'].filter(filter);
const expected = ['foo.js'];
t.deepEqual(actual, expected);
});

test.serial('patterns should be translated according to process.cwd()', t => {
const previous = process.cwd();
const cwd = path.join(__dirname, 'fixtures/gitignore');
process.chdir(cwd);
try {
const filter = manager.getGitIgnoreFilter({});
const actual = ['bar.js', 'test/foo.js', 'test/bar.js'].filter(filter);
const expected = ['bar.js', 'test/bar.js'];
t.deepEqual(actual, expected);
} finally {
process.chdir(previous);
}
});
34 changes: 0 additions & 34 deletions test/options-manager.js
Expand Up @@ -172,40 +172,6 @@ test('groupConfigs', t => {
}));
});

test('gitignore', t => {
const cwd = path.join(__dirname, 'fixtures/gitignore/test');
const filter = manager.getGitIgnoreFilter({cwd});
const actual = ['foo.js', 'bar.js'].filter(filter);
const expected = ['bar.js'];
t.deepEqual(actual, expected);
});

test('ignore ignored .gitignore', t => {
const opts = {
cwd: path.join(__dirname, 'fixtures/gitignore'),
ignores: ['**/test/**']
};

const filter = manager.getGitIgnoreFilter(opts);
const actual = ['foo.js'].filter(filter);
const expected = ['foo.js'];
t.deepEqual(actual, expected);
});

test.serial('patterns should be translated according to process.cwd()', t => {
const previous = process.cwd();
const cwd = path.join(__dirname, 'fixtures/gitignore');
process.chdir(cwd);
try {
const filter = manager.getGitIgnoreFilter({});
const actual = ['bar.js', 'test/foo.js', 'test/bar.js'].filter(filter);
const expected = ['bar.js', 'test/bar.js'];
t.deepEqual(actual, expected);
} finally {
process.chdir(previous);
}
});

test('mergeWithPkgConf: use child if closest', t => {
const cwd = path.resolve('fixtures', 'nested', 'child');
const result = manager.mergeWithPkgConf({cwd});
Expand Down

0 comments on commit a1ae203

Please sign in to comment.