Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add concurrency option (#69)
  • Loading branch information
threequartersjohn authored and sindresorhus committed Aug 3, 2019
1 parent b1ca91c commit 4e282cc
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 12 deletions.
7 changes: 7 additions & 0 deletions index.d.ts
Expand Up @@ -32,6 +32,13 @@ declare namespace cpy {
```
*/
readonly rename?: string | ((basename: string) => string);

/**
Number of files being copied concurrently.
@default (os.cpus().length || 1) * 2
*/
readonly concurrency?: number;
}

interface ProgressData {
Expand Down
29 changes: 18 additions & 11 deletions index.js
@@ -1,6 +1,8 @@
'use strict';
const EventEmitter = require('events');
const path = require('path');
const os = require('os');
const pAll = require('p-all');
const arrify = require('arrify');
const globby = require('globby');
const cpFile = require('cp-file');
Expand Down Expand Up @@ -29,7 +31,10 @@ const preprocessDestinationPath = (source, destination, options) => {
return path.join(destination, basename);
};

module.exports = (source, destination, options = {}) => {
module.exports = (source, destination, {
concurrency = (os.cpus().lengh || 1) * 2,
...options
} = {}) => {
const progressEmitter = new EventEmitter();

const promise = (async () => {
Expand Down Expand Up @@ -84,18 +89,20 @@ module.exports = (source, destination, options = {}) => {
}
};

return Promise.all(files.map(async sourcePath => {
const from = preprocessSourcePath(sourcePath, options);
const to = preprocessDestinationPath(sourcePath, destination, options);
return pAll(files.map(sourcePath => {
return async () => {
const from = preprocessSourcePath(sourcePath, options);
const to = preprocessDestinationPath(sourcePath, destination, options);

try {
await cpFile(from, to, options).on('progress', fileProgressHandler);
} catch (error) {
throw new CpyError(`Cannot copy from \`${from}\` to \`${to}\`: ${error.message}`, error);
}
try {
await cpFile(from, to, options).on('progress', fileProgressHandler);
} catch (error) {
throw new CpyError(`Cannot copy from \`${from}\` to \`${to}\`: ${error.message}`, error);
}

return to;
}));
return to;
};
}), {concurrency});
})();

promise.on = (...arguments_) => {
Expand Down
4 changes: 4 additions & 0 deletions index.test-d.ts
Expand Up @@ -23,6 +23,10 @@ expectType<Promise<string[]> & ProgressEmitter>(
expectType<Promise<string[]> & ProgressEmitter>(
cpy('foo.js', 'destination', {overwrite: false})
);
expectType<Promise<string[]> & ProgressEmitter>(
cpy('foo.js', 'destination', {concurrency: 2})
);


expectType<Promise<string[]>>(
cpy('foo.js', 'destination').on('progress', progress => {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -45,7 +45,8 @@
"arrify": "^2.0.1",
"cp-file": "^7.0.0",
"globby": "^9.2.0",
"nested-error-stacks": "^2.1.0"
"nested-error-stacks": "^2.1.0",
"p-all": "^2.1.0"
},
"devDependencies": {
"ava": "^2.1.0",
Expand Down
7 changes: 7 additions & 0 deletions readme.md
Expand Up @@ -94,6 +94,13 @@ const cpy = require('cpy');
})();
```

##### concurrency

Type: `number`<br>
Default: `(os.cpus().length || 1) * 2`

Number of files being copied concurrently.


## Progress reporting

Expand Down
5 changes: 5 additions & 0 deletions test.js
Expand Up @@ -49,6 +49,11 @@ test('copy array of files', async t => {
t.is(read('package.json'), read(t.context.tmp, 'package.json'));
});

test('throws on invalid concurrency value', async t => {
await t.throwsAsync(cpy(['license', 'package.json'], t.context.tmp, {concurrency: -2}));
await t.throwsAsync(cpy(['license', 'package.json'], t.context.tmp, {concurrency: 'foo'}));
});

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

0 comments on commit 4e282cc

Please sign in to comment.