From efa796bbad170d130ad6c8874470e63bc64c4901 Mon Sep 17 00:00:00 2001 From: Ryan Zimmerman Date: Fri, 14 Feb 2020 12:19:02 -0500 Subject: [PATCH 1/4] Refactor internal getStats() util Fixes #762 --- lib/util/stat.js | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/lib/util/stat.js b/lib/util/stat.js index 14fb00c7..a60ba20e 100644 --- a/lib/util/stat.js +++ b/lib/util/stat.js @@ -1,35 +1,21 @@ 'use strict' -const fs = require('graceful-fs') +const fs = require('../fs') const path = require('path') +const util = require('util') const atLeastNode = require('at-least-node') const nodeSupportsBigInt = atLeastNode('10.5.0') +const stat = (file) => nodeSupportsBigInt ? fs.stat(file, { bigint: true }) : fs.stat(file) -function getStats (src, dest, cb) { - if (nodeSupportsBigInt) { - fs.stat(src, { bigint: true }, (err, srcStat) => { - if (err) return cb(err) - fs.stat(dest, { bigint: true }, (err, destStat) => { - if (err) { - if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null }) - return cb(err) - } - return cb(null, { srcStat, destStat }) - }) - }) - } else { - fs.stat(src, (err, srcStat) => { - if (err) return cb(err) - fs.stat(dest, (err, destStat) => { - if (err) { - if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null }) - return cb(err) - } - return cb(null, { srcStat, destStat }) - }) +function getStats (src, dest) { + return Promise.all([ + stat(src), + stat(dest).catch(err => { + if (err.code === 'ENOENT') return null + throw err }) - } + ]).then(([srcStat, destStat]) => ({ srcStat, destStat })) } function getStatsSync (src, dest) { @@ -53,7 +39,7 @@ function getStatsSync (src, dest) { } function checkPaths (src, dest, funcName, cb) { - getStats(src, dest, (err, stats) => { + util.callbackify(getStats)(src, dest, (err, stats) => { if (err) return cb(err) const { srcStat, destStat } = stats if (destStat && areIdentical(srcStat, destStat)) { From c9d2e9e6b0734d557800e912b83bf67e485b1c3c Mon Sep 17 00:00:00 2001 From: Ryan Zimmerman Date: Fri, 14 Feb 2020 12:19:54 -0500 Subject: [PATCH 2/4] Proper promise tests for copy() Our hacky tests don't play well with multiple layers of callback/promise switching --- lib/__tests__/promise.test.js | 1 - lib/copy/__tests__/copy.test.js | 13 +++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/__tests__/promise.test.js b/lib/__tests__/promise.test.js index 2c134687..09417fde 100644 --- a/lib/__tests__/promise.test.js +++ b/lib/__tests__/promise.test.js @@ -7,7 +7,6 @@ const fs = require('fs') const fse = require('..') const methods = [ - 'copy', 'emptyDir', 'ensureFile', 'ensureDir', diff --git a/lib/copy/__tests__/copy.test.js b/lib/copy/__tests__/copy.test.js index 798bafd6..ba230f37 100644 --- a/lib/copy/__tests__/copy.test.js +++ b/lib/copy/__tests__/copy.test.js @@ -72,6 +72,19 @@ describe('fs-extra', () => { }) }) + it('should work with promises', () => { + const fileSrc = path.join(TEST_DIR, 'TEST_fs-extra_src') + const fileDest = path.join(TEST_DIR, 'TEST_fs-extra_copy') + fs.writeFileSync(fileSrc, crypto.randomBytes(SIZE)) + const srcMd5 = crypto.createHash('md5').update(fs.readFileSync(fileSrc)).digest('hex') + let destMd5 = '' + + return fse.copy(fileSrc, fileDest).then(() => { + destMd5 = crypto.createHash('md5').update(fs.readFileSync(fileDest)).digest('hex') + assert.strictEqual(srcMd5, destMd5) + }) + }) + it('should return an error if src file does not exist', done => { const fileSrc = 'we-simply-assume-this-file-does-not-exist.bin' const fileDest = path.join(TEST_DIR, 'TEST_fs-extra_copy') From 02df72f72b94e95b73301ac49f0a39b8d0425e02 Mon Sep 17 00:00:00 2001 From: Ryan Zimmerman Date: Fri, 14 Feb 2020 12:22:01 -0500 Subject: [PATCH 3/4] Simplify internal checkParentPaths() --- lib/util/stat.js | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/lib/util/stat.js b/lib/util/stat.js index a60ba20e..644e40b9 100644 --- a/lib/util/stat.js +++ b/lib/util/stat.js @@ -71,29 +71,18 @@ function checkParentPaths (src, srcStat, dest, funcName, cb) { const srcParent = path.resolve(path.dirname(src)) const destParent = path.resolve(path.dirname(dest)) if (destParent === srcParent || destParent === path.parse(destParent).root) return cb() - if (nodeSupportsBigInt) { - fs.stat(destParent, { bigint: true }, (err, destStat) => { - if (err) { - if (err.code === 'ENOENT') return cb() - return cb(err) - } - if (areIdentical(srcStat, destStat)) { - return cb(new Error(errMsg(src, dest, funcName))) - } - return checkParentPaths(src, srcStat, destParent, funcName, cb) - }) - } else { - fs.stat(destParent, (err, destStat) => { - if (err) { - if (err.code === 'ENOENT') return cb() - return cb(err) - } - if (areIdentical(srcStat, destStat)) { - return cb(new Error(errMsg(src, dest, funcName))) - } - return checkParentPaths(src, srcStat, destParent, funcName, cb) - }) + const callback = (err, destStat) => { + if (err) { + if (err.code === 'ENOENT') return cb() + return cb(err) + } + if (areIdentical(srcStat, destStat)) { + return cb(new Error(errMsg(src, dest, funcName))) + } + return checkParentPaths(src, srcStat, destParent, funcName, cb) } + if (nodeSupportsBigInt) fs.stat(destParent, { bigint: true }, callback) + else fs.stat(destParent, callback) } function checkParentPathsSync (src, srcStat, dest, funcName) { From 1a4ccc0572b050d88d17d6cbd67d54298f772ac3 Mon Sep 17 00:00:00 2001 From: Ryan Zimmerman Date: Fri, 14 Feb 2020 12:56:44 -0500 Subject: [PATCH 4/4] Port improvments to sync methods --- lib/util/stat.js | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/lib/util/stat.js b/lib/util/stat.js index 644e40b9..0b1c1b09 100644 --- a/lib/util/stat.js +++ b/lib/util/stat.js @@ -7,6 +7,7 @@ const atLeastNode = require('at-least-node') const nodeSupportsBigInt = atLeastNode('10.5.0') const stat = (file) => nodeSupportsBigInt ? fs.stat(file, { bigint: true }) : fs.stat(file) +const statSync = (file) => nodeSupportsBigInt ? fs.statSync(file, { bigint: true }) : fs.statSync(file) function getStats (src, dest) { return Promise.all([ @@ -19,18 +20,10 @@ function getStats (src, dest) { } function getStatsSync (src, dest) { - let srcStat, destStat - if (nodeSupportsBigInt) { - srcStat = fs.statSync(src, { bigint: true }) - } else { - srcStat = fs.statSync(src) - } + let destStat + const srcStat = statSync(src) try { - if (nodeSupportsBigInt) { - destStat = fs.statSync(dest, { bigint: true }) - } else { - destStat = fs.statSync(dest) - } + destStat = statSync(dest) } catch (err) { if (err.code === 'ENOENT') return { srcStat, destStat: null } throw err @@ -91,11 +84,7 @@ function checkParentPathsSync (src, srcStat, dest, funcName) { if (destParent === srcParent || destParent === path.parse(destParent).root) return let destStat try { - if (nodeSupportsBigInt) { - destStat = fs.statSync(destParent, { bigint: true }) - } else { - destStat = fs.statSync(destParent) - } + destStat = statSync(destParent) } catch (err) { if (err.code === 'ENOENT') return throw err