diff --git a/package.json b/package.json index e7d3ea7ddc..4dccf3f93d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "death": "^1.0.0", "debug": "^2.2.0", "detect-indent": "^5.0.0", + "fcopy": "^0.0.7", "gunzip-maybe": "^1.4.0", "ini": "^1.3.4", "inquirer": "^3.0.1", diff --git a/src/util/fs.js b/src/util/fs.js index 609889728d..5d585f865b 100644 --- a/src/util/fs.js +++ b/src/util/fs.js @@ -6,6 +6,7 @@ import * as promise from './promise.js'; import {promisify} from './promise.js'; import map from './map.js'; +const fcopy = require('fcopy'); const path = require('path'); const fs = require('fs'); const os = require('os'); @@ -26,8 +27,9 @@ export const exists: (path: string) => Promise = promisify(fs.exists, t export const lstat: (path: string) => Promise = promisify(fs.lstat); export const chmod: (path: string, mode: number | string) => Promise = promisify(fs.chmod); export const link: (path: string) => Promise = promisify(fs.link); +export const utimes: (path: string, atime: number, mtime: number) => Promise = promisify(fs.utimes); -const CONCURRENT_QUEUE_ITEMS = 4; +const CONCURRENT_QUEUE_ITEMS = 16; const fsSymlink: ( target: string, @@ -510,37 +512,16 @@ export async function copyBulk( } const cleanup = () => delete currentlyWriting[data.dest]; - return currentlyWriting[data.dest] = new Promise((resolve, reject) => { - const readStream = fs.createReadStream(data.src); - const writeStream = fs.createWriteStream(data.dest, {mode: data.mode}); - + return currentlyWriting[data.dest] = (async function() : Promise { reporter.verbose(reporter.lang('verboseFileCopy', data.src, data.dest)); - - readStream.on('error', reject); - writeStream.on('error', reject); - - writeStream.on('open', function() { - readStream.pipe(writeStream); - }); - - writeStream.once('close', function() { - fs.utimes(data.dest, data.atime, data.mtime, function(err) { - if (err) { - reject(err); - } else { - events.onProgress(data.dest); - cleanup(); - resolve(); - } - }); - }); - }).then((arg) => { - cleanup(); - return arg; - }).catch((arg) => { - cleanup(); - throw arg; - }); + try { + await fcopy(data.src, data.dest, {mode: data.mode}); + await utimes(data.dest, data.atime, data.mtime); + events.onProgress(data.dest); + } finally { + cleanup(); + } + })(); }, CONCURRENT_QUEUE_ITEMS); // we need to copy symlinks last as they could reference files we were copying diff --git a/yarn.lock b/yarn.lock index 2c843b0217..6979d76799 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1695,6 +1695,12 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" +fcopy@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/fcopy/-/fcopy-0.0.7.tgz#bad8c8f1d256f1bae65e4165334bae58b1d190c2" + dependencies: + nan "^2.6.2" + figures@^1.3.5: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -3281,6 +3287,10 @@ nan@^2.3.0: version "2.5.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2" +nan@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" + natives@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31"