Skip to content

Commit

Permalink
add filter option, fixes sindresorhus#63
Browse files Browse the repository at this point in the history
  • Loading branch information
stroncium committed Mar 1, 2020
1 parent 85831f1 commit 93f6893
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 1 deletion.
16 changes: 16 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ declare namespace cpy {
@default true
*/
readonly ignoreJunk?: boolean;

/**
Function to filter copied files. Return true to include, false to exclude. Can also return a Promise that resolves to true or false.
@example
```
import cpy = require('cpy');
(async () => {
await cpy('foo', 'destination', {
filter: name => !name.includes('NOCOPY')
});
})();
```
*/
readonly filter?: (basename: string) => (boolean | Promise<boolean>);
}

interface ProgressData {
Expand Down
15 changes: 15 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const globby = require('globby');
const hasGlob = require('has-glob');
const cpFile = require('cp-file');
const junk = require('junk');
const pFilter = require('p-filter');
const CpyError = require('./cpy-error');

const defaultOptions = {
Expand Down Expand Up @@ -74,6 +75,20 @@ module.exports = (source, destination, {
throw new CpyError(`Cannot copy \`${source}\`: the file doesn't exist`);
}

if (options.filter !== undefined) {
const filteredFiles = await pFilter(files, options.filter, {concurrency: 1024});
files = filteredFiles;
}

if (files.length === 0) {
progressEmitter.emit('progress', {
totalFiles: 0,
percent: 1,
completedFiles: 0,
completedSize: 0
});
}

const fileProgressHandler = event => {
const fileStatus = copyStatus.get(event.src) || {written: 0, percent: 0};

Expand Down
6 changes: 6 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ expectType<Promise<string[]> & ProgressEmitter>(
cpy('foo.js', 'destination', {concurrency: 2})
);

expectType<Promise<string[]> & ProgressEmitter>(
cpy('foo.js', 'destination', {filter: () => true})
);
expectType<Promise<string[]> & ProgressEmitter>(
cpy('foo.js', 'destination', {filter: async () => true})
);

expectType<Promise<string[]>>(
cpy('foo.js', 'destination').on('progress', progress => {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
"has-glob": "^1.0.0",
"junk": "^3.1.0",
"nested-error-stacks": "^2.1.0",
"p-all": "^2.1.0"
"p-all": "^2.1.0",
"p-filter": "^2.1.0"
},
"devDependencies": {
"ava": "^2.1.0",
Expand Down
15 changes: 15 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,21 @@ Default: `true`

Ignores [junk](https://github.com/sindresorhus/junk) files.

#### filter

Type: `string | Function`

Function to filter copied files. Return true to include, false to exclude. Can also return a Promise that resolves to true or false.

```js
const cpy = require('cpy');

(async () => {
await cpy('foo.js', 'destination', {
filter: name => !name.includes('NOCOPY')
});
})();
```
## Progress reporting

### cpy.on('progress', handler)
Expand Down
14 changes: 14 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ test('throws on invalid concurrency value', async t => {
await t.throwsAsync(cpy(['license', 'package.json'], t.context.tmp, {concurrency: 'foo'}));
});

test('copy array of files with filter', async t => {
await cpy(['license', 'package.json'], t.context.tmp, {filter: name => name !== 'license'});

t.false(fs.existsSync(path.join(t.context.tmp, 'license')));
t.is(read('package.json'), read(t.context.tmp, 'package.json'));
});

test('copy array of files with async filter', async t => {
await cpy(['license', 'package.json'], t.context.tmp, {filter: async name => name !== 'license'});

t.false(fs.existsSync(path.join(t.context.tmp, 'license')));
t.is(read('package.json'), read(t.context.tmp, 'package.json'));
});

test('cwd', async t => {
fs.mkdirSync(t.context.tmp);
fs.mkdirSync(path.join(t.context.tmp, 'cwd'));
Expand Down

0 comments on commit 93f6893

Please sign in to comment.