Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require Node.js 12.20 and move to ESM #181

Merged
merged 4 commits into from Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Expand Up @@ -10,16 +10,16 @@ jobs:
fail-fast: false
matrix:
node-version:
- 16
- 14
- 12
- 10
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
69 changes: 37 additions & 32 deletions bench.js
@@ -1,95 +1,100 @@
'use strict';
/* global after, before, bench, suite */
const fs = require('fs');
const rimraf = require('rimraf');
const globbyMainBranch = require('globby');
const gs = require('glob-stream');
const fastGlob = require('fast-glob');
const globby = require('.');
import fs from 'node:fs';
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import rimraf from 'rimraf';
import globbyMainBranch from 'globby';
import gs from 'glob-stream';
import fastGlob from 'fast-glob';
import {globby, globbySync} from './index.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const BENCH_DIR = 'bench';

const runners = [{
name: 'globby async (working directory)',
run: async (patterns, callback) => {
await globby(patterns);
callback();
}
},
}, {
name: 'globby async (upstream/main)',
run: async (patterns, callback) => {
await globbyMainBranch(patterns);
callback();
}
},
}, {
name: 'globby sync (working directory)',
run: patterns => {
globby.sync(patterns);
}
globbySync(patterns);
},
}, {
name: 'globby sync (upstream/main)',
run: patterns => {
globbyMainBranch.sync(patterns);
}
},
}, {
name: 'glob-stream',
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);
}
},
}];
const benchs = [{
name: 'negative globs (some files inside dir)',
patterns: [
'a/*',
'!a/c*'
]
'!a/c*',
],
}, {
name: 'negative globs (whole dir)',
patterns: [
'a/*',
'!a/**'
]
'!a/**',
],
}, {
name: 'multiple positive globs',
patterns: [
'a/*',
'b/*'
]
'b/*',
],
}];

before(() => {
process.chdir(__dirname);
rimraf.sync(BENCH_DIR);
fs.mkdirSync(BENCH_DIR);
process.chdir(BENCH_DIR);
['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, '');
}
});
const directories = ['a', 'b']
.map(directory => `${directory}/`);

for (const directory of directories) {
fs.mkdirSync(directory);
for (let i = 0; i < 500; i++) {
fs.writeFileSync(directory + (i < 100 ? 'c' : 'd') + i, '');
}
}
});

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

benchs.forEach(benchmark => {
for (const benchmark of benchs) {
suite(benchmark.name, () => {
runners.forEach(runner => bench(runner.name, runner.run.bind(null, benchmark.patterns)));
for (const runner of runners) {
bench(runner.name, runner.run.bind(null, benchmark.patterns));
}
});
});
}
44 changes: 20 additions & 24 deletions gitignore.js
@@ -1,16 +1,15 @@
'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');
import {promisify} from 'node:util';
import fs from 'node:fs';
import path from 'node:path';
import fastGlob from 'fast-glob';
import gitIgnore from 'ignore';
import slash from 'slash';

const DEFAULT_IGNORE = [
'**/node_modules/**',
'**/flow-typed/**',
'**/coverage/**',
'**/.git'
'**/.git',
];

const readFileP = promisify(fs.readFile);
Expand Down Expand Up @@ -38,7 +37,7 @@ const reduceIgnore = files => {
for (const file of files) {
ignores.add(parseGitIgnore(file.content, {
cwd: file.cwd,
fileName: file.filePath
fileName: file.filePath,
}));
}

Expand All @@ -58,9 +57,7 @@ const ensureAbsolutePathForCwd = (cwd, p) => {
return path.join(cwd, p);
};

const getIsIgnoredPredecate = (ignores, cwd) => {
return p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p.path || p))));
};
const getIsIgnoredPredicate = (ignores, cwd) => p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p.path || p))));

const getFile = async (file, cwd) => {
const filePath = path.join(cwd, file);
Expand All @@ -69,7 +66,7 @@ const getFile = async (file, cwd) => {
return {
cwd,
filePath,
content
content,
};
};

Expand All @@ -80,41 +77,40 @@ const getFileSync = (file, cwd) => {
return {
cwd,
filePath,
content
content,
};
};

const normalizeOptions = ({
ignore = [],
cwd = slash(process.cwd())
} = {}) => {
return {ignore, cwd};
};
cwd = slash(process.cwd()),
} = {}) => ({ignore, cwd});

module.exports = async options => {
export const isGitIgnored = async options => {
options = normalizeOptions(options);

const paths = await fastGlob('**/.gitignore', {
ignore: DEFAULT_IGNORE.concat(options.ignore),
cwd: options.cwd
cwd: options.cwd,
});

const files = await Promise.all(paths.map(file => getFile(file, options.cwd)));
const ignores = reduceIgnore(files);

return getIsIgnoredPredecate(ignores, options.cwd);
return getIsIgnoredPredicate(ignores, options.cwd);
};

module.exports.sync = options => {
export const isGitIgnoredSync = options => {
options = normalizeOptions(options);

const paths = fastGlob.sync('**/.gitignore', {
ignore: DEFAULT_IGNORE.concat(options.ignore),
cwd: options.cwd
cwd: options.cwd,
});

const files = paths.map(file => getFileSync(file, options.cwd));
const ignores = reduceIgnore(files);

return getIsIgnoredPredecate(ignores, options.cwd);
return getIsIgnoredPredicate(ignores, options.cwd);
};

35 changes: 19 additions & 16 deletions gitignore.test.js
@@ -1,31 +1,34 @@
const path = require('path');
const test = require('ava');
const slash = require('slash');
const gitignore = require('./gitignore');
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import test from 'ava';
import slash from 'slash';
import {isGitIgnored, isGitIgnoredSync} from './gitignore.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

test('gitignore', async t => {
const cwd = path.join(__dirname, 'fixtures/gitignore');
const isIgnored = await gitignore({cwd});
const isIgnored = await isGitIgnored({cwd});
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
const expected = ['bar.js'];
t.deepEqual(actual, expected);
});

test('gitignore - mixed path styles', async t => {
const cwd = path.join(__dirname, 'fixtures/gitignore');
const isIgnored = await gitignore({cwd});
const isIgnored = await isGitIgnored({cwd});
t.true(isIgnored(slash(path.resolve(cwd, 'foo.js'))));
});

test('gitignore - os paths', async t => {
const cwd = path.join(__dirname, 'fixtures/gitignore');
const isIgnored = await gitignore({cwd});
const isIgnored = await isGitIgnored({cwd});
t.true(isIgnored(path.resolve(cwd, 'foo.js')));
});

test('gitignore - sync', t => {
const cwd = path.join(__dirname, 'fixtures/gitignore');
const isIgnored = gitignore.sync({cwd});
const isIgnored = isGitIgnoredSync({cwd});
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
const expected = ['bar.js'];
t.deepEqual(actual, expected);
Expand All @@ -35,7 +38,7 @@ test('ignore ignored .gitignore', async t => {
const cwd = path.join(__dirname, 'fixtures/gitignore');
const ignore = ['**/.gitignore'];

const isIgnored = await gitignore({cwd, ignore});
const isIgnored = await isGitIgnored({cwd, ignore});
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
const expected = ['foo.js', 'bar.js'];
t.deepEqual(actual, expected);
Expand All @@ -45,37 +48,37 @@ test('ignore ignored .gitignore - sync', t => {
const cwd = path.join(__dirname, 'fixtures/gitignore');
const ignore = ['**/.gitignore'];

const isIgnored = gitignore.sync({cwd, ignore});
const isIgnored = isGitIgnoredSync({cwd, ignore});
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
const expected = ['foo.js', 'bar.js'];
t.deepEqual(actual, expected);
});

test('negative gitignore', async t => {
const cwd = path.join(__dirname, 'fixtures/negative');
const isIgnored = await gitignore({cwd});
const isIgnored = await isGitIgnored({cwd});
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
const expected = ['foo.js'];
t.deepEqual(actual, expected);
});

test('negative gitignore - sync', t => {
const cwd = path.join(__dirname, 'fixtures/negative');
const isIgnored = gitignore.sync({cwd});
const isIgnored = isGitIgnoredSync({cwd});
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
const expected = ['foo.js'];
t.deepEqual(actual, expected);
});

test('multiple negation', async t => {
const cwd = path.join(__dirname, 'fixtures/multiple-negation');
const isIgnored = await gitignore({cwd});
const isIgnored = await isGitIgnored({cwd});

const actual = [
'!!!unicorn.js',
'!!unicorn.js',
'!unicorn.js',
'unicorn.js'
'unicorn.js',
].filter(file => !isIgnored(file));

const expected = ['!!unicorn.js', '!unicorn.js'];
Expand All @@ -84,13 +87,13 @@ test('multiple negation', async t => {

test('multiple negation - sync', t => {
const cwd = path.join(__dirname, 'fixtures/multiple-negation');
const isIgnored = gitignore.sync({cwd});
const isIgnored = isGitIgnoredSync({cwd});

const actual = [
'!!!unicorn.js',
'!!unicorn.js',
'!unicorn.js',
'unicorn.js'
'unicorn.js',
].filter(file => !isIgnored(file));

const expected = ['!!unicorn.js', '!unicorn.js'];
Expand Down