From a8e229f82d38ece787f6b8a8170d6b3955f4f6ce Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 27 Jul 2018 13:25:06 -0700 Subject: [PATCH] Utilize fs.copyFileSync if available. * Currently would only be utilized on windows * available in node 8.5.x * prefer Copy-On-Write if available * good benchmarks https://github.com/yarnpkg/yarn/pull/3290 Although node-copy-file-sync module exists, it uses more modern JS features. Which this library cannot yet support (without major version bump) --- index.js | 13 ++++++++++++- tests/index.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index d69b26f..f81d5c7 100644 --- a/index.js +++ b/index.js @@ -123,6 +123,13 @@ function symlink(_srcPath, _destPath) { // Fix for https://github.com/broccolijs/broccoli-merge-trees/issues/42 var WINDOWS_PREFIX = "\\\\?\\"; +function copyFileSync(srcPath, destPath, stat) { + options.fs.writeFileSync(destPath, options.fs.readFileSync(srcPath), { + flag: 'wx', + mode: stat.mode + }); +} + function symlinkWindows(srcPath, destPath) { var stat = options.fs.lstatSync(srcPath); var isDir = stat.isDirectory(); @@ -143,7 +150,11 @@ function symlinkWindows(srcPath, destPath) { if (isDir) { options.fs.symlinkSync(srcPath, destPath, 'junction'); } else { - options.fs.writeFileSync(destPath, options.fs.readFileSync(srcPath), { flag: 'wx', mode: stat.mode }); + if (options.fs.copyFileSync) { + options.fs.copyFileSync(srcPath, destPath); + } else { + copyFileSync(srcPath, destPath, stat); + } options.fs.utimesSync(destPath, stat.atime, stat.mtime); } } diff --git a/tests/index.js b/tests/index.js index f93a8ae..5799f14 100644 --- a/tests/index.js +++ b/tests/index.js @@ -122,6 +122,58 @@ describe('symlink-or-copy', function() { assert.equal(utimesSyncCount, 1); }); + it('windows falls back to copyFileSync if available for file', function() { + var count = 0 + var lstatSyncCount = 0 + var isDirectoryCount = 0 + var readFileSyncCount = 0 + var writeFileSyncCount = 0 + var utimesSyncCount = 0 + var copyFileSync = 0 + symLinkOrCopy.setOptions({ + isWindows: true, + canSymLink: false, + fs: { + lstatSync: function() { + lstatSyncCount++; + return { + isSymbolicLink: function() { + return true; + }, + isDirectory: function() { + isDirectoryCount++; + return false; + } + }; + }, + readFileSync: function() { + readFileSyncCount++; + return 'foo'; + }, + writeFileSync: function() { + writeFileSyncCount++; + return 'foo'; + }, + copyFileSync: function() { + copyFileSync++; + return 'foo'; + }, + realpathSync: function() {count++;}, + symlinkSync: function() {count++;}, + utimesSync: function() {utimesSyncCount++;} + } + }); + + symLinkOrCopy.sync('foo', 'bar'); + assert.equal(count, 1); + assert.equal(lstatSyncCount, 2); + assert.equal(isDirectoryCount, 2); + assert.equal(writeFileSyncCount, 0); + assert.equal(copyFileSync, 1); + assert.equal(readFileSyncCount, 0); + assert.equal(utimesSyncCount, 1); + }); + it('windows symlinks when has permission', function() { var count = 0; symLinkOrCopy.setOptions({