Comparing version 3.0.1 to 4.0.0
@@ -0,1 +1,16 @@ | ||
4.0.0 / 2017-07-14 | ||
------------------ | ||
### Changed | ||
- **BREAKING:** The promisified versions of `fs.read()` & `fs.write()` now return objects. See [the docs](docs/fs-read-write.md) for details. | ||
- `fs.move()` now errors out when source and destination are the same. | ||
- Applied upstream fixes from `rimraf` to `fs.remove()` & `fs.removeSync()`. | ||
### Fixed | ||
- Got `fs.outputJSONSync()` working again; it was broken due to refactoring. | ||
Also clarified the docs in a few places. | ||
3.0.1 / 2017-05-04 | ||
@@ -2,0 +17,0 @@ ------------------ |
# outputJsonSync(file, object, [options]) | ||
Almost the same as [`writeJsonSync`](writeJson-sync.md), except that if the directory does not exist, it's created. | ||
`options` are what you'd pass to [`jsonFile.writeFileSync()`](https://github.com/jprichardson/node-jsonfile#writefilesyncfilename-obj-options). | ||
@@ -11,2 +10,5 @@ **Alias:** `outputJSONSync()` | ||
- `options` `<Object>` | ||
- `spaces` `<Number|String>` Number of spaces to indent; or a string to use for indentation (i.e. pass `'\t'` for tab indentation). See [the docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_space_argument) for more info. | ||
- `replacer` [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) | ||
- Also accepts [`fs.writeFileSync` options](https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options) | ||
@@ -13,0 +15,0 @@ ## Example: |
# outputJson(file, object, [options, callback]) | ||
Almost the same as [`writeJson`](writeJson.md), except that if the directory does not exist, it's created. | ||
`options` are what you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback). | ||
@@ -11,2 +10,5 @@ **Alias:** `outputJSON()` | ||
- `options` `<Object>` | ||
- `spaces` `<Number|String>` Number of spaces to indent; or a string to use for indentation (i.e. pass `'\t'` for tab indentation). See [the docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_space_argument) for more info. | ||
- `replacer` [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) | ||
- Also accepts [`fs.writeFile` options](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback) | ||
- `callback` `<Function>` | ||
@@ -13,0 +15,0 @@ |
# writeJsonSync(file, object, [options]) | ||
Writes an object to a JSON file. `options` are the same that | ||
you'd pass to [`jsonFile.writeFileSync()`](https://github.com/jprichardson/node-jsonfile#writefilesyncfilename-obj-options). | ||
Writes an object to a JSON file. | ||
@@ -11,2 +10,5 @@ **Alias:** `writeJSONSync()` | ||
- `options` `<Object>` | ||
- `spaces` `<Number|String>` Number of spaces to indent; or a string to use for indentation (i.e. pass `'\t'` for tab indentation). See [the docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_space_argument) for more info. | ||
- `replacer` [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) | ||
- Also accepts [`fs.writeFileSync` options](https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options) | ||
@@ -13,0 +15,0 @@ ## Example: |
# writeJson(file, object, [options, callback]) | ||
Writes an object to a JSON file. `options` are the same that | ||
you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback). | ||
Writes an object to a JSON file. | ||
@@ -11,2 +10,5 @@ **Alias:** `writeJSON()` | ||
- `options` `<Object>` | ||
- `spaces` `<Number|String>` Number of spaces to indent; or a string to use for indentation (i.e. pass `'\t'` for tab indentation). See [the docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_space_argument) for more info. | ||
- `replacer` [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) | ||
- Also accepts [`fs.writeFile` options](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback) | ||
- `callback` `<Function>` | ||
@@ -13,0 +15,0 @@ |
@@ -24,3 +24,2 @@ // This is adapted from https://github.com/normalize/mz | ||
'open', | ||
'read', | ||
'readFile', | ||
@@ -37,3 +36,2 @@ 'readdir', | ||
'utimes', | ||
'write', | ||
'writeFile' | ||
@@ -64,1 +62,43 @@ ] | ||
} | ||
// fs.read() & fs.write need special treatment due to multiple callback args | ||
exports.read = function (fd, buffer, offset, length, position, callback) { | ||
if (typeof callback === 'function') { | ||
return fs.read(fd, buffer, offset, length, position, callback) | ||
} | ||
return new Promise((resolve, reject) => { | ||
fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer) => { | ||
if (err) return reject(err) | ||
resolve({ bytesRead, buffer }) | ||
}) | ||
}) | ||
} | ||
// Function signature can be | ||
// fs.write(fd, buffer[, offset[, length[, position]]], callback) | ||
// OR | ||
// fs.write(fd, string[, position[, encoding]], callback) | ||
// so we need to handle both cases | ||
exports.write = function (fd, buffer, a, b, c, callback) { | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
return fs.write(fd, buffer, a, b, c, callback) | ||
} | ||
// Check for old, depricated fs.write(fd, string[, position[, encoding]], callback) | ||
if (typeof buffer === 'string') { | ||
return new Promise((resolve, reject) => { | ||
fs.write(fd, buffer, a, b, (err, bytesWritten, buffer) => { | ||
if (err) return reject(err) | ||
resolve({ bytesWritten, buffer }) | ||
}) | ||
}) | ||
} | ||
return new Promise((resolve, reject) => { | ||
fs.write(fd, buffer, a, b, c, (err, bytesWritten, buffer) => { | ||
if (err) return reject(err) | ||
resolve({ bytesWritten, buffer }) | ||
}) | ||
}) | ||
} |
@@ -6,7 +6,7 @@ 'use strict' | ||
jsonFile.outputJson = u(require('./output-json')) | ||
jsonFile.outputJsonSync = require('./output-json-sync') | ||
jsonFile.outputJson = u(require('./output-json')) | ||
// aliases | ||
jsonFile.outputJSONSync = jsonFile.outputJSONSync | ||
jsonFile.outputJSON = jsonFile.outputJson | ||
jsonFile.outputJSONSync = jsonFile.outputJsonSync | ||
jsonFile.writeJSON = jsonFile.writeJson | ||
@@ -13,0 +13,0 @@ jsonFile.writeJSONSync = jsonFile.writeJsonSync |
@@ -16,3 +16,3 @@ 'use strict' | ||
function move (source, dest, options, callback) { | ||
function move (src, dest, options, callback) { | ||
if (typeof options === 'function') { | ||
@@ -23,12 +23,7 @@ callback = options | ||
const shouldMkdirp = ('mkdirp' in options) ? options.mkdirp : true | ||
const overwrite = options.overwrite || options.clobber || false | ||
if (shouldMkdirp) { | ||
mkdirs() | ||
} else { | ||
doRename() | ||
} | ||
function mkdirs () { | ||
isSrcSubdir(src, dest, (err, itIs) => { | ||
if (err) return callback(err) | ||
if (itIs) return callback(new Error(`Cannot move '${src}' to a subdirectory of itself, '${dest}'.`)) | ||
mkdirp(path.dirname(dest), err => { | ||
@@ -38,9 +33,9 @@ if (err) return callback(err) | ||
}) | ||
} | ||
}) | ||
function doRename () { | ||
if (path.resolve(source) === path.resolve(dest)) { | ||
fs.access(source, callback) | ||
if (path.resolve(src) === path.resolve(dest)) { | ||
fs.access(src, callback) | ||
} else if (overwrite) { | ||
fs.rename(source, dest, err => { | ||
fs.rename(src, dest, err => { | ||
if (!err) return callback() | ||
@@ -52,3 +47,3 @@ | ||
options.overwrite = false // just overwriteed it, no need to do it again | ||
move(source, dest, options, callback) | ||
move(src, dest, options, callback) | ||
}) | ||
@@ -64,3 +59,3 @@ return | ||
options.overwrite = false | ||
move(source, dest, options, callback) | ||
move(src, dest, options, callback) | ||
}) | ||
@@ -72,15 +67,13 @@ }, 200) | ||
if (err.code !== 'EXDEV') return callback(err) | ||
moveAcrossDevice(source, dest, overwrite, callback) | ||
moveAcrossDevice(src, dest, overwrite, callback) | ||
}) | ||
} else { | ||
fs.link(source, dest, err => { | ||
fs.link(src, dest, err => { | ||
if (err) { | ||
if (err.code === 'EXDEV' || err.code === 'EISDIR' || err.code === 'EPERM' || err.code === 'ENOTSUP') { | ||
moveAcrossDevice(source, dest, overwrite, callback) | ||
return | ||
return moveAcrossDevice(src, dest, overwrite, callback) | ||
} | ||
callback(err) | ||
return | ||
return callback(err) | ||
} | ||
fs.unlink(source, callback) | ||
return fs.unlink(src, callback) | ||
}) | ||
@@ -91,13 +84,10 @@ } | ||
function moveAcrossDevice (source, dest, overwrite, callback) { | ||
fs.stat(source, (err, stat) => { | ||
if (err) { | ||
callback(err) | ||
return | ||
} | ||
function moveAcrossDevice (src, dest, overwrite, callback) { | ||
fs.stat(src, (err, stat) => { | ||
if (err) return callback(err) | ||
if (stat.isDirectory()) { | ||
moveDirAcrossDevice(source, dest, overwrite, callback) | ||
moveDirAcrossDevice(src, dest, overwrite, callback) | ||
} else { | ||
moveFileAcrossDevice(source, dest, overwrite, callback) | ||
moveFileAcrossDevice(src, dest, overwrite, callback) | ||
} | ||
@@ -107,5 +97,5 @@ }) | ||
function moveFileAcrossDevice (source, dest, overwrite, callback) { | ||
function moveFileAcrossDevice (src, dest, overwrite, callback) { | ||
const flags = overwrite ? 'w' : 'wx' | ||
const ins = fs.createReadStream(source) | ||
const ins = fs.createReadStream(src) | ||
const outs = fs.createWriteStream(dest, { flags }) | ||
@@ -124,3 +114,3 @@ | ||
if (err.code === 'EISDIR' || err.code === 'EPERM') { | ||
moveDirAcrossDevice(source, dest, overwrite, callback) | ||
moveDirAcrossDevice(src, dest, overwrite, callback) | ||
} else { | ||
@@ -143,7 +133,7 @@ callback(err) | ||
function onClose () { | ||
fs.unlink(source, callback) | ||
fs.unlink(src, callback) | ||
} | ||
} | ||
function moveDirAcrossDevice (source, dest, overwrite, callback) { | ||
function moveDirAcrossDevice (src, dest, overwrite, callback) { | ||
const options = { | ||
@@ -163,5 +153,5 @@ overwrite: false | ||
function startNcp () { | ||
ncp(source, dest, options, err => { | ||
ncp(src, dest, options, err => { | ||
if (err) return callback(err) | ||
remove(source, callback) | ||
remove(src, callback) | ||
}) | ||
@@ -171,4 +161,22 @@ } | ||
// return true if dest is a subdir of src, otherwise false. | ||
// extract dest base dir and check if that is the same as src basename | ||
function isSrcSubdir (src, dest, cb) { | ||
fs.stat(src, (err, st) => { | ||
if (err) return cb(err) | ||
if (st.isDirectory()) { | ||
const baseDir = dest.split(path.dirname(src) + path.sep)[1] | ||
if (baseDir) { | ||
const destBasename = baseDir.split(path.sep)[0] | ||
if (destBasename) return cb(null, src !== dest && dest.indexOf(src) > -1 && destBasename === path.basename(src)) | ||
return cb(null, false) | ||
} | ||
return cb(null, false) | ||
} | ||
return cb(null, false) | ||
}) | ||
} | ||
module.exports = { | ||
move: u(move) | ||
} |
@@ -45,3 +45,3 @@ 'use strict' | ||
if (er) { | ||
if (isWindows && (er.code === 'EBUSY' || er.code === 'ENOTEMPTY' || er.code === 'EPERM') && | ||
if ((er.code === 'EBUSY' || er.code === 'ENOTEMPTY' || er.code === 'EPERM') && | ||
busyTries < options.maxBusyTries) { | ||
@@ -293,3 +293,21 @@ busyTries++ | ||
options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options)) | ||
options.rmdirSync(p, options) | ||
// We only end up here once we got ENOTEMPTY at least once, and | ||
// at this point, we are guaranteed to have removed all the kids. | ||
// So, we know that it won't be ENOENT or ENOTDIR or anything else. | ||
// try really hard to delete stuff on windows, because it has a | ||
// PROFOUNDLY annoying habit of not closing handles promptly when | ||
// files are deleted, resulting in spurious ENOTEMPTY errors. | ||
const retries = isWindows ? 100 : 1 | ||
let i = 0 | ||
do { | ||
let threw = true | ||
try { | ||
const ret = options.rmdirSync(p, options) | ||
threw = false | ||
return ret | ||
} finally { | ||
if (++i < retries && threw) continue // eslint-disable-line | ||
} | ||
} while (true) | ||
} | ||
@@ -296,0 +314,0 @@ |
{ | ||
"name": "fs-extra", | ||
"version": "3.0.1", | ||
"version": "4.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.", | ||
@@ -51,4 +51,5 @@ "homepage": "https://github.com/jprichardson/node-fs-extra", | ||
"secure-random": "^1.1.1", | ||
"semver": "^5.3.0", | ||
"standard": "^10.0.2", | ||
"standard-markdown": "^2.3.0" | ||
"standard-markdown": "^4.0.1" | ||
}, | ||
@@ -55,0 +56,0 @@ "main": "./lib/index", |
@@ -131,3 +131,3 @@ Node.js: fs-extra | ||
**NOTE:** You can still use the native Node.js methods. They are promisified and copied over to `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) | ||
@@ -145,3 +145,3 @@ ### What happened to `walk()` and `walkSync()`? | ||
If you like TypeScript, you can use `fs-extra` with it: https://github.com/borisyankov/DefinitelyTyped/tree/master/fs-extra | ||
If you like TypeScript, you can use `fs-extra` with it: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/fs-extra | ||
@@ -148,0 +148,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
139142
64
1628
13