Skip to content

Commit

Permalink
Use the windows CopyFile API for copying files
Browse files Browse the repository at this point in the history
  • Loading branch information
vbfox committed Apr 11, 2017
1 parent fb40251 commit 80bb164
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 26 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"death": "^1.0.0",
"debug": "^2.2.0",
"detect-indent": "^5.0.0",
"ffi": "^2.2.0",
"ini": "^1.3.4",
"inquirer": "^3.0.1",
"invariant": "^2.2.0",
Expand All @@ -29,6 +30,7 @@
"object-path": "^0.11.2",
"proper-lockfile": "^2.0.0",
"read": "^1.0.7",
"ref-wchar": "^1.0.2",
"request": "^2.81.0",
"request-capture-har": "^1.2.2",
"rimraf": "^2.5.0",
Expand Down
78 changes: 54 additions & 24 deletions src/util/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,57 @@ export function copy(src: string, dest: string, reporter: Reporter): Promise<voi
return copyBulk([{src, dest}], reporter);
}

let copyFile = (reporter: Reporter, data: CopyFileAction) => new Promise((resolve, reject) => {
const readStream = fs.createReadStream(data.src);
const writeStream = fs.createWriteStream(data.dest, {mode: data.mode});

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('finish', function() {
fs.utimes(data.dest, data.atime, data.mtime, function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
});

if (process.platform === 'win32') {
const ffi = require('ffi');
const wchar_t = require('ref-wchar');

const kernel32 = ffi.Library('kernel32', {
'CopyFileW': ['uint32', [wchar_t.string, wchar_t.string, 'uint32']],
});

const longFileNamePrefix = '\\\\?\\';

copyFile = (reporter: Reporter, data: CopyFileAction) => new Promise((resolve, reject) => {
reporter.verbose(reporter.lang('verboseFileCopy', data.src, data.dest));

kernel32.CopyFileW.async(longFileNamePrefix + data.src, longFileNamePrefix + data.dest, 0, function(err, res) {
if (err) {
reject(err);
}

if (res === 0) {
reject(new Error('CopyFileW failed'));
}

resolve();
});
});
}

export async function copyBulk(
queue: CopyQueue,
reporter: Reporter,
Expand Down Expand Up @@ -490,31 +541,10 @@ 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});

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('finish', function() {
fs.utimes(data.dest, data.atime, data.mtime, function(err) {
if (err) {
reject(err);
} else {
events.onProgress(data.dest);
cleanup();
resolve();
}
});
});
}).then((arg) => {
return currentlyWriting[data.dest] = copyFile(reporter, data)
.then((arg) => {
events.onProgress(data.dest);
cleanup();
return arg;
}).catch((arg) => {
Expand Down
46 changes: 44 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,10 @@ binary-extensions@^1.0.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"

bindings@1, bindings@~1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"

bl@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.0.tgz#1397e7ec42c5f5dc387470c500e34a9f6be9ea98"
Expand Down Expand Up @@ -1231,7 +1235,7 @@ debug-fabulous@0.0.X:
lazy-debug-legacy "0.0.X"
object-assign "4.1.0"

debug@2.X, debug@^2.1.1, debug@^2.2.0:
debug@2, debug@2.X, debug@^2.1.1, debug@^2.2.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
dependencies:
Expand Down Expand Up @@ -1695,6 +1699,16 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"

ffi@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ffi/-/ffi-2.2.0.tgz#bf18b04666a29f71227ed56895d5430af47042fa"
dependencies:
bindings "~1.2.0"
debug "2"
nan "2"
ref "1"
ref-struct "1"

figures@^1.3.5:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
Expand Down Expand Up @@ -2268,6 +2282,12 @@ iconv-lite@0.4.13:
version "0.4.13"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"

iconv@2:
version "2.2.3"
resolved "https://registry.yarnpkg.com/iconv/-/iconv-2.2.3.tgz#e084d60eeb7d73da7f0a9c096e4c8abe090bfaed"
dependencies:
nan "^2.3.5"

ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
Expand Down Expand Up @@ -3258,7 +3278,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"

nan@^2.3.0:
nan@2, nan@^2.3.0, nan@^2.3.5:
version "2.5.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2"

Expand Down Expand Up @@ -3814,6 +3834,28 @@ rechoir@^0.6.2:
dependencies:
resolve "^1.1.6"

ref-struct@1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ref-struct/-/ref-struct-1.1.0.tgz#5d5ee65ad41cefc3a5c5feb40587261e479edc13"
dependencies:
debug "2"
ref "1"

ref-wchar@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/ref-wchar/-/ref-wchar-1.0.2.tgz#a709aab2f461ac8f3de6d3dcb4d18495f8d93d1e"
dependencies:
iconv "2"
ref "^1.3.1"

ref@1, ref@^1.3.1:
version "1.3.4"
resolved "https://registry.yarnpkg.com/ref/-/ref-1.3.4.tgz#724d2bf8ac85f8c8db194d3d85be6efe416bc1e5"
dependencies:
bindings "1"
debug "2"
nan "2"

regenerate@^1.2.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
Expand Down

0 comments on commit 80bb164

Please sign in to comment.