Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sindresorhus/globby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2b49f02ac7211b8de3eb570e0d81d8733b249a9b
Choose a base ref
...
head repository: sindresorhus/globby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 45ac58a95d9f774acd66a8996b777e52d3ed51d6
Choose a head ref
Loading
5 changes: 1 addition & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -7,9 +7,6 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[package.json]
[*.yml]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* text=auto
* text=auto eol=lf
4 changes: 4 additions & 0 deletions .github/funding.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github: sindresorhus
open_collective: sindresorhus
tidelift: npm/globby
custom: https://sindresorhus.com/donate
3 changes: 3 additions & 0 deletions .github/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Security Policy

To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
node_modules
yarn.lock
bench
*.tmp
tmp
13 changes: 0 additions & 13 deletions .jshintrc

This file was deleted.

1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
11 changes: 6 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
sudo: false
os:
- linux
- osx
- windows
language: node_js
node_js:
- 'iojs'
- '0.12'
- '0.10'
script: 'npm test && npm run bench'
- '12'
- '10'
89 changes: 56 additions & 33 deletions bench.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,95 @@
'use strict';
var fs = require('fs');
var rimraf = require('rimraf');
var globbyMaster = require('globby');
var gs = require('glob-stream');
var globby = require('./');
/* global after, before, bench, suite */
const fs = require('fs');
const rimraf = require('rimraf');
const globbyMaster = require('globby');
const gs = require('glob-stream');
const fastGlob = require('fast-glob');
const globby = require('.');

var BENCH_DIR = 'bench';
const BENCH_DIR = 'bench';

var runners = [{
const runners = [{
name: 'globby async (working directory)',
run: function (patterns, cb) {
setImmediate(globby, patterns, cb);
run: async (patterns, callback) => {
await globby(patterns);
callback();
}
}, {
name: 'globby async (upstream/master)',
run: function (patterns, cb) {
setImmediate(globbyMaster, patterns, cb);
run: async (patterns, callback) => {
await globbyMaster(patterns);
callback();
}
}, {
name: 'globby sync (working directory)',
run: function (patterns) {
run: patterns => {
globby.sync(patterns);
}
}, {
name: 'globby sync (upstream/master)',
run: function (patterns) {
run: patterns => {
globbyMaster.sync(patterns);
}
}, {
name: 'glob-stream',
run: function (patterns, cb) {
gs.create(patterns).on('data', function () {}).on('end', cb);
run: (patterns, cb) => {
gs(patterns).on('data', () => {}).on('end', cb);
}
}, {
name: 'fast-glob async',
run: async (patterns, callback) => {
await fastGlob(patterns);
callback();
}
}, {
name: 'fast-glob sync',
run: patterns => {
fastGlob.sync(patterns);
}
}];
var benchs = [{
const benchs = [{
name: 'negative globs (some files inside dir)',
patterns: ['a/*', '!a/c*']
patterns: [
'a/*',
'!a/c*'
]
}, {
name: 'negative globs (whole dir)',
patterns: ['a/*', '!a/**']
patterns: [
'a/*',
'!a/**'
]
}, {
name: 'multiple positive globs',
patterns: ['a/*', 'b/*']
patterns: [
'a/*',
'b/*'
]
}];

before(function () {
before(() => {
process.chdir(__dirname);
rimraf.sync(BENCH_DIR);
fs.mkdirSync(BENCH_DIR);
process.chdir(BENCH_DIR);
['a', 'b'].forEach(function (dir) {
var path = dir + '/';
fs.mkdirSync(path);
for (var i = 0; i < 500; i++) {
fs.writeFileSync(path + (i < 100 ? 'c' : 'd') + i, '');
}
});
['a', 'b']
.map(directory => `${directory}/`)
.forEach(directory => {
fs.mkdirSync(directory);
for (let i = 0; i < 500; i++) {
fs.writeFileSync(directory + (i < 100 ? 'c' : 'd') + i, '');
}
});
});

after(function () {
after(() => {
process.chdir(__dirname);
rimraf.sync(BENCH_DIR);
});

benchs.forEach(function (benchmark) {
suite(benchmark.name, function () {
runners.forEach(function (runner) {
bench(runner.name, runner.run.bind(null, benchmark.patterns));
});
benchs.forEach(benchmark => {
suite(benchmark.name, () => {
runners.forEach(runner => bench(runner.name, runner.run.bind(null, benchmark.patterns)));
});
});
2 changes: 2 additions & 0 deletions fixtures/gitignore/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
foo.js
!bar.js
6 changes: 6 additions & 0 deletions fixtures/gitignore/bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import test from 'ava';
import fn from '..';

test(t => {
t.is(fn('foo'), fn('foobar'));
});
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions fixtures/multiple-negation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.js
!!unicorn.js
!!!unicorn.js
2 changes: 2 additions & 0 deletions fixtures/negative/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.js
!foo.js
1 change: 1 addition & 0 deletions fixtures/negative/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('no semicolon');
117 changes: 117 additions & 0 deletions gitignore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
'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 => {
return files.reduce((ignores, file) => {
ignores.add(parseGitIgnore(file.content, {
cwd: file.cwd,
fileName: file.filePath
}));
return ignores;
}, gitIgnore());
};

const ensureAbsolutePathForCwd = (cwd, p) => {
if (path.isAbsolute(p)) {
if (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))));
};

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);
};
Loading