Comparing version
@@ -5,4 +5,4 @@ 'use strict' | ||
const path = require('path') | ||
const mkdirpSync = require('../mkdirs').mkdirsSync | ||
const utimesSync = require('../util/utimes.js').utimesMillisSync | ||
const mkdirsSync = require('../mkdirs').mkdirsSync | ||
const utimesMillisSync = require('../util/utimes').utimesMillisSync | ||
const stat = require('../util/stat') | ||
@@ -33,3 +33,3 @@ | ||
const destParent = path.dirname(dest) | ||
if (!fs.existsSync(destParent)) mkdirpSync(destParent) | ||
if (!fs.existsSync(destParent)) mkdirsSync(destParent) | ||
return startCopy(destStat, src, dest, opts) | ||
@@ -69,35 +69,37 @@ } | ||
function copyFile (srcStat, src, dest, opts) { | ||
if (typeof fs.copyFileSync === 'function') { | ||
fs.copyFileSync(src, dest) | ||
fs.chmodSync(dest, srcStat.mode) | ||
if (opts.preserveTimestamps) { | ||
return utimesSync(dest, srcStat.atime, srcStat.mtime) | ||
} | ||
return | ||
} | ||
return copyFileFallback(srcStat, src, dest, opts) | ||
fs.copyFileSync(src, dest) | ||
if (opts.preserveTimestamps) handleTimestamps(srcStat.mode, src, dest) | ||
return setDestMode(dest, srcStat.mode) | ||
} | ||
function copyFileFallback (srcStat, src, dest, opts) { | ||
const BUF_LENGTH = 64 * 1024 | ||
const _buff = require('../util/buffer')(BUF_LENGTH) | ||
function handleTimestamps (srcMode, src, dest) { | ||
// Make sure the file is writable before setting the timestamp | ||
// otherwise open fails with EPERM when invoked with 'r+' | ||
// (through utimes call) | ||
if (fileIsNotWritable(srcMode)) makeFileWritable(dest, srcMode) | ||
return setDestTimestamps(src, dest) | ||
} | ||
const fdr = fs.openSync(src, 'r') | ||
const fdw = fs.openSync(dest, 'w', srcStat.mode) | ||
let pos = 0 | ||
function fileIsNotWritable (srcMode) { | ||
return (srcMode & 0o200) === 0 | ||
} | ||
while (pos < srcStat.size) { | ||
const bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos) | ||
fs.writeSync(fdw, _buff, 0, bytesRead) | ||
pos += bytesRead | ||
} | ||
function makeFileWritable (dest, srcMode) { | ||
return setDestMode(dest, srcMode | 0o200) | ||
} | ||
if (opts.preserveTimestamps) fs.futimesSync(fdw, srcStat.atime, srcStat.mtime) | ||
function setDestMode (dest, srcMode) { | ||
return fs.chmodSync(dest, srcMode) | ||
} | ||
fs.closeSync(fdr) | ||
fs.closeSync(fdw) | ||
function setDestTimestamps (src, dest) { | ||
// The initial srcStat.atime cannot be trusted | ||
// because it is modified by the read(2) system call | ||
// (See https://nodejs.org/api/fs.html#fs_stat_time_values) | ||
const updatedSrcStat = fs.statSync(src) | ||
return utimesMillisSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime) | ||
} | ||
function onDir (srcStat, destStat, src, dest, opts) { | ||
if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts) | ||
if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts) | ||
if (destStat && !destStat.isDirectory()) { | ||
@@ -109,6 +111,6 @@ throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`) | ||
function mkDirAndCopy (srcStat, src, dest, opts) { | ||
function mkDirAndCopy (srcMode, src, dest, opts) { | ||
fs.mkdirSync(dest) | ||
copyDir(src, dest, opts) | ||
return fs.chmodSync(dest, srcStat.mode) | ||
return setDestMode(dest, srcMode) | ||
} | ||
@@ -115,0 +117,0 @@ |
@@ -5,5 +5,5 @@ 'use strict' | ||
const path = require('path') | ||
const mkdirp = require('../mkdirs').mkdirs | ||
const mkdirs = require('../mkdirs').mkdirs | ||
const pathExists = require('../path-exists').pathExists | ||
const utimes = require('../util/utimes').utimesMillis | ||
const utimesMillis = require('../util/utimes').utimesMillis | ||
const stat = require('../util/stat') | ||
@@ -47,3 +47,3 @@ | ||
if (dirExists) return startCopy(destStat, src, dest, opts, cb) | ||
mkdirp(destParent, err => { | ||
mkdirs(destParent, err => { | ||
if (err) return cb(err) | ||
@@ -97,28 +97,48 @@ return startCopy(destStat, src, dest, opts, cb) | ||
function copyFile (srcStat, src, dest, opts, cb) { | ||
if (typeof fs.copyFile === 'function') { | ||
return fs.copyFile(src, dest, err => { | ||
fs.copyFile(src, dest, err => { | ||
if (err) return cb(err) | ||
if (opts.preserveTimestamps) return handleTimestampsAndMode(srcStat.mode, src, dest, cb) | ||
return setDestMode(dest, srcStat.mode, cb) | ||
}) | ||
} | ||
function handleTimestampsAndMode (srcMode, src, dest, cb) { | ||
// Make sure the file is writable before setting the timestamp | ||
// otherwise open fails with EPERM when invoked with 'r+' | ||
// (through utimes call) | ||
if (fileIsNotWritable(srcMode)) { | ||
return makeFileWritable(dest, srcMode, err => { | ||
if (err) return cb(err) | ||
return setDestModeAndTimestamps(srcStat, dest, opts, cb) | ||
return setDestTimestampsAndMode(srcMode, src, dest, cb) | ||
}) | ||
} | ||
return copyFileFallback(srcStat, src, dest, opts, cb) | ||
return setDestTimestampsAndMode(srcMode, src, dest, cb) | ||
} | ||
function copyFileFallback (srcStat, src, dest, opts, cb) { | ||
const rs = fs.createReadStream(src) | ||
rs.on('error', err => cb(err)).once('open', () => { | ||
const ws = fs.createWriteStream(dest, { mode: srcStat.mode }) | ||
ws.on('error', err => cb(err)) | ||
.on('open', () => rs.pipe(ws)) | ||
.once('close', () => setDestModeAndTimestamps(srcStat, dest, opts, cb)) | ||
function fileIsNotWritable (srcMode) { | ||
return (srcMode & 0o200) === 0 | ||
} | ||
function makeFileWritable (dest, srcMode, cb) { | ||
return setDestMode(dest, srcMode | 0o200, cb) | ||
} | ||
function setDestTimestampsAndMode (srcMode, src, dest, cb) { | ||
setDestTimestamps(src, dest, err => { | ||
if (err) return cb(err) | ||
return setDestMode(dest, srcMode, cb) | ||
}) | ||
} | ||
function setDestModeAndTimestamps (srcStat, dest, opts, cb) { | ||
fs.chmod(dest, srcStat.mode, err => { | ||
function setDestMode (dest, srcMode, cb) { | ||
return fs.chmod(dest, srcMode, cb) | ||
} | ||
function setDestTimestamps (src, dest, cb) { | ||
// The initial srcStat.atime cannot be trusted | ||
// because it is modified by the read(2) system call | ||
// (See https://nodejs.org/api/fs.html#fs_stat_time_values) | ||
fs.stat(src, (err, updatedSrcStat) => { | ||
if (err) return cb(err) | ||
if (opts.preserveTimestamps) { | ||
return utimes(dest, srcStat.atime, srcStat.mtime, cb) | ||
} | ||
return cb() | ||
return utimesMillis(dest, updatedSrcStat.atime, updatedSrcStat.mtime, cb) | ||
}) | ||
@@ -128,3 +148,3 @@ } | ||
function onDir (srcStat, destStat, src, dest, opts, cb) { | ||
if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts, cb) | ||
if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts, cb) | ||
if (destStat && !destStat.isDirectory()) { | ||
@@ -136,3 +156,3 @@ return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)) | ||
function mkDirAndCopy (srcStat, src, dest, opts, cb) { | ||
function mkDirAndCopy (srcMode, src, dest, opts, cb) { | ||
fs.mkdir(dest, err => { | ||
@@ -142,3 +162,3 @@ if (err) return cb(err) | ||
if (err) return cb(err) | ||
return fs.chmod(dest, srcStat.mode, cb) | ||
return setDestMode(dest, srcMode, cb) | ||
}) | ||
@@ -145,0 +165,0 @@ }) |
@@ -33,3 +33,3 @@ 'use strict' | ||
items = fs.readdirSync(dir) | ||
} catch (err) { | ||
} catch { | ||
return mkdir.mkdirsSync(dir) | ||
@@ -36,0 +36,0 @@ } |
@@ -7,3 +7,2 @@ 'use strict' | ||
const mkdir = require('../mkdirs') | ||
const pathExists = require('../path-exists').pathExists | ||
@@ -21,9 +20,22 @@ function createFile (file, callback) { | ||
const dir = path.dirname(file) | ||
pathExists(dir, (err, dirExists) => { | ||
if (err) return callback(err) | ||
if (dirExists) return makeFile() | ||
mkdir.mkdirs(dir, err => { | ||
if (err) return callback(err) | ||
makeFile() | ||
}) | ||
fs.stat(dir, (err, stats) => { | ||
if (err) { | ||
// if the directory doesn't exist, make it | ||
if (err.code === 'ENOENT') { | ||
return mkdir.mkdirs(dir, err => { | ||
if (err) return callback(err) | ||
makeFile() | ||
}) | ||
} | ||
return callback(err) | ||
} | ||
if (stats.isDirectory()) makeFile() | ||
else { | ||
// parent is not a directory | ||
// This is just to cause an internal ENOTDIR error to be thrown | ||
fs.readdir(dir, err => { | ||
if (err) return callback(err) | ||
}) | ||
} | ||
}) | ||
@@ -37,8 +49,16 @@ }) | ||
stats = fs.statSync(file) | ||
} catch (e) {} | ||
} catch {} | ||
if (stats && stats.isFile()) return | ||
const dir = path.dirname(file) | ||
if (!fs.existsSync(dir)) { | ||
mkdir.mkdirsSync(dir) | ||
try { | ||
if (!fs.statSync(dir).isDirectory()) { | ||
// parent is not a directory | ||
// This is just to cause an internal ENOTDIR error to be thrown | ||
fs.readdirSync(dir) | ||
} | ||
} catch (err) { | ||
// If the stat call above failed because the directory doesn't exist, create it | ||
if (err && err.code === 'ENOENT') mkdir.mkdirsSync(dir) | ||
else throw err | ||
} | ||
@@ -45,0 +65,0 @@ |
@@ -37,4 +37,4 @@ 'use strict' | ||
return callback(null, { | ||
'toCwd': srcpath, | ||
'toDst': srcpath | ||
toCwd: srcpath, | ||
toDst: srcpath | ||
}) | ||
@@ -49,4 +49,4 @@ }) | ||
return callback(null, { | ||
'toCwd': relativeToDst, | ||
'toDst': srcpath | ||
toCwd: relativeToDst, | ||
toDst: srcpath | ||
}) | ||
@@ -60,4 +60,4 @@ } else { | ||
return callback(null, { | ||
'toCwd': srcpath, | ||
'toDst': path.relative(dstdir, srcpath) | ||
toCwd: srcpath, | ||
toDst: path.relative(dstdir, srcpath) | ||
}) | ||
@@ -76,4 +76,4 @@ }) | ||
return { | ||
'toCwd': srcpath, | ||
'toDst': srcpath | ||
toCwd: srcpath, | ||
toDst: srcpath | ||
} | ||
@@ -86,4 +86,4 @@ } else { | ||
return { | ||
'toCwd': relativeToDst, | ||
'toDst': srcpath | ||
toCwd: relativeToDst, | ||
toDst: srcpath | ||
} | ||
@@ -94,4 +94,4 @@ } else { | ||
return { | ||
'toCwd': srcpath, | ||
'toDst': path.relative(dstdir, srcpath) | ||
toCwd: srcpath, | ||
toDst: path.relative(dstdir, srcpath) | ||
} | ||
@@ -98,0 +98,0 @@ } |
@@ -22,3 +22,3 @@ 'use strict' | ||
stats = fs.lstatSync(srcpath) | ||
} catch (e) { | ||
} catch { | ||
return 'file' | ||
@@ -25,0 +25,0 @@ } |
@@ -21,4 +21,4 @@ 'use strict' | ||
'futimes', | ||
'lchmod', | ||
'lchown', | ||
'lchmod', | ||
'link', | ||
@@ -29,4 +29,5 @@ 'lstat', | ||
'open', | ||
'opendir', | ||
'readdir', | ||
'readFile', | ||
'readdir', | ||
'readlink', | ||
@@ -44,4 +45,3 @@ 'realpath', | ||
// Some commands are not available on some systems. Ex: | ||
// fs.copyFile was added in Node.js v8.5.0 | ||
// fs.mkdtemp was added in Node.js v5.10.0 | ||
// fs.opendir was added in Node.js v12.12.0 | ||
// fs.lchown is not available on at least some Linux | ||
@@ -77,3 +77,3 @@ return typeof fs[key] === 'function' | ||
// fs.read() & fs.write need special treatment due to multiple callback args | ||
// fs.read(), fs.write(), & fs.writev() need special treatment due to multiple callback args | ||
@@ -110,2 +110,21 @@ exports.read = function (fd, buffer, offset, length, position, callback) { | ||
// fs.writev only available in Node v12.9.0+ | ||
if (typeof fs.writev === 'function') { | ||
// Function signature is | ||
// s.writev(fd, buffers[, position], callback) | ||
// We need to handle the optional arg, so we use ...args | ||
exports.writev = function (fd, buffers, ...args) { | ||
if (typeof args[args.length - 1] === 'function') { | ||
return fs.writev(fd, buffers, ...args) | ||
} | ||
return new Promise((resolve, reject) => { | ||
fs.writev(fd, buffers, ...args, (err, bytesWritten, buffers) => { | ||
if (err) return reject(err) | ||
resolve({ bytesWritten, buffers }) | ||
}) | ||
}) | ||
} | ||
} | ||
// fs.realpath.native only available in Node v9.2+ | ||
@@ -112,0 +131,0 @@ if (typeof fs.realpath.native === 'function') { |
'use strict' | ||
module.exports = Object.assign( | ||
{}, | ||
module.exports = { | ||
// Export promiseified graceful-fs: | ||
require('./fs'), | ||
...require('./fs'), | ||
// Export extra methods: | ||
require('./copy-sync'), | ||
require('./copy'), | ||
require('./empty'), | ||
require('./ensure'), | ||
require('./json'), | ||
require('./mkdirs'), | ||
require('./move-sync'), | ||
require('./move'), | ||
require('./output'), | ||
require('./path-exists'), | ||
require('./remove') | ||
) | ||
...require('./copy-sync'), | ||
...require('./copy'), | ||
...require('./empty'), | ||
...require('./ensure'), | ||
...require('./json'), | ||
...require('./mkdirs'), | ||
...require('./move-sync'), | ||
...require('./move'), | ||
...require('./output'), | ||
...require('./path-exists'), | ||
...require('./remove') | ||
} | ||
@@ -21,0 +20,0 @@ // Export fs.promises as a getter property so that we don't trigger |
'use strict' | ||
const u = require('universalify').fromCallback | ||
const u = require('universalify').fromPromise | ||
const jsonFile = require('./jsonfile') | ||
@@ -5,0 +5,0 @@ |
'use strict' | ||
const u = require('universalify').fromCallback | ||
const jsonFile = require('jsonfile') | ||
@@ -8,6 +7,6 @@ | ||
// jsonfile exports | ||
readJson: u(jsonFile.readFile), | ||
readJson: jsonFile.readFile, | ||
readJsonSync: jsonFile.readFileSync, | ||
writeJson: u(jsonFile.writeFile), | ||
writeJson: jsonFile.writeFile, | ||
writeJsonSync: jsonFile.writeFileSync | ||
} |
'use strict' | ||
const fs = require('graceful-fs') | ||
const path = require('path') | ||
const mkdir = require('../mkdirs') | ||
const jsonFile = require('./jsonfile') | ||
const { stringify } = require('jsonfile/utils') | ||
const { outputFileSync } = require('../output') | ||
function outputJsonSync (file, data, options) { | ||
const dir = path.dirname(file) | ||
const str = stringify(data, options) | ||
if (!fs.existsSync(dir)) { | ||
mkdir.mkdirsSync(dir) | ||
} | ||
jsonFile.writeJsonSync(file, data, options) | ||
outputFileSync(file, str, options) | ||
} | ||
module.exports = outputJsonSync |
'use strict' | ||
const path = require('path') | ||
const mkdir = require('../mkdirs') | ||
const pathExists = require('../path-exists').pathExists | ||
const jsonFile = require('./jsonfile') | ||
const { stringify } = require('jsonfile/utils') | ||
const { outputFile } = require('../output') | ||
function outputJson (file, data, options, callback) { | ||
if (typeof options === 'function') { | ||
callback = options | ||
options = {} | ||
} | ||
async function outputJson (file, data, options = {}) { | ||
const str = stringify(data, options) | ||
const dir = path.dirname(file) | ||
pathExists(dir, (err, itDoes) => { | ||
if (err) return callback(err) | ||
if (itDoes) return jsonFile.writeJson(file, data, options, callback) | ||
mkdir.mkdirs(dir, err => { | ||
if (err) return callback(err) | ||
jsonFile.writeJson(file, data, options, callback) | ||
}) | ||
}) | ||
await outputFile(file, str, options) | ||
} | ||
module.exports = outputJson |
'use strict' | ||
const u = require('universalify').fromCallback | ||
const mkdirs = u(require('./mkdirs')) | ||
const mkdirsSync = require('./mkdirs-sync') | ||
const u = require('universalify').fromPromise | ||
const { makeDir: _makeDir, makeDirSync } = require('./make-dir') | ||
const makeDir = u(_makeDir) | ||
module.exports = { | ||
mkdirs, | ||
mkdirsSync, | ||
mkdirs: makeDir, | ||
mkdirsSync: makeDirSync, | ||
// alias | ||
mkdirp: mkdirs, | ||
mkdirpSync: mkdirsSync, | ||
ensureDir: mkdirs, | ||
ensureDirSync: mkdirsSync | ||
mkdirp: makeDir, | ||
mkdirpSync: makeDirSync, | ||
ensureDir: makeDir, | ||
ensureDirSync: makeDirSync | ||
} |
@@ -305,3 +305,3 @@ 'use strict' | ||
return ret | ||
} catch (er) { } | ||
} catch {} | ||
} while (Date.now() - startTime < 500) // give up after 500ms | ||
@@ -308,0 +308,0 @@ } else { |
'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 NODE_VERSION_MAJOR_WITH_BIGINT = 10 | ||
const NODE_VERSION_MINOR_WITH_BIGINT = 5 | ||
const NODE_VERSION_PATCH_WITH_BIGINT = 0 | ||
const nodeVersion = process.versions.node.split('.') | ||
const nodeVersionMajor = Number.parseInt(nodeVersion[0], 10) | ||
const nodeVersionMinor = Number.parseInt(nodeVersion[1], 10) | ||
const nodeVersionPatch = Number.parseInt(nodeVersion[2], 10) | ||
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 nodeSupportsBigInt () { | ||
if (nodeVersionMajor > NODE_VERSION_MAJOR_WITH_BIGINT) { | ||
return true | ||
} else if (nodeVersionMajor === NODE_VERSION_MAJOR_WITH_BIGINT) { | ||
if (nodeVersionMinor > NODE_VERSION_MINOR_WITH_BIGINT) { | ||
return true | ||
} else if (nodeVersionMinor === NODE_VERSION_MINOR_WITH_BIGINT) { | ||
if (nodeVersionPatch >= NODE_VERSION_PATCH_WITH_BIGINT) { | ||
return true | ||
} | ||
} | ||
} | ||
return false | ||
} | ||
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) { | ||
@@ -76,6 +35,6 @@ if (err.code === 'ENOENT') return { srcStat, destStat: null } | ||
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 && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) { | ||
if (destStat && areIdentical(srcStat, destStat)) { | ||
return cb(new Error('Source and destination must not be the same.')) | ||
@@ -92,3 +51,3 @@ } | ||
const { srcStat, destStat } = getStatsSync(src, dest) | ||
if (destStat && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) { | ||
if (destStat && areIdentical(srcStat, destStat)) { | ||
throw new Error('Source and destination must not be the same.') | ||
@@ -110,25 +69,14 @@ } | ||
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 (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) { | ||
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 (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) { | ||
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) | ||
} | ||
@@ -142,7 +90,3 @@ | ||
try { | ||
if (nodeSupportsBigInt()) { | ||
destStat = fs.statSync(destParent, { bigint: true }) | ||
} else { | ||
destStat = fs.statSync(destParent) | ||
} | ||
destStat = statSync(destParent) | ||
} catch (err) { | ||
@@ -152,3 +96,3 @@ if (err.code === 'ENOENT') return | ||
} | ||
if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) { | ||
if (areIdentical(srcStat, destStat)) { | ||
throw new Error(errMsg(src, dest, funcName)) | ||
@@ -159,2 +103,25 @@ } | ||
function areIdentical (srcStat, destStat) { | ||
if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) { | ||
if (nodeSupportsBigInt || destStat.ino < Number.MAX_SAFE_INTEGER) { | ||
// definitive answer | ||
return true | ||
} | ||
// Use additional heuristics if we can't use 'bigint'. | ||
// Different 'ino' could be represented the same if they are >= Number.MAX_SAFE_INTEGER | ||
// See issue 657 | ||
if (destStat.size === srcStat.size && | ||
destStat.mode === srcStat.mode && | ||
destStat.nlink === srcStat.nlink && | ||
destStat.atimeMs === srcStat.atimeMs && | ||
destStat.mtimeMs === srcStat.mtimeMs && | ||
destStat.ctimeMs === srcStat.ctimeMs && | ||
destStat.birthtimeMs === srcStat.birthtimeMs) { | ||
// heuristic answer | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
// return true if dest is a subdir of src, otherwise false. | ||
@@ -161,0 +128,0 @@ // It only checks the path strings. |
'use strict' | ||
const fs = require('graceful-fs') | ||
const os = require('os') | ||
const path = require('path') | ||
// HFS, ext{2,3}, FAT do not, Node.js v0.10 does not | ||
function hasMillisResSync () { | ||
let tmpfile = path.join('millis-test-sync' + Date.now().toString() + Math.random().toString().slice(2)) | ||
tmpfile = path.join(os.tmpdir(), tmpfile) | ||
// 550 millis past UNIX epoch | ||
const d = new Date(1435410243862) | ||
fs.writeFileSync(tmpfile, 'https://github.com/jprichardson/node-fs-extra/pull/141') | ||
const fd = fs.openSync(tmpfile, 'r+') | ||
fs.futimesSync(fd, d, d) | ||
fs.closeSync(fd) | ||
return fs.statSync(tmpfile).mtime > 1435410243000 | ||
} | ||
function hasMillisRes (callback) { | ||
let tmpfile = path.join('millis-test' + Date.now().toString() + Math.random().toString().slice(2)) | ||
tmpfile = path.join(os.tmpdir(), tmpfile) | ||
// 550 millis past UNIX epoch | ||
const d = new Date(1435410243862) | ||
fs.writeFile(tmpfile, 'https://github.com/jprichardson/node-fs-extra/pull/141', err => { | ||
if (err) return callback(err) | ||
fs.open(tmpfile, 'r+', (err, fd) => { | ||
if (err) return callback(err) | ||
fs.futimes(fd, d, d, err => { | ||
if (err) return callback(err) | ||
fs.close(fd, err => { | ||
if (err) return callback(err) | ||
fs.stat(tmpfile, (err, stats) => { | ||
if (err) return callback(err) | ||
callback(null, stats.mtime > 1435410243000) | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) | ||
} | ||
function timeRemoveMillis (timestamp) { | ||
if (typeof timestamp === 'number') { | ||
return Math.floor(timestamp / 1000) * 1000 | ||
} else if (timestamp instanceof Date) { | ||
return new Date(Math.floor(timestamp.getTime() / 1000) * 1000) | ||
} else { | ||
throw new Error('fs-extra: timeRemoveMillis() unknown parameter type') | ||
} | ||
} | ||
function utimesMillis (path, atime, mtime, callback) { | ||
@@ -74,7 +24,4 @@ // if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback) | ||
module.exports = { | ||
hasMillisRes, | ||
hasMillisResSync, | ||
timeRemoveMillis, | ||
utimesMillis, | ||
utimesMillisSync | ||
} |
{ | ||
"name": "fs-extra", | ||
"version": "8.1.0", | ||
"version": "9.0.0", | ||
"description": "fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as mkdir -p, cp -r, and rm -rf.", | ||
"engines": { | ||
"node": ">=6 <7 || >=8" | ||
"node": ">=10" | ||
}, | ||
@@ -34,3 +34,4 @@ "homepage": "https://github.com/jprichardson/node-fs-extra", | ||
"output", | ||
"move" | ||
"move", | ||
"promise" | ||
], | ||
@@ -40,9 +41,9 @@ "author": "JP Richardson <jprichardson@gmail.com>", | ||
"dependencies": { | ||
"at-least-node": "^1.0.0", | ||
"graceful-fs": "^4.2.0", | ||
"jsonfile": "^4.0.0", | ||
"universalify": "^0.1.0" | ||
"jsonfile": "^6.0.1", | ||
"universalify": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"coveralls": "^3.0.0", | ||
"istanbul": "^0.4.5", | ||
"klaw": "^2.1.1", | ||
@@ -52,6 +53,6 @@ "klaw-sync": "^3.0.2", | ||
"mocha": "^5.0.5", | ||
"nyc": "^15.0.0", | ||
"proxyquire": "^2.0.1", | ||
"read-dir-files": "^0.1.1", | ||
"semver": "^5.3.0", | ||
"standard": "^12.0.1" | ||
"standard": "^14.1.0" | ||
}, | ||
@@ -65,3 +66,3 @@ "main": "./lib/index.js", | ||
"full-ci": "npm run lint && npm run coverage", | ||
"coverage": "istanbul cover -i 'lib/**' -x '**/__tests__/**' test.js", | ||
"coverage": "nyc -r lcovonly npm run unit", | ||
"coveralls": "coveralls < coverage/lcov.info", | ||
@@ -68,0 +69,0 @@ "lint": "standard", |
@@ -146,3 +146,3 @@ Node.js: fs-extra | ||
**NOTE:** You can still use the native Node.js methods. They are promisified and copied over to `fs-extra`. See [notes on `fs.read()` & `fs.write()`](docs/fs-read-write.md) | ||
**NOTE:** You can still use the native Node.js methods. They are promisified and copied over to `fs-extra`. See [notes on `fs.read()`, `fs.write()`, & `fs.writev()`](docs/fs-read-write-writev.md) | ||
@@ -149,0 +149,0 @@ ### What happened to `walk()` and `walkSync()`? |
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
129011
1.18%9
-10%1
-50%4
33.33%33
-8.33%1591
-3.34%+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
Updated
Updated