Skip to content

Commit

Permalink
Refactor internal stat utils (#764)
Browse files Browse the repository at this point in the history
* Refactor internal getStats() util

Fixes #762

* Proper promise tests for copy()

Our hacky tests don't play well with multiple layers of
callback/promise switching

* Simplify internal checkParentPaths()

* Port improvments to sync methods
  • Loading branch information
RyanZim authored Feb 17, 2020
1 parent ce41762 commit 075c2d1
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 64 deletions.
1 change: 0 additions & 1 deletion lib/__tests__/promise.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const fs = require('fs')
const fse = require('..')

const methods = [
'copy',
'emptyDir',
'ensureFile',
'ensureDir',
Expand Down
13 changes: 13 additions & 0 deletions lib/copy/__tests__/copy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
90 changes: 27 additions & 63 deletions lib/util/stat.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,29 @@
'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)
const statSync = (file) => nodeSupportsBigInt ? fs.statSync(file, { bigint: true }) : fs.statSync(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 })
})
function getStats (src, dest) {
return Promise.all([
stat(src),
stat(dest).catch(err => {
if (err.code === 'ENOENT') return null
throw err
})
} 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 })
})
})
}
]).then(([srcStat, destStat]) => ({ srcStat, destStat }))
}

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
Expand All @@ -53,7 +32,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)) {
Expand Down Expand Up @@ -85,29 +64,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) {
Expand All @@ -116,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
Expand Down

0 comments on commit 075c2d1

Please sign in to comment.