diff --git a/package.json b/package.json index e7d3ea7ddc..24673cc3c3 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.4", "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..93768f3553 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1695,6 +1695,13 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" +fcopy@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/fcopy/-/fcopy-0.0.4.tgz#ed412be317a02897250242c628962f447694ee14" + dependencies: + nan "^2.6.2" + node-pre-gyp "^0.6.34" + figures@^1.3.5: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -1850,7 +1857,7 @@ fsevents@^1.0.0: nan "^2.3.0" node-pre-gyp "^0.6.29" -fstream-ignore@~1.0.5: +fstream-ignore@^1.0.5, fstream-ignore@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" dependencies: @@ -1858,7 +1865,7 @@ fstream-ignore@~1.0.5: inherits "2" minimatch "^3.0.0" -fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10: +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2, fstream@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822" dependencies: @@ -3281,6 +3288,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" @@ -3350,6 +3361,27 @@ node-pre-gyp@^0.6.29: tar "~2.2.1" tar-pack "~3.3.0" +node-pre-gyp@^0.6.34: + version "0.6.34" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7" + dependencies: + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.0.2" + rc "^1.1.7" + request "^2.81.0" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^2.2.1" + tar-pack "^3.4.0" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -3369,7 +3401,7 @@ normalize-path@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" -npmlog@^4.0.1: +npmlog@^4.0.1, npmlog@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f" dependencies: @@ -3413,7 +3445,7 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -3483,6 +3515,13 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" +osenv@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + p-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" @@ -3728,7 +3767,7 @@ randombytes@^2.0.0, randombytes@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.3.tgz#674c99760901c3c4112771a31e521dc349cc09ec" -rc@~1.1.6: +rc@^1.1.7, rc@~1.1.6: version "1.1.7" resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.7.tgz#c5ea564bb07aff9fd3a5b32e906c1d3a65940fea" dependencies: @@ -3767,7 +3806,7 @@ read@^1.0.7: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@^2.1.5, readable-stream@^2.2.2: +readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.3.tgz#9cf49463985df016c8ae8813097a9293a9b33729" dependencies: @@ -3969,7 +4008,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.0: +rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.0, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: @@ -4305,6 +4344,19 @@ tar-fs@^1.15.1: pump "^1.0.0" tar-stream "^1.1.2" +tar-pack@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" + dependencies: + debug "^2.2.0" + fstream "^1.0.10" + fstream-ignore "^1.0.5" + once "^1.3.3" + readable-stream "^2.1.4" + rimraf "^2.5.1" + tar "^2.2.1" + uid-number "^0.0.6" + tar-pack@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae" @@ -4327,7 +4379,7 @@ tar-stream@^1.1.2, tar-stream@^1.5.2: readable-stream "^2.0.0" xtend "^4.0.0" -tar@~2.2.1: +tar@^2.2.1, tar@~2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -4476,7 +4528,7 @@ uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" -uid-number@~0.0.6: +uid-number@^0.0.6, uid-number@~0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"