Socket
Socket
Sign inDemoInstall

fs-extra

Package Overview
Dependencies
3
Maintainers
2
Versions
96
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.0 to 6.0.0

10

CHANGELOG.md

@@ -0,1 +1,11 @@

6.0.0 / 2018-05-01
------------------
- Drop support for Node.js versions 4, 5, & 7 ([#564](https://github.com/jprichardson/node-fs-extra/pull/564))
- Rewrite `move` to use `fs.rename` where possible ([#549](https://github.com/jprichardson/node-fs-extra/pull/549))
- Don't convert relative paths to absolute paths for `filter` ([#554](https://github.com/jprichardson/node-fs-extra/pull/554))
- `copy*`'s behavior when `preserveTimestamps` is `false` has been OS-dependent since 5.0.0, but that's now explicitly noted in the docs ([#563](https://github.com/jprichardson/node-fs-extra/pull/563))
- Fix subdirectory detection for `copy*` & `move*` ([#541](https://github.com/jprichardson/node-fs-extra/pull/541))
- Handle case-insensitive paths correctly in `copy*` ([#568](https://github.com/jprichardson/node-fs-extra/pull/568))
5.0.0 / 2017-12-11

@@ -2,0 +12,0 @@ ------------------

6

docs/copy-sync.md

@@ -5,4 +5,4 @@ # copySync(src, dest, [options])

- `src` `<String>`
- `dest` `<String>`
- `src` `<String>` Note that if `src` is a directory it will copy everything inside of this directory, not the entire directory itself (see [issue #537](https://github.com/jprichardson/node-fs-extra/issues/537)).
- `dest` `<String>` Note that if `src` is a file, `dest` cannot be a directory (see [issue #323](https://github.com/jprichardson/node-fs-extra/issues/323)).
- `options` `<Object>`

@@ -12,3 +12,3 @@ - `overwrite` `<boolean>`: overwrite existing file or directory, default is `true`. _Note that the copy operation will silently fail if you set this to `false` and the destination exists._ Use the `errorOnExist` option to change this behavior.

- `dereference` `<boolean>`: dereference symlinks, default is `false`.
- `preserveTimestamps` `<boolean>`: will set last modification and access times to the ones of the original source files, default is `false`.
- `preserveTimestamps` `<boolean>`: When true, will set last modification and access times to the ones of the original source files. When false, timestamp behavior is OS-dependent. Default is `false`.
- `filter` `<Function>`: Function to filter copied files. Return `true` to include, `false` to exclude.

@@ -15,0 +15,0 @@

@@ -5,3 +5,3 @@ # copy(src, dest, [options, callback])

- `src` `<String>`
- `src` `<String>` Note that if `src` is a directory it will copy everything inside of this directory, not the entire directory itself (see [issue #537](https://github.com/jprichardson/node-fs-extra/issues/537)).
- `dest` `<String>` Note that if `src` is a file, `dest` cannot be a directory (see [issue #323](https://github.com/jprichardson/node-fs-extra/issues/323)).

@@ -12,3 +12,3 @@ - `options` `<Object>`

- `dereference` `<boolean>`: dereference symlinks, default is `false`.
- `preserveTimestamps` `<boolean>`: will set last modification and access times to the ones of the original source files, default is `false`.
- `preserveTimestamps` `<boolean>`: When true, will set last modification and access times to the ones of the original source files. When false, timestamp behavior is OS-dependent. Default is `false`.
- `filter` `<Function>`: Function to filter copied files. Return `true` to include, `false` to exclude. Can also return a `Promise` that resolves to `true` or `false` (or pass in an `async` function).

@@ -22,2 +22,3 @@ - `callback` `<Function>`

// With a callback:
fs.copy('/tmp/myfile', '/tmp/mynewfile', err => {

@@ -35,3 +36,3 @@ if (err) return console.error(err)

// Promise usage:
// With Promises:
fs.copy('/tmp/myfile', '/tmp/mynewfile')

@@ -44,2 +45,14 @@ .then(() => {

})
// With async/await:
async function example () {
try {
await fs.copy('/tmp/myfile', '/tmp/mynewfile')
console.log('success!')
} catch (err) {
console.error(err)
}
}
example()
```

@@ -46,0 +59,0 @@

@@ -16,2 +16,3 @@ # emptyDir(dir, [callback])

// assume this directory has a lot of files and folders
// With a callback:
fs.emptyDir('/tmp/some/dir', err => {

@@ -23,3 +24,3 @@ if (err) return console.error(err)

// With promises
// With Promises:
fs.emptyDir('/tmp/some/dir')

@@ -32,2 +33,14 @@ .then(() => {

})
// With async/await:
async function example () {
try {
await fs.emptyDir('/tmp/some/dir')
console.log('success!')
} catch (err) {
console.error(err)
}
}
example()
```

@@ -16,2 +16,4 @@ # ensureDir(dir, [callback])

const dir = '/tmp/this/path/does/not/exist'
// With a callback:
fs.ensureDir(dir, err => {

@@ -30,2 +32,14 @@ console.log(err) // => null

})
// With async/await:
async function example (directory) {
try {
await fs.ensureDir(directory)
console.log('success!')
} catch (err) {
console.error(err)
}
}
example(dir)
```

@@ -16,2 +16,4 @@ # ensureFile(file, [callback])

const file = '/tmp/this/path/does/not/exist/file.txt'
// With a callback:
fs.ensureFile(file, err => {

@@ -30,2 +32,14 @@ console.log(err) // => null

})
// With async/await:
async function example (f) {
try {
await fs.ensureFile(f)
console.log('success!')
} catch (err) {
console.error(err)
}
}
example(file)
```

@@ -16,2 +16,4 @@ # ensureLink(srcpath, dstpath, [callback])

const dstpath = '/tmp/this/path/does/not/exist/file.txt'
// With a callback:
fs.ensureLink(srcpath, dstpath, err => {

@@ -30,2 +32,14 @@ console.log(err) // => null

})
// With async/await:
async function example (src, dest) {
try {
await fs.ensureLink(src, dest)
console.log('success!')
} catch (err) {
console.error(err)
}
}
example(srcpath, dstpath)
```

@@ -17,2 +17,4 @@ # ensureSymlink(srcpath, dstpath, [type, callback])

const dstpath = '/tmp/this/path/does/not/exist/file.txt'
// With a callback:
fs.ensureSymlink(srcpath, dstpath, err => {

@@ -31,2 +33,14 @@ console.log(err) // => null

})
// With async/await:
async function example (src, dest) {
try {
await fs.ensureSymlink(src, dest)
console.log('success!')
} catch (err) {
console.error(err)
}
}
example(srcpath, dstpath)
```

@@ -12,3 +12,3 @@ # About `fs.read()` & `fs.write()`

```js
// Basic promises
// With Promises:
fs.read(fd, buffer, offset, length, position)

@@ -20,3 +20,3 @@ .then(results => {

// Async/await usage:
// With async/await:
async function example () {

@@ -30,3 +30,3 @@ const { bytesRead, buffer } = await fs.read(fd, Buffer.alloc(length), offset, length, position)

```js
// Basic promises
// With Promises:
fs.write(fd, buffer, offset, length, position)

@@ -38,3 +38,3 @@ .then(results => {

// Async/await usage:
// With async/await:
async function example () {

@@ -41,0 +41,0 @@ const { bytesWritten, buffer } = await fs.write(fd, Buffer.alloc(length), offset, length, position)

@@ -16,3 +16,7 @@ # move(src, dest, [options, callback])

fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile', err => {
const srcpath = '/tmp/file.txt'
const dstpath = '/tmp/this/path/does/not/exist/file.txt'
// With a callback:
fs.move(srcpath, dstpath, err => {
if (err) return console.error(err)

@@ -23,3 +27,4 @@

fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile')
// With Promises:
fs.move(srcpath, dstpath)
.then(() => {

@@ -31,2 +36,14 @@ console.log('success!')

})
// With async/await:
async function example (src, dest) {
try {
await fs.move(srcpath, dstpath)
console.log('success!')
} catch (err) {
console.error(err)
}
}
example(srcpath, dstpath)
```

@@ -33,0 +50,0 @@

@@ -16,2 +16,4 @@ # outputFile(file, data, [options, callback])

const file = '/tmp/this/path/does/not/exist/file.txt'
// With a callback:
fs.outputFile(file, 'hello!', err => {

@@ -35,2 +37,17 @@ console.log(err) // => null

})
// With async/await:
async function example (f) {
try {
await fs.outputFile(f, 'hello!')
const data = await fs.readFile(f, 'utf8')
console.log(data) // => hello!
} catch (err) {
console.error(err)
}
}
example(file)
```

@@ -22,2 +22,4 @@ # outputJson(file, object, [options, callback])

const file = '/tmp/this/path/does/not/exist/file.json'
// With a callback:
fs.outputJson(file, {name: 'JP'}, err => {

@@ -41,2 +43,17 @@ console.log(err) // => null

})
// With async/await:
async function example (f) {
try {
await fs.outputJson(f, {name: 'JP'})
const data = await fs.readJson(f)
console.log(data.name) // => JP
} catch (err) {
console.error(err)
}
}
example(file)
```

@@ -14,10 +14,21 @@ # pathExists(file[, callback])

const file = '/tmp/this/path/does/not/exist/file.txt'
// With a callback:
fs.pathExists(file, (err, exists) => {
console.log(err) // => null
console.log(exists) // => false
})
// Promise usage:
fs.pathExists(file)
.then(exists => console.log(exists)) // => false
// Callback usage:
fs.pathExists(file, (err, exists) => {
console.log(err) // => null
// With async/await:
async function example (f) {
const exists = await fs.pathExists(f)
console.log(exists) // => false
})
}
example(file)
```

@@ -17,2 +17,3 @@ # readJson(file, [options, callback])

// With a callback:
fs.readJson('./package.json', (err, packageObj) => {

@@ -24,3 +25,3 @@ if (err) console.error(err)

// Promise Usage
// With Promises:
fs.readJson('./package.json')

@@ -33,2 +34,15 @@ .then(packageObj => {

})
// With async/await:
async function example () {
try {
const packageObj = await fs.readJson('./package.json')
console.log(packageObj.version) // => 0.1.3
} catch (err) {
console.error(err)
}
}
example()
```

@@ -47,2 +61,3 @@

// With a callback:
fs.readJson(file, { throws: false }, (err, obj) => {

@@ -54,3 +69,3 @@ if (err) console.error(err)

// Promise Usage
// Wtih Promises:
fs.readJson(file, { throws: false })

@@ -63,2 +78,11 @@ .then(obj => {

})
// With async/await:
async function example (f) {
const obj = await fs.readJson(f, { throws: false })
console.log(obj) // => null
}
example(file)
```

@@ -14,2 +14,3 @@ # remove(path, [callback])

// remove file
// With a callback:
fs.remove('/tmp/myfile', err => {

@@ -27,3 +28,3 @@ if (err) return console.error(err)

// Promise Usage
// With Promises:
fs.remove('/tmp/myfile')

@@ -36,2 +37,14 @@ .then(() => {

})
// With async/await:
async function example (src, dest) {
try {
await fs.remove('/tmp/myfile')
console.log('success!')
} catch (err) {
console.error(err)
}
}
example()
```

@@ -21,2 +21,3 @@ # writeJson(file, object, [options, callback])

// With a callback:
fs.writeJson('./package.json', {name: 'fs-extra'}, err => {

@@ -28,3 +29,3 @@ if (err) return console.error(err)

// With Promises
// With Promises:
fs.writeJson('./package.json', {name: 'fs-extra'})

@@ -37,2 +38,14 @@ .then(() => {

})
// With async/await:
async function example () {
try {
await fs.writeJson('./package.json', {name: 'fs-extra'})
console.log('success!')
} catch (err) {
console.error(err)
}
}
example()
```

@@ -39,0 +52,0 @@

@@ -26,8 +26,4 @@ 'use strict'

src = path.resolve(src)
dest = path.resolve(dest)
const resolvedDest = checkPaths(src, dest)
// don't allow src and dest to be the same
if (src === dest) throw new Error('Source and destination must not be the same.')
if (opts.filter && !opts.filter(src, dest)) return

@@ -37,31 +33,25 @@

if (!fs.existsSync(destParent)) mkdirpSync(destParent)
return startCopy(src, dest, opts)
return startCopy(resolvedDest, src, dest, opts)
}
function startCopy (src, dest, opts) {
function startCopy (resolvedDest, src, dest, opts) {
if (opts.filter && !opts.filter(src, dest)) return
return getStats(src, dest, opts)
return getStats(resolvedDest, src, dest, opts)
}
function getStats (src, dest, opts) {
function getStats (resolvedDest, src, dest, opts) {
const statSync = opts.dereference ? fs.statSync : fs.lstatSync
const st = statSync(src)
if (st.isDirectory()) return onDir(st, src, dest, opts)
if (st.isDirectory()) return onDir(st, resolvedDest, src, dest, opts)
else if (st.isFile() ||
st.isCharacterDevice() ||
st.isBlockDevice()) return onFile(st, src, dest, opts)
else if (st.isSymbolicLink()) return onLink(src, dest, opts)
st.isBlockDevice()) return onFile(st, resolvedDest, src, dest, opts)
else if (st.isSymbolicLink()) return onLink(resolvedDest, src, dest, opts)
}
function onFile (srcStat, src, dest, opts) {
const resolvedPath = checkDest(dest)
if (resolvedPath === notExist) {
return copyFile(srcStat, src, dest, opts)
} else if (resolvedPath === existsReg) {
return mayCopyFile(srcStat, src, dest, opts)
} else {
if (src === resolvedPath) return
return mayCopyFile(srcStat, src, dest, opts)
}
function onFile (srcStat, resolvedDest, src, dest, opts) {
if (resolvedDest === notExist) return copyFile(srcStat, src, dest, opts)
else if (resolvedDest === existsReg) return mayCopyFile(srcStat, src, dest, opts)
return mayCopyFile(srcStat, src, dest, opts)
}

@@ -96,7 +86,6 @@

const fdw = fs.openSync(dest, 'w', srcStat.mode)
let bytesRead = 1
let pos = 0
while (bytesRead > 0) {
bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
while (pos < srcStat.size) {
const bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
fs.writeSync(fdw, _buff, 0, bytesRead)

@@ -112,5 +101,4 @@ pos += bytesRead

function onDir (srcStat, src, dest, opts) {
const resolvedPath = checkDest(dest)
if (resolvedPath === notExist) {
function onDir (srcStat, resolvedDest, src, dest, opts) {
if (resolvedDest === notExist) {
if (isSrcSubdir(src, dest)) {

@@ -120,3 +108,3 @@ throw new Error(`Cannot copy '${src}' to a subdirectory of itself, '${dest}'.`)

return mkDirAndCopy(srcStat, src, dest, opts)
} else if (resolvedPath === existsReg) {
} else if (resolvedDest === existsReg) {
if (isSrcSubdir(src, dest)) {

@@ -126,6 +114,4 @@ throw new Error(`Cannot copy '${src}' to a subdirectory of itself, '${dest}'.`)

return mayCopyDir(src, dest, opts)
} else {
if (src === resolvedPath) return
return copyDir(src, dest, opts)
}
return copyDir(src, dest, opts)
}

@@ -147,24 +133,28 @@

function copyDir (src, dest, opts) {
fs.readdirSync(src).forEach(item => {
startCopy(path.join(src, item), path.join(dest, item), opts)
})
fs.readdirSync(src).forEach(item => copyDirItem(item, src, dest, opts))
}
function onLink (src, dest, opts) {
let resolvedSrcPath = fs.readlinkSync(src)
function copyDirItem (item, src, dest, opts) {
const srcItem = path.join(src, item)
const destItem = path.join(dest, item)
const resolvedDest = checkPaths(srcItem, destItem)
return startCopy(resolvedDest, srcItem, destItem, opts)
}
function onLink (resolvedDest, src, dest, opts) {
let resolvedSrc = fs.readlinkSync(src)
if (opts.dereference) {
resolvedSrcPath = path.resolve(process.cwd(), resolvedSrcPath)
resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
}
let resolvedDestPath = checkDest(dest)
if (resolvedDestPath === notExist || resolvedDestPath === existsReg) {
if (resolvedDest === notExist || resolvedDest === existsReg) {
// if dest already exists, fs throws error anyway,
// so no need to guard against it here.
return fs.symlinkSync(resolvedSrcPath, dest)
return fs.symlinkSync(resolvedSrc, dest)
} else {
if (opts.dereference) {
resolvedDestPath = path.resolve(process.cwd(), resolvedDestPath)
resolvedDest = path.resolve(process.cwd(), resolvedDest)
}
if (resolvedDestPath === resolvedSrcPath) return
if (pathsAreIdentical(resolvedSrc, resolvedDest)) return

@@ -174,15 +164,26 @@ // prevent copy if src is a subdir of dest since unlinking

// and therefore a broken symlink would be created.
if (fs.statSync(dest).isDirectory() && isSrcSubdir(resolvedDestPath, resolvedSrcPath)) {
throw new Error(`Cannot overwrite '${resolvedDestPath}' with '${resolvedSrcPath}'.`)
if (fs.statSync(dest).isDirectory() && isSrcSubdir(resolvedDest, resolvedSrc)) {
throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
}
return copyLink(resolvedSrcPath, dest)
return copyLink(resolvedSrc, dest)
}
}
function copyLink (resolvedSrcPath, dest) {
function copyLink (resolvedSrc, dest) {
fs.unlinkSync(dest)
return fs.symlinkSync(resolvedSrcPath, dest)
return fs.symlinkSync(resolvedSrc, dest)
}
// check if dest exists and/or is a symlink
// 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) {
const srcArray = path.resolve(src).split(path.sep)
const destArray = path.resolve(dest).split(path.sep)
return srcArray.reduce((acc, current, i) => {
return acc && destArray[i] === current
}, true)
}
// check if dest exists and is a symlink.
function checkDest (dest) {

@@ -195,3 +196,3 @@ let resolvedPath

// dest exists and is a regular file or directory, Windows may throw UNKNOWN error
// dest exists and is a regular file or directory, Windows may throw UNKNOWN error.
if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return existsReg

@@ -204,16 +205,25 @@

// 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) {
const baseDir = dest.split(path.dirname(src) + path.sep)[1]
if (baseDir) {
const destBasename = baseDir.split(path.sep)[0]
if (destBasename) {
return src !== dest && dest.indexOf(src) > -1 && destBasename === path.basename(src)
}
return false
function pathsAreIdentical (src, dest) {
const os = process.platform
const resolvedSrc = path.resolve(src)
const resolvedDest = path.resolve(dest)
// case-insensitive paths
if (os === 'darwin' || os === 'win32') {
return resolvedSrc.toLowerCase() === resolvedDest.toLowerCase()
}
return false
return resolvedSrc === resolvedDest
}
function checkPaths (src, dest) {
const resolvedDest = checkDest(dest)
if (resolvedDest === notExist || resolvedDest === existsReg) {
if (pathsAreIdentical(src, dest)) throw new Error('Source and destination must not be the same.')
return resolvedDest
} else {
// check resolved dest path if dest is a symlink
if (pathsAreIdentical(src, resolvedDest)) throw new Error('Source and destination must not be the same.')
return resolvedDest
}
}
module.exports = copySync

@@ -0,3 +1,5 @@

'use strict'
module.exports = {
copySync: require('./copy-sync')
}

@@ -32,20 +32,17 @@ 'use strict'

src = path.resolve(src)
dest = path.resolve(dest)
// don't allow src and dest to be the same
if (src === dest) return cb(new Error('Source and destination must not be the same.'))
if (opts.filter) return handleFilter(checkParentDir, src, dest, opts, cb)
return checkParentDir(src, dest, opts, cb)
checkPaths(src, dest, (err, resolvedDest) => {
if (err) return cb(err)
if (opts.filter) return handleFilter(checkParentDir, resolvedDest, src, dest, opts, cb)
return checkParentDir(resolvedDest, src, dest, opts, cb)
})
}
function checkParentDir (src, dest, opts, cb) {
function checkParentDir (resolvedDest, src, dest, opts, cb) {
const destParent = path.dirname(dest)
pathExists(destParent, (err, dirExists) => {
if (err) return cb(err)
if (dirExists) return startCopy(src, dest, opts, cb)
if (dirExists) return startCopy(resolvedDest, src, dest, opts, cb)
mkdirp(destParent, err => {
if (err) return cb(err)
return startCopy(src, dest, opts, cb)
return startCopy(resolvedDest, src, dest, opts, cb)
})

@@ -55,16 +52,18 @@ })

function startCopy (src, dest, opts, cb) {
if (opts.filter) return handleFilter(getStats, src, dest, opts, cb)
return getStats(src, dest, opts, cb)
function startCopy (resolvedDest, src, dest, opts, cb) {
if (opts.filter) return handleFilter(getStats, resolvedDest, src, dest, opts, cb)
return getStats(resolvedDest, src, dest, opts, cb)
}
function handleFilter (onInclude, src, dest, opts, cb) {
Promise.resolve(opts.filter(src, dest))
.then(include => {
if (include) return onInclude(src, dest, opts, cb)
return cb()
}, error => cb(error))
function handleFilter (onInclude, resolvedDest, src, dest, opts, cb) {
Promise.resolve(opts.filter(src, dest)).then(include => {
if (include) {
if (resolvedDest) return onInclude(resolvedDest, src, dest, opts, cb)
return onInclude(src, dest, opts, cb)
}
return cb()
}, error => cb(error))
}
function getStats (src, dest, opts, cb) {
function getStats (resolvedDest, src, dest, opts, cb) {
const stat = opts.dereference ? fs.stat : fs.lstat

@@ -74,22 +73,14 @@ stat(src, (err, st) => {

if (st.isDirectory()) return onDir(st, src, dest, opts, cb)
if (st.isDirectory()) return onDir(st, resolvedDest, src, dest, opts, cb)
else if (st.isFile() ||
st.isCharacterDevice() ||
st.isBlockDevice()) return onFile(st, src, dest, opts, cb)
else if (st.isSymbolicLink()) return onLink(src, dest, opts, cb)
st.isBlockDevice()) return onFile(st, resolvedDest, src, dest, opts, cb)
else if (st.isSymbolicLink()) return onLink(resolvedDest, src, dest, opts, cb)
})
}
function onFile (srcStat, src, dest, opts, cb) {
checkDest(dest, (err, resolvedPath) => {
if (err) return cb(err)
if (resolvedPath === notExist) {
return copyFile(srcStat, src, dest, opts, cb)
} else if (resolvedPath === existsReg) {
return mayCopyFile(srcStat, src, dest, opts, cb)
} else {
if (src === resolvedPath) return cb()
return mayCopyFile(srcStat, src, dest, opts, cb)
}
})
function onFile (srcStat, resolvedDest, src, dest, opts, cb) {
if (resolvedDest === notExist) return copyFile(srcStat, src, dest, opts, cb)
else if (resolvedDest === existsReg) return mayCopyFile(srcStat, src, dest, opts, cb)
return mayCopyFile(srcStat, src, dest, opts, cb)
}

@@ -120,9 +111,8 @@

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))
})
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))
})
}

@@ -140,20 +130,15 @@

function onDir (srcStat, src, dest, opts, cb) {
checkDest(dest, (err, resolvedPath) => {
if (err) return cb(err)
if (resolvedPath === notExist) {
if (isSrcSubdir(src, dest)) {
return cb(new Error(`Cannot copy '${src}' to a subdirectory of itself, '${dest}'.`))
}
return mkDirAndCopy(srcStat, src, dest, opts, cb)
} else if (resolvedPath === existsReg) {
if (isSrcSubdir(src, dest)) {
return cb(new Error(`Cannot copy '${src}' to a subdirectory of itself, '${dest}'.`))
}
return mayCopyDir(src, dest, opts, cb)
} else {
if (src === resolvedPath) return cb()
return copyDir(src, dest, opts, cb)
function onDir (srcStat, resolvedDest, src, dest, opts, cb) {
if (resolvedDest === notExist) {
if (isSrcSubdir(src, dest)) {
return cb(new Error(`Cannot copy '${src}' to a subdirectory of itself, '${dest}'.`))
}
})
return mkDirAndCopy(srcStat, src, dest, opts, cb)
} else if (resolvedDest === existsReg) {
if (isSrcSubdir(src, dest)) {
return cb(new Error(`Cannot copy '${src}' to a subdirectory of itself, '${dest}'.`))
}
return mayCopyDir(src, dest, opts, cb)
}
return copyDir(src, dest, opts, cb)
}

@@ -191,52 +176,68 @@

if (!item) return cb()
startCopy(path.join(src, item), path.join(dest, item), opts, err => {
return copyDirItem(items, item, src, dest, opts, cb)
}
function copyDirItem (items, item, src, dest, opts, cb) {
const srcItem = path.join(src, item)
const destItem = path.join(dest, item)
checkPaths(srcItem, destItem, (err, resolvedDest) => {
if (err) return cb(err)
return copyDirItems(items, src, dest, opts, cb)
startCopy(resolvedDest, srcItem, destItem, opts, err => {
if (err) return cb(err)
return copyDirItems(items, src, dest, opts, cb)
})
})
}
function onLink (src, dest, opts, cb) {
fs.readlink(src, (err, resolvedSrcPath) => {
function onLink (resolvedDest, src, dest, opts, cb) {
fs.readlink(src, (err, resolvedSrc) => {
if (err) return cb(err)
if (opts.dereference) {
resolvedSrcPath = path.resolve(process.cwd(), resolvedSrcPath)
resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
}
checkDest(dest, (err, resolvedDestPath) => {
if (err) return cb(err)
if (resolvedDest === notExist || resolvedDest === existsReg) {
// if dest already exists, fs throws error anyway,
// so no need to guard against it here.
return fs.symlink(resolvedSrc, dest, cb)
} else {
if (opts.dereference) {
resolvedDest = path.resolve(process.cwd(), resolvedDest)
}
if (pathsAreIdentical(resolvedSrc, resolvedDest)) return cb()
if (resolvedDestPath === notExist || resolvedDestPath === existsReg) {
// if dest already exists, fs throws error anyway,
// so no need to guard against it here.
return fs.symlink(resolvedSrcPath, dest, cb)
} else {
if (opts.dereference) {
resolvedDestPath = path.resolve(process.cwd(), resolvedDestPath)
// prevent copy if src is a subdir of dest since unlinking
// dest in this case would result in removing src contents
// and therefore a broken symlink would be created.
fs.stat(dest, (err, st) => {
if (err) return cb(err)
if (st.isDirectory() && isSrcSubdir(resolvedDest, resolvedSrc)) {
return cb(new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`))
}
if (resolvedDestPath === resolvedSrcPath) return cb()
// prevent copy if src is a subdir of dest since unlinking
// dest in this case would result in removing src contents
// and therefore a broken symlink would be created.
fs.stat(dest, (err, st) => {
if (err) return cb(err)
if (st.isDirectory() && isSrcSubdir(resolvedDestPath, resolvedSrcPath)) {
return cb(new Error(`Cannot overwrite '${resolvedDestPath}' with '${resolvedSrcPath}'.`))
}
return copyLink(resolvedSrcPath, dest, cb)
})
}
})
return copyLink(resolvedSrc, dest, cb)
})
}
})
}
function copyLink (resolvedSrcPath, dest, cb) {
function copyLink (resolvedSrc, dest, cb) {
fs.unlink(dest, err => {
if (err) return cb(err)
return fs.symlink(resolvedSrcPath, dest, cb)
return fs.symlink(resolvedSrc, dest, cb)
})
}
// check if dest exists and/or is a symlink
// 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) {
const srcArray = path.resolve(src).split(path.sep)
const destArray = path.resolve(dest).split(path.sep)
return srcArray.reduce((acc, current, i) => {
return acc && destArray[i] === current
}, true)
}
// check if dest exists and is a symlink.
function checkDest (dest, cb) {

@@ -256,16 +257,27 @@ fs.readlink(dest, (err, resolvedPath) => {

// 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) {
const baseDir = dest.split(path.dirname(src) + path.sep)[1]
if (baseDir) {
const destBasename = baseDir.split(path.sep)[0]
if (destBasename) {
return src !== dest && dest.indexOf(src) > -1 && destBasename === path.basename(src)
}
return false
function pathsAreIdentical (src, dest) {
const os = process.platform
const resolvedSrc = path.resolve(src)
const resolvedDest = path.resolve(dest)
// case-insensitive paths
if (os === 'darwin' || os === 'win32') {
return resolvedSrc.toLowerCase() === resolvedDest.toLowerCase()
}
return false
return resolvedSrc === resolvedDest
}
function checkPaths (src, dest, cb) {
checkDest(dest, (err, resolvedDest) => {
if (err) return cb(err)
if (resolvedDest === notExist || resolvedDest === existsReg) {
if (pathsAreIdentical(src, dest)) return cb(new Error('Source and destination must not be the same.'))
return cb(null, resolvedDest)
} else {
// check resolved dest path if dest is a symlink
if (pathsAreIdentical(src, resolvedDest)) return cb(new Error('Source and destination must not be the same.'))
return cb(null, resolvedDest)
}
})
}
module.exports = copy

@@ -0,1 +1,3 @@

'use strict'
const u = require('universalify').fromCallback

@@ -2,0 +4,0 @@ module.exports = {

@@ -20,3 +20,3 @@ 'use strict'

if (destinationExists) return callback(null)
fs.lstat(srcpath, (err, stat) => {
fs.lstat(srcpath, (err) => {
if (err) {

@@ -40,3 +40,3 @@ err.message = err.message.replace('lstat', 'ensureLink')

function createLinkSync (srcpath, dstpath, callback) {
function createLinkSync (srcpath, dstpath) {
const destinationExists = fs.existsSync(dstpath)

@@ -43,0 +43,0 @@ if (destinationExists) return undefined

@@ -31,3 +31,3 @@ 'use strict'

if (path.isAbsolute(srcpath)) {
return fs.lstat(srcpath, (err, stat) => {
return fs.lstat(srcpath, (err) => {
if (err) {

@@ -53,3 +53,3 @@ err.message = err.message.replace('lstat', 'ensureSymlink')

} else {
return fs.lstat(srcpath, (err, stat) => {
return fs.lstat(srcpath, (err) => {
if (err) {

@@ -56,0 +56,0 @@ err.message = err.message.replace('lstat', 'ensureSymlink')

@@ -46,6 +46,3 @@ 'use strict'

function createSymlinkSync (srcpath, dstpath, type, callback) {
callback = (typeof type === 'function') ? type : callback
type = (typeof type === 'function') ? false : type
function createSymlinkSync (srcpath, dstpath, type) {
const destinationExists = fs.existsSync(dstpath)

@@ -52,0 +49,0 @@ if (destinationExists) return undefined

@@ -0,1 +1,2 @@

'use strict'
// This is adapted from https://github.com/normalize/mz

@@ -85,20 +86,10 @@ // Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors

// 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)
// We need to handle both cases, so we use ...args
exports.write = function (fd, buffer, ...args) {
if (typeof args[args.length - 1] === 'function') {
return fs.write(fd, buffer, ...args)
}
// 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) => {
fs.write(fd, buffer, ...args, (err, bytesWritten, buffer) => {
if (err) return reject(err)

@@ -105,0 +96,0 @@ resolve({ bytesWritten, buffer })

'use strict'
const assign = require('./util/assign')
const fs = {}
// Export graceful-fs:
assign(fs, require('./fs'))
// Export extra methods:
assign(fs, require('./copy'))
assign(fs, require('./copy-sync'))
assign(fs, require('./mkdirs'))
assign(fs, require('./remove'))
assign(fs, require('./json'))
assign(fs, require('./move'))
assign(fs, require('./move-sync'))
assign(fs, require('./empty'))
assign(fs, require('./ensure'))
assign(fs, require('./output'))
assign(fs, require('./path-exists'))
module.exports = fs
module.exports = Object.assign(
{},
// Export promiseified graceful-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')
)

@@ -7,4 +7,4 @@ 'use strict'

module.exports = {
mkdirs: mkdirs,
mkdirsSync: mkdirsSync,
mkdirs,
mkdirsSync,
// alias

@@ -11,0 +11,0 @@ mkdirp: mkdirs,

@@ -34,21 +34,16 @@ 'use strict'

} catch (err0) {
switch (err0.code) {
case 'ENOENT':
if (path.dirname(p) === p) throw err0
made = mkdirsSync(path.dirname(p), opts, made)
mkdirsSync(p, opts, made)
break
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
let stat
try {
stat = xfs.statSync(p)
} catch (err1) {
throw err0
}
if (!stat.isDirectory()) throw err0
break
if (err0.code === 'ENOENT') {
if (path.dirname(p) === p) throw err0
made = mkdirsSync(path.dirname(p), opts, made)
mkdirsSync(p, opts, made)
} else {
// In the case of any other error, just see if there's a dir there
// already. If so, then hooray! If not, then something is borked.
let stat
try {
stat = xfs.statSync(p)
} catch (err1) {
throw err0
}
if (!stat.isDirectory()) throw err0
}

@@ -55,0 +50,0 @@ }

@@ -71,7 +71,6 @@ 'use strict'

const fdw = fs.openSync(dest, flags, stat.mode)
let bytesRead = 1
let pos = 0
while (bytesRead > 0) {
bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
while (pos < stat.size) {
const bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
fs.writeSync(fdw, _buff, 0, bytesRead)

@@ -78,0 +77,0 @@ pos += bytesRead

'use strict'
// most of this code was written by Andrew Kelley
// licensed under the BSD license: see
// https://github.com/andrewrk/node-mv/blob/master/package.json
// this needs a cleanup
const u = require('universalify').fromCallback
const fs = require('graceful-fs')
const copy = require('../copy/copy')
const path = require('path')
const copy = require('../copy').copy
const remove = require('../remove').remove
const mkdirp = require('../mkdirs').mkdirs
const mkdirp = require('../mkdirs').mkdirp
const pathExists = require('../path-exists').pathExists
function move (src, dest, options, callback) {
if (typeof options === 'function') {
callback = options
options = {}
function move (src, dest, opts, cb) {
if (typeof opts === 'function') {
cb = opts
opts = {}
}
const overwrite = options.overwrite || options.clobber || false
const overwrite = opts.overwrite || opts.clobber || false
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 => {
if (err) return callback(err)
doRename()
})
})
src = path.resolve(src)
dest = path.resolve(dest)
function doRename () {
if (path.resolve(src) === path.resolve(dest)) {
fs.access(src, callback)
} else if (overwrite) {
fs.rename(src, dest, err => {
if (!err) return callback()
if (src === dest) return fs.access(src, cb)
if (err.code === 'ENOTEMPTY' || err.code === 'EEXIST') {
remove(dest, err => {
if (err) return callback(err)
options.overwrite = false // just overwriteed it, no need to do it again
move(src, dest, options, callback)
})
return
}
fs.stat(src, (err, st) => {
if (err) return cb(err)
// weird Windows shit
if (err.code === 'EPERM') {
setTimeout(() => {
remove(dest, err => {
if (err) return callback(err)
options.overwrite = false
move(src, dest, options, callback)
})
}, 200)
return
}
if (err.code !== 'EXDEV') return callback(err)
moveAcrossDevice(src, dest, overwrite, callback)
})
} else {
fs.link(src, dest, err => {
if (err) {
if (err.code === 'EXDEV' || err.code === 'EISDIR' || err.code === 'EPERM' || err.code === 'ENOTSUP') {
return moveAcrossDevice(src, dest, overwrite, callback)
}
return callback(err)
}
return fs.unlink(src, callback)
})
if (st.isDirectory() && isSrcSubdir(src, dest)) {
return cb(new Error(`Cannot move '${src}' to a subdirectory of itself, '${dest}'.`))
}
}
}
function moveAcrossDevice (src, dest, overwrite, callback) {
fs.stat(src, (err, stat) => {
if (err) return callback(err)
if (stat.isDirectory()) {
moveDirAcrossDevice(src, dest, overwrite, callback)
} else {
moveFileAcrossDevice(src, dest, overwrite, callback)
}
mkdirp(path.dirname(dest), err => {
if (err) return cb(err)
return doRename(src, dest, overwrite, cb)
})
})
}
function moveFileAcrossDevice (src, dest, overwrite, callback) {
const flags = overwrite ? 'w' : 'wx'
const ins = fs.createReadStream(src)
const outs = fs.createWriteStream(dest, { flags })
ins.on('error', err => {
ins.destroy()
outs.destroy()
outs.removeListener('close', onClose)
// may want to create a directory but `out` line above
// creates an empty file for us: See #108
// don't care about error here
fs.unlink(dest, () => {
// note: `err` here is from the input stream errror
if (err.code === 'EISDIR' || err.code === 'EPERM') {
moveDirAcrossDevice(src, dest, overwrite, callback)
} else {
callback(err)
}
function doRename (src, dest, overwrite, cb) {
if (overwrite) {
return remove(dest, err => {
if (err) return cb(err)
return rename(src, dest, overwrite, cb)
})
}
pathExists(dest, (err, destExists) => {
if (err) return cb(err)
if (destExists) return cb(new Error('dest already exists.'))
return rename(src, dest, overwrite, cb)
})
}
outs.on('error', err => {
ins.destroy()
outs.destroy()
outs.removeListener('close', onClose)
callback(err)
function rename (src, dest, overwrite, cb) {
fs.rename(src, dest, err => {
if (!err) return cb()
if (err.code !== 'EXDEV') return cb(err)
return moveAcrossDevice(src, dest, overwrite, cb)
})
outs.once('close', onClose)
ins.pipe(outs)
function onClose () {
fs.unlink(src, callback)
}
}
function moveDirAcrossDevice (src, dest, overwrite, callback) {
const options = {
overwrite: false
function moveAcrossDevice (src, dest, overwrite, cb) {
const opts = {
overwrite,
errorOnExist: true
}
if (overwrite) {
remove(dest, err => {
if (err) return callback(err)
startCopy()
})
} else {
startCopy()
}
function startCopy () {
copy(src, dest, options, err => {
if (err) return callback(err)
remove(src, callback)
})
}
}
// 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) => {
copy(src, dest, opts, err => {
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)
return remove(src, cb)
})
}
function isSrcSubdir (src, dest) {
const srcArray = src.split(path.sep)
const destArray = dest.split(path.sep)
return srcArray.reduce((acc, current, i) => {
return acc && destArray[i] === current
}, true)
}
module.exports = {
move: u(move)
}

@@ -28,9 +28,9 @@ 'use strict'

function outputFileSync (file, data, encoding) {
function outputFileSync (file, ...args) {
const dir = path.dirname(file)
if (fs.existsSync(dir)) {
return fs.writeFileSync.apply(fs, arguments)
return fs.writeFileSync(file, ...args)
}
mkdir.mkdirsSync(dir)
fs.writeFileSync.apply(fs, arguments)
fs.writeFileSync(file, ...args)
}

@@ -37,0 +37,0 @@

@@ -36,6 +36,6 @@ 'use strict'

assert(p, 'rimraf: missing path')
assert.equal(typeof p, 'string', 'rimraf: path should be a string')
assert.equal(typeof cb, 'function', 'rimraf: callback function required')
assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
assert.strictEqual(typeof cb, 'function', 'rimraf: callback function required')
assert(options, 'rimraf: invalid options argument provided')
assert.equal(typeof options, 'object', 'rimraf: options should be object')
assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')

@@ -49,3 +49,3 @@ defaults(options)

busyTries++
let time = busyTries * 100
const time = busyTries * 100
// try again, with the same exact callback as this one.

@@ -234,5 +234,5 @@ return setTimeout(() => rimraf_(p, options, CB), time)

assert(p, 'rimraf: missing path')
assert.equal(typeof p, 'string', 'rimraf: path should be a string')
assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
assert(options, 'rimraf: missing options')
assert.equal(typeof options, 'object', 'rimraf: options should be object')
assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')

@@ -239,0 +239,0 @@ try {

@@ -0,1 +1,2 @@

'use strict'
/* eslint-disable node/no-deprecated-api */

@@ -2,0 +3,0 @@ module.exports = function (size) {

{
"name": "fs-extra",
"version": "5.0.0",
"version": "6.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.",

@@ -41,9 +41,9 @@ "homepage": "https://github.com/jprichardson/node-fs-extra",

"devDependencies": {
"coveralls": "^2.11.2",
"coveralls": "^3.0.0",
"istanbul": "^0.4.5",
"klaw": "^1.0.0",
"klaw-sync": "^1.1.2",
"klaw": "^2.1.1",
"klaw-sync": "^3.0.2",
"minimist": "^1.1.1",
"mocha": "^3.1.2",
"proxyquire": "^1.7.10",
"mocha": "^5.0.5",
"proxyquire": "^2.0.1",
"read-dir-files": "^0.1.1",

@@ -53,3 +53,3 @@ "rimraf": "^2.2.8",

"semver": "^5.3.0",
"standard": "^10.0.2",
"standard": "^11.0.1",
"standard-markdown": "^4.0.1"

@@ -59,2 +59,3 @@ },

"scripts": {
"full-ci": "npm run lint && npm run coverage",
"coverage": "istanbul cover -i 'lib/**' -x '**/__tests__/**' test.js",

@@ -61,0 +62,0 @@ "coveralls": "coveralls < coverage/lcov.info",

Node.js: fs-extra
=================
`fs-extra` adds file system methods that aren't included in the native `fs` module and adds promise support to the `fs` methods. It should be a drop in replacement for `fs`.
`fs-extra` adds file system methods that aren't included in the native `fs` module and adds promise support to the `fs` methods. It also uses [`graceful-fs`](https://github.com/isaacs/node-graceful-fs) to prevent `EMFILE` errors. It should be a drop in replacement for `fs`.
[![npm Package](https://img.shields.io/npm/v/fs-extra.svg?style=flat-square)](https://www.npmjs.org/package/fs-extra)
[![build status](https://api.travis-ci.org/jprichardson/node-fs-extra.svg)](http://travis-ci.org/jprichardson/node-fs-extra)
[![npm Package](https://img.shields.io/npm/v/fs-extra.svg)](https://www.npmjs.org/package/fs-extra)
[![License](https://img.shields.io/npm/l/express.svg)](https://github.com/jprichardson/node-fs-extra/blob/master/LICENSE)
[![build status](https://img.shields.io/travis/jprichardson/node-fs-extra/master.svg)](http://travis-ci.org/jprichardson/node-fs-extra)
[![windows Build status](https://img.shields.io/appveyor/ci/jprichardson/node-fs-extra/master.svg?label=windows%20build)](https://ci.appveyor.com/project/jprichardson/node-fs-extra/branch/master)
[![downloads per month](http://img.shields.io/npm/dm/fs-extra.svg)](https://www.npmjs.org/package/fs-extra)
[![Coverage Status](https://img.shields.io/coveralls/jprichardson/node-fs-extra.svg)](https://coveralls.io/r/jprichardson/node-fs-extra)
[![Coverage Status](https://img.shields.io/coveralls/github/jprichardson/node-fs-extra/master.svg)](https://coveralls.io/github/jprichardson/node-fs-extra)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
<a href="https://github.com/feross/standard"><img src="https://cdn.rawgit.com/feross/standard/master/sticker.svg" alt="Standard JavaScript" width="100"></a>
Why?

@@ -61,3 +60,3 @@ ----

Sync vs Async
Sync vs Async vs Async/Await
-------------

@@ -68,2 +67,4 @@ Most methods are async by default. All async methods will return a promise if the callback isn't passed.

Also Async/Await will throw an error if one occurs.
Example:

@@ -92,2 +93,14 @@

}
// Async/Await:
async function copyFiles () {
try {
await fs.copy('/tmp/myfile', '/tmp/mynewfile')
console.log('success!')
} catch (err) {
console.error(err)
}
}
copyFiles()
```

@@ -154,5 +167,9 @@

### Obtain Filesystem (Devices, Partitions) Information
[fs-filesystem](https://github.com/arthurintelligence/node-fs-filesystem) allows you to read the state of the filesystem of the host on which it is run. It returns information about both the devices and the partitions (volumes) of the system.
### Misc.
- [fs-extra-debug](https://github.com/jdxcode/fs-extra-debug) - Send your fs-extra calls to [debug](https://npmjs.org/package/debug).
- [mfs](https://github.com/cadorn/mfs) - Monitor your fs-extra calls.

@@ -159,0 +176,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc