diff options
Diffstat (limited to 'node_modules/fs-extra/lib')
30 files changed, 1989 insertions, 0 deletions
diff --git a/node_modules/fs-extra/lib/copy-sync/copy-sync.js b/node_modules/fs-extra/lib/copy-sync/copy-sync.js new file mode 100644 index 0000000..c4742db --- /dev/null +++ b/node_modules/fs-extra/lib/copy-sync/copy-sync.js @@ -0,0 +1,209 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const mkdirpSync = require('../mkdirs').mkdirsSync +const utimesSync = require('../util/utimes.js').utimesMillisSync + +const notExist = Symbol('notExist') +const existsReg = Symbol('existsReg') + +function copySync (src, dest, opts) { + if (typeof opts === 'function') { + opts = {filter: opts} + } + + opts = opts || {} + opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now + opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber + + // Warn about using preserveTimestamps on 32-bit node + if (opts.preserveTimestamps && process.arch === 'ia32') { + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n + see https://github.com/jprichardson/node-fs-extra/issues/269`) + } + + src = path.resolve(src) + dest = path.resolve(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 + + const destParent = path.dirname(dest) + if (!fs.existsSync(destParent)) mkdirpSync(destParent) + return startCopy(src, dest, opts) +} + +function startCopy (src, dest, opts) { + if (opts.filter && !opts.filter(src, dest)) return + return getStats(src, dest, opts) +} + +function getStats (src, dest, opts) { + const statSync = opts.dereference ? fs.statSync : fs.lstatSync + const st = statSync(src) + + if (st.isDirectory()) return onDir(st, 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) +} + +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 mayCopyFile (srcStat, src, dest, opts) { + if (opts.overwrite) { + fs.unlinkSync(dest) + return copyFile(srcStat, src, dest, opts) + } else if (opts.errorOnExist) { + throw new Error(`'${dest}' already exists`) + } +} + +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) +} + +function copyFileFallback (srcStat, src, dest, opts) { + const BUF_LENGTH = 64 * 1024 + const _buff = require('../util/buffer')(BUF_LENGTH) + + const fdr = fs.openSync(src, 'r') + 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) + fs.writeSync(fdw, _buff, 0, bytesRead) + pos += bytesRead + } + + if (opts.preserveTimestamps) fs.futimesSync(fdw, srcStat.atime, srcStat.mtime) + + fs.closeSync(fdr) + fs.closeSync(fdw) +} + +function onDir (srcStat, src, dest, opts) { + const resolvedPath = checkDest(dest) + if (resolvedPath === notExist) { + if (isSrcSubdir(src, dest)) { + throw new Error(`Cannot copy '${src}' to a subdirectory of itself, '${dest}'.`) + } + return mkDirAndCopy(srcStat, src, dest, opts) + } else if (resolvedPath === existsReg) { + if (isSrcSubdir(src, dest)) { + 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) + } +} + +function mayCopyDir (src, dest, opts) { + if (!fs.statSync(dest).isDirectory()) { + throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`) + } + return copyDir(src, dest, opts) +} + +function mkDirAndCopy (srcStat, src, dest, opts) { + fs.mkdirSync(dest, srcStat.mode) + fs.chmodSync(dest, srcStat.mode) + return copyDir(src, dest, opts) +} + +function copyDir (src, dest, opts) { + fs.readdirSync(src).forEach(item => { + startCopy(path.join(src, item), path.join(dest, item), opts) + }) +} + +function onLink (src, dest, opts) { + let resolvedSrcPath = fs.readlinkSync(src) + + if (opts.dereference) { + resolvedSrcPath = path.resolve(process.cwd(), resolvedSrcPath) + } + + let resolvedDestPath = checkDest(dest) + if (resolvedDestPath === notExist || resolvedDestPath === existsReg) { + // if dest already exists, fs throws error anyway, + // so no need to guard against it here. + return fs.symlinkSync(resolvedSrcPath, dest) + } else { + if (opts.dereference) { + resolvedDestPath = path.resolve(process.cwd(), resolvedDestPath) + } + if (resolvedDestPath === resolvedSrcPath) return + + // 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. + if (fs.statSync(dest).isDirectory() && isSrcSubdir(resolvedDestPath, resolvedSrcPath)) { + throw new Error(`Cannot overwrite '${resolvedDestPath}' with '${resolvedSrcPath}'.`) + } + return copyLink(resolvedSrcPath, dest) + } +} + +function copyLink (resolvedSrcPath, dest) { + fs.unlinkSync(dest) + return fs.symlinkSync(resolvedSrcPath, dest) +} + +// check if dest exists and/or is a symlink +function checkDest (dest) { + let resolvedPath + try { + resolvedPath = fs.readlinkSync(dest) + } catch (err) { + if (err.code === 'ENOENT') return notExist + + // dest exists and is a regular file or directory, Windows may throw UNKNOWN error + if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return existsReg + + throw err + } + return resolvedPath // dest exists and 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 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 + } + return false +} + +module.exports = copySync diff --git a/node_modules/fs-extra/lib/copy-sync/index.js b/node_modules/fs-extra/lib/copy-sync/index.js new file mode 100644 index 0000000..ebc7e0b --- /dev/null +++ b/node_modules/fs-extra/lib/copy-sync/index.js @@ -0,0 +1,3 @@ +module.exports = { + copySync: require('./copy-sync') +} diff --git a/node_modules/fs-extra/lib/copy/copy.js b/node_modules/fs-extra/lib/copy/copy.js new file mode 100644 index 0000000..fd9687f --- /dev/null +++ b/node_modules/fs-extra/lib/copy/copy.js @@ -0,0 +1,264 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const mkdirp = require('../mkdirs').mkdirs +const pathExists = require('../path-exists').pathExists +const utimes = require('../util/utimes').utimesMillis + +const notExist = Symbol('notExist') +const existsReg = Symbol('existsReg') + +function copy (src, dest, opts, cb) { + if (typeof opts === 'function' && !cb) { + cb = opts + opts = {} + } else if (typeof opts === 'function') { + opts = {filter: opts} + } + + cb = cb || function () {} + opts = opts || {} + + opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now + opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber + + // Warn about using preserveTimestamps on 32-bit node + if (opts.preserveTimestamps && process.arch === 'ia32') { + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n + see https://github.com/jprichardson/node-fs-extra/issues/269`) + } + + 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) +} + +function checkParentDir (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) + mkdirp(destParent, err => { + if (err) return cb(err) + return startCopy(src, dest, opts, cb) + }) + }) +} + +function startCopy (src, dest, opts, cb) { + if (opts.filter) return handleFilter(getStats, src, dest, opts, cb) + return getStats(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 getStats (src, dest, opts, cb) { + const stat = opts.dereference ? fs.stat : fs.lstat + stat(src, (err, st) => { + if (err) return cb(err) + + if (st.isDirectory()) return onDir(st, 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) + }) +} + +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 mayCopyFile (srcStat, src, dest, opts, cb) { + if (opts.overwrite) { + fs.unlink(dest, err => { + if (err) return cb(err) + return copyFile(srcStat, src, dest, opts, cb) + }) + } else if (opts.errorOnExist) { + return cb(new Error(`'${dest}' already exists`)) + } else return cb() +} + +function copyFile (srcStat, src, dest, opts, cb) { + if (typeof fs.copyFile === 'function') { + return fs.copyFile(src, dest, err => { + if (err) return cb(err) + return setDestModeAndTimestamps(srcStat, dest, opts, cb) + }) + } + return copyFileFallback(srcStat, src, dest, opts, 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 setDestModeAndTimestamps (srcStat, dest, opts, cb) { + fs.chmod(dest, srcStat.mode, err => { + if (err) return cb(err) + if (opts.preserveTimestamps) { + return utimes(dest, srcStat.atime, srcStat.mtime, cb) + } + return cb() + }) +} + +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 mayCopyDir (src, dest, opts, cb) { + fs.stat(dest, (err, st) => { + if (err) return cb(err) + if (!st.isDirectory()) { + return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)) + } + return copyDir(src, dest, opts, cb) + }) +} + +function mkDirAndCopy (srcStat, src, dest, opts, cb) { + fs.mkdir(dest, srcStat.mode, err => { + if (err) return cb(err) + fs.chmod(dest, srcStat.mode, err => { + if (err) return cb(err) + return copyDir(src, dest, opts, cb) + }) + }) +} + +function copyDir (src, dest, opts, cb) { + fs.readdir(src, (err, items) => { + if (err) return cb(err) + return copyDirItems(items, src, dest, opts, cb) + }) +} + +function copyDirItems (items, src, dest, opts, cb) { + const item = items.pop() + if (!item) return cb() + startCopy(path.join(src, item), path.join(dest, item), 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) => { + if (err) return cb(err) + + if (opts.dereference) { + resolvedSrcPath = path.resolve(process.cwd(), resolvedSrcPath) + } + + checkDest(dest, (err, resolvedDestPath) => { + if (err) return cb(err) + + 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) + } + 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) + }) + } + }) + }) +} + +function copyLink (resolvedSrcPath, dest, cb) { + fs.unlink(dest, err => { + if (err) return cb(err) + return fs.symlink(resolvedSrcPath, dest, cb) + }) +} + +// check if dest exists and/or is a symlink +function checkDest (dest, cb) { + fs.readlink(dest, (err, resolvedPath) => { + if (err) { + if (err.code === 'ENOENT') return cb(null, notExist) + + // dest exists and is a regular file or directory, Windows may throw UNKNOWN error. + if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return cb(null, existsReg) + + return cb(err) + } + return cb(null, resolvedPath) // dest exists and 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 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 + } + return false +} + +module.exports = copy diff --git a/node_modules/fs-extra/lib/copy/index.js b/node_modules/fs-extra/lib/copy/index.js new file mode 100644 index 0000000..a6a51da --- /dev/null +++ b/node_modules/fs-extra/lib/copy/index.js @@ -0,0 +1,4 @@ +const u = require('universalify').fromCallback +module.exports = { + copy: u(require('./copy')) +} diff --git a/node_modules/fs-extra/lib/empty/index.js b/node_modules/fs-extra/lib/empty/index.js new file mode 100644 index 0000000..db05c17 --- /dev/null +++ b/node_modules/fs-extra/lib/empty/index.js @@ -0,0 +1,48 @@ +'use strict' + +const u = require('universalify').fromCallback +const fs = require('fs') +const path = require('path') +const mkdir = require('../mkdirs') +const remove = require('../remove') + +const emptyDir = u(function emptyDir (dir, callback) { + callback = callback || function () {} + fs.readdir(dir, (err, items) => { + if (err) return mkdir.mkdirs(dir, callback) + + items = items.map(item => path.join(dir, item)) + + deleteItem() + + function deleteItem () { + const item = items.pop() + if (!item) return callback() + remove.remove(item, err => { + if (err) return callback(err) + deleteItem() + }) + } + }) +}) + +function emptyDirSync (dir) { + let items + try { + items = fs.readdirSync(dir) + } catch (err) { + return mkdir.mkdirsSync(dir) + } + + items.forEach(item => { + item = path.join(dir, item) + remove.removeSync(item) + }) +} + +module.exports = { + emptyDirSync, + emptydirSync: emptyDirSync, + emptyDir, + emptydir: emptyDir +} diff --git a/node_modules/fs-extra/lib/ensure/file.js b/node_modules/fs-extra/lib/ensure/file.js new file mode 100644 index 0000000..67eed30 --- /dev/null +++ b/node_modules/fs-extra/lib/ensure/file.js @@ -0,0 +1,49 @@ +'use strict' + +const u = require('universalify').fromCallback +const path = require('path') +const fs = require('graceful-fs') +const mkdir = require('../mkdirs') +const pathExists = require('../path-exists').pathExists + +function createFile (file, callback) { + function makeFile () { + fs.writeFile(file, '', err => { + if (err) return callback(err) + callback() + }) + } + + fs.stat(file, (err, stats) => { // eslint-disable-line handle-callback-err + if (!err && stats.isFile()) return 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() + }) + }) + }) +} + +function createFileSync (file) { + let stats + try { + stats = fs.statSync(file) + } catch (e) {} + if (stats && stats.isFile()) return + + const dir = path.dirname(file) + if (!fs.existsSync(dir)) { + mkdir.mkdirsSync(dir) + } + + fs.writeFileSync(file, '') +} + +module.exports = { + createFile: u(createFile), + createFileSync +} diff --git a/node_modules/fs-extra/lib/ensure/index.js b/node_modules/fs-extra/lib/ensure/index.js new file mode 100644 index 0000000..c1f67b7 --- /dev/null +++ b/node_modules/fs-extra/lib/ensure/index.js @@ -0,0 +1,23 @@ +'use strict' + +const file = require('./file') +const link = require('./link') +const symlink = require('./symlink') + +module.exports = { + // file + createFile: file.createFile, + createFileSync: file.createFileSync, + ensureFile: file.createFile, + ensureFileSync: file.createFileSync, + // link + createLink: link.createLink, + createLinkSync: link.createLinkSync, + ensureLink: link.createLink, + ensureLinkSync: link.createLinkSync, + // symlink + createSymlink: symlink.createSymlink, + createSymlinkSync: symlink.createSymlinkSync, + ensureSymlink: symlink.createSymlink, + ensureSymlinkSync: symlink.createSymlinkSync +} diff --git a/node_modules/fs-extra/lib/ensure/link.js b/node_modules/fs-extra/lib/ensure/link.js new file mode 100644 index 0000000..49fe379 --- /dev/null +++ b/node_modules/fs-extra/lib/ensure/link.js @@ -0,0 +1,61 @@ +'use strict' + +const u = require('universalify').fromCallback +const path = require('path') +const fs = require('graceful-fs') +const mkdir = require('../mkdirs') +const pathExists = require('../path-exists').pathExists + +function createLink (srcpath, dstpath, callback) { + function makeLink (srcpath, dstpath) { + fs.link(srcpath, dstpath, err => { + if (err) return callback(err) + callback(null) + }) + } + + pathExists(dstpath, (err, destinationExists) => { + if (err) return callback(err) + if (destinationExists) return callback(null) + fs.lstat(srcpath, (err, stat) => { + if (err) { + err.message = err.message.replace('lstat', 'ensureLink') + return callback(err) + } + + const dir = path.dirname(dstpath) + pathExists(dir, (err, dirExists) => { + if (err) return callback(err) + if (dirExists) return makeLink(srcpath, dstpath) + mkdir.mkdirs(dir, err => { + if (err) return callback(err) + makeLink(srcpath, dstpath) + }) + }) + }) + }) +} + +function createLinkSync (srcpath, dstpath, callback) { + const destinationExists = fs.existsSync(dstpath) + if (destinationExists) return undefined + + try { + fs.lstatSync(srcpath) + } catch (err) { + err.message = err.message.replace('lstat', 'ensureLink') + throw err + } + + const dir = path.dirname(dstpath) + const dirExists = fs.existsSync(dir) + if (dirExists) return fs.linkSync(srcpath, dstpath) + mkdir.mkdirsSync(dir) + + return fs.linkSync(srcpath, dstpath) +} + +module.exports = { + createLink: u(createLink), + createLinkSync +} diff --git a/node_modules/fs-extra/lib/ensure/symlink-paths.js b/node_modules/fs-extra/lib/ensure/symlink-paths.js new file mode 100644 index 0000000..4a6b78a --- /dev/null +++ b/node_modules/fs-extra/lib/ensure/symlink-paths.js @@ -0,0 +1,99 @@ +'use strict' + +const path = require('path') +const fs = require('graceful-fs') +const pathExists = require('../path-exists').pathExists + +/** + * Function that returns two types of paths, one relative to symlink, and one + * relative to the current working directory. Checks if path is absolute or + * relative. If the path is relative, this function checks if the path is + * relative to symlink or relative to current working directory. This is an + * initiative to find a smarter `srcpath` to supply when building symlinks. + * This allows you to determine which path to use out of one of three possible + * types of source paths. The first is an absolute path. This is detected by + * `path.isAbsolute()`. When an absolute path is provided, it is checked to + * see if it exists. If it does it's used, if not an error is returned + * (callback)/ thrown (sync). The other two options for `srcpath` are a + * relative url. By default Node's `fs.symlink` works by creating a symlink + * using `dstpath` and expects the `srcpath` to be relative to the newly + * created symlink. If you provide a `srcpath` that does not exist on the file + * system it results in a broken symlink. To minimize this, the function + * checks to see if the 'relative to symlink' source file exists, and if it + * does it will use it. If it does not, it checks if there's a file that + * exists that is relative to the current working directory, if does its used. + * This preserves the expectations of the original fs.symlink spec and adds + * the ability to pass in `relative to current working direcotry` paths. + */ + +function symlinkPaths (srcpath, dstpath, callback) { + if (path.isAbsolute(srcpath)) { + return fs.lstat(srcpath, (err, stat) => { + if (err) { + err.message = err.message.replace('lstat', 'ensureSymlink') + return callback(err) + } + return callback(null, { + 'toCwd': srcpath, + 'toDst': srcpath + }) + }) + } else { + const dstdir = path.dirname(dstpath) + const relativeToDst = path.join(dstdir, srcpath) + return pathExists(relativeToDst, (err, exists) => { + if (err) return callback(err) + if (exists) { + return callback(null, { + 'toCwd': relativeToDst, + 'toDst': srcpath + }) + } else { + return fs.lstat(srcpath, (err, stat) => { + if (err) { + err.message = err.message.replace('lstat', 'ensureSymlink') + return callback(err) + } + return callback(null, { + 'toCwd': srcpath, + 'toDst': path.relative(dstdir, srcpath) + }) + }) + } + }) + } +} + +function symlinkPathsSync (srcpath, dstpath) { + let exists + if (path.isAbsolute(srcpath)) { + exists = fs.existsSync(srcpath) + if (!exists) throw new Error('absolute srcpath does not exist') + return { + 'toCwd': srcpath, + 'toDst': srcpath + } + } else { + const dstdir = path.dirname(dstpath) + const relativeToDst = path.join(dstdir, srcpath) + exists = fs.existsSync(relativeToDst) + if (exists) { + return { + 'toCwd': relativeToDst, + 'toDst': srcpath + } + } else { + exists = fs.existsSync(srcpath) + if (!exists) throw new Error('relative srcpath does not exist') + return { + 'toCwd': srcpath, + 'toDst': path.relative(dstdir, srcpath) + } + } + } +} + +module.exports = { + symlinkPaths, + symlinkPathsSync +} diff --git a/node_modules/fs-extra/lib/ensure/symlink-type.js b/node_modules/fs-extra/lib/ensure/symlink-type.js new file mode 100644 index 0000000..4f8787c --- /dev/null +++ b/node_modules/fs-extra/lib/ensure/symlink-type.js @@ -0,0 +1,31 @@ +'use strict' + +const fs = require('graceful-fs') + +function symlinkType (srcpath, type, callback) { + callback = (typeof type === 'function') ? type : callback + type = (typeof type === 'function') ? false : type + if (type) return callback(null, type) + fs.lstat(srcpath, (err, stats) => { + if (err) return callback(null, 'file') + type = (stats && stats.isDirectory()) ? 'dir' : 'file' + callback(null, type) + }) +} + +function symlinkTypeSync (srcpath, type) { + let stats + + if (type) return type + try { + stats = fs.lstatSync(srcpath) + } catch (e) { + return 'file' + } + return (stats && stats.isDirectory()) ? 'dir' : 'file' +} + +module.exports = { + symlinkType, + symlinkTypeSync +} diff --git a/node_modules/fs-extra/lib/ensure/symlink.js b/node_modules/fs-extra/lib/ensure/symlink.js new file mode 100644 index 0000000..847c1b9 --- /dev/null +++ b/node_modules/fs-extra/lib/ensure/symlink.js @@ -0,0 +1,66 @@ +'use strict' + +const u = require('universalify').fromCallback +const path = require('path') +const fs = require('graceful-fs') +const _mkdirs = require('../mkdirs') +const mkdirs = _mkdirs.mkdirs +const mkdirsSync = _mkdirs.mkdirsSync + +const _symlinkPaths = require('./symlink-paths') +const symlinkPaths = _symlinkPaths.symlinkPaths +const symlinkPathsSync = _symlinkPaths.symlinkPathsSync + +const _symlinkType = require('./symlink-type') +const symlinkType = _symlinkType.symlinkType +const symlinkTypeSync = _symlinkType.symlinkTypeSync + +const pathExists = require('../path-exists').pathExists + +function createSymlink (srcpath, dstpath, type, callback) { + callback = (typeof type === 'function') ? type : callback + type = (typeof type === 'function') ? false : type + + pathExists(dstpath, (err, destinationExists) => { + if (err) return callback(err) + if (destinationExists) return callback(null) + symlinkPaths(srcpath, dstpath, (err, relative) => { + if (err) return callback(err) + srcpath = relative.toDst + symlinkType(relative.toCwd, type, (err, type) => { + if (err) return callback(err) + const dir = path.dirname(dstpath) + pathExists(dir, (err, dirExists) => { + if (err) return callback(err) + if (dirExists) return fs.symlink(srcpath, dstpath, type, callback) + mkdirs(dir, err => { + if (err) return callback(err) + fs.symlink(srcpath, dstpath, type, callback) + }) + }) + }) + }) + }) +} + +function createSymlinkSync (srcpath, dstpath, type, callback) { + callback = (typeof type === 'function') ? type : callback + type = (typeof type === 'function') ? false : type + + const destinationExists = fs.existsSync(dstpath) + if (destinationExists) return undefined + + const relative = symlinkPathsSync(srcpath, dstpath) + srcpath = relative.toDst + type = symlinkTypeSync(relative.toCwd, type) + const dir = path.dirname(dstpath) + const exists = fs.existsSync(dir) + if (exists) return fs.symlinkSync(srcpath, dstpath, type) + mkdirsSync(dir) + return fs.symlinkSync(srcpath, dstpath, type) +} + +module.exports = { + createSymlink: u(createSymlink), + createSymlinkSync +} diff --git a/node_modules/fs-extra/lib/fs/index.js b/node_modules/fs-extra/lib/fs/index.js new file mode 100644 index 0000000..1821fd0 --- /dev/null +++ b/node_modules/fs-extra/lib/fs/index.js @@ -0,0 +1,107 @@ +// This is adapted from https://github.com/normalize/mz +// Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors +const u = require('universalify').fromCallback +const fs = require('graceful-fs') + +const api = [ + 'access', + 'appendFile', + 'chmod', + 'chown', + 'close', + 'copyFile', + 'fchmod', + 'fchown', + 'fdatasync', + 'fstat', + 'fsync', + 'ftruncate', + 'futimes', + 'lchown', + 'link', + 'lstat', + 'mkdir', + 'mkdtemp', + 'open', + 'readFile', + 'readdir', + 'readlink', + 'realpath', + 'rename', + 'rmdir', + 'stat', + 'symlink', + 'truncate', + 'unlink', + 'utimes', + 'writeFile' +].filter(key => { + // 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.lchown is not available on at least some Linux + return typeof fs[key] === 'function' +}) + +// Export all keys: +Object.keys(fs).forEach(key => { + exports[key] = fs[key] +}) + +// Universalify async methods: +api.forEach(method => { + exports[method] = u(fs[method]) +}) + +// We differ from mz/fs in that we still ship the old, broken, fs.exists() +// since we are a drop-in replacement for the native module +exports.exists = function (filename, callback) { + if (typeof callback === 'function') { + return fs.exists(filename, callback) + } + return new Promise(resolve => { + return fs.exists(filename, resolve) + }) +} + +// 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 }) + }) + }) +} diff --git a/node_modules/fs-extra/lib/index.js b/node_modules/fs-extra/lib/index.js new file mode 100644 index 0000000..cb7dd9e --- /dev/null +++ b/node_modules/fs-extra/lib/index.js @@ -0,0 +1,22 @@ +'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 diff --git a/node_modules/fs-extra/lib/json/index.js b/node_modules/fs-extra/lib/json/index.js new file mode 100644 index 0000000..bae68d4 --- /dev/null +++ b/node_modules/fs-extra/lib/json/index.js @@ -0,0 +1,16 @@ +'use strict' + +const u = require('universalify').fromCallback +const jsonFile = require('./jsonfile') + +jsonFile.outputJson = u(require('./output-json')) +jsonFile.outputJsonSync = require('./output-json-sync') +// aliases +jsonFile.outputJSON = jsonFile.outputJson +jsonFile.outputJSONSync = jsonFile.outputJsonSync +jsonFile.writeJSON = jsonFile.writeJson +jsonFile.writeJSONSync = jsonFile.writeJsonSync +jsonFile.readJSON = jsonFile.readJson +jsonFile.readJSONSync = jsonFile.readJsonSync + +module.exports = jsonFile diff --git a/node_modules/fs-extra/lib/json/jsonfile.js b/node_modules/fs-extra/lib/json/jsonfile.js new file mode 100644 index 0000000..59cdb3e --- /dev/null +++ b/node_modules/fs-extra/lib/json/jsonfile.js @@ -0,0 +1,12 @@ +'use strict' + +const u = require('universalify').fromCallback +const jsonFile = require('jsonfile') + +module.exports = { + // jsonfile exports + readJson: u(jsonFile.readFile), + readJsonSync: jsonFile.readFileSync, + writeJson: u(jsonFile.writeFile), + writeJsonSync: jsonFile.writeFileSync +} diff --git a/node_modules/fs-extra/lib/json/output-json-sync.js b/node_modules/fs-extra/lib/json/output-json-sync.js new file mode 100644 index 0000000..6f76710 --- /dev/null +++ b/node_modules/fs-extra/lib/json/output-json-sync.js @@ -0,0 +1,18 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const mkdir = require('../mkdirs') +const jsonFile = require('./jsonfile') + +function outputJsonSync (file, data, options) { + const dir = path.dirname(file) + + if (!fs.existsSync(dir)) { + mkdir.mkdirsSync(dir) + } + + jsonFile.writeJsonSync(file, data, options) +} + +module.exports = outputJsonSync diff --git a/node_modules/fs-extra/lib/json/output-json.js b/node_modules/fs-extra/lib/json/output-json.js new file mode 100644 index 0000000..d45edb8 --- /dev/null +++ b/node_modules/fs-extra/lib/json/output-json.js @@ -0,0 +1,27 @@ +'use strict' + +const path = require('path') +const mkdir = require('../mkdirs') +const pathExists = require('../path-exists').pathExists +const jsonFile = require('./jsonfile') + +function outputJson (file, data, options, callback) { + if (typeof options === 'function') { + callback = options + 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) + }) + }) +} + +module.exports = outputJson diff --git a/node_modules/fs-extra/lib/mkdirs/index.js b/node_modules/fs-extra/lib/mkdirs/index.js new file mode 100644 index 0000000..29975c5 --- /dev/null +++ b/node_modules/fs-extra/lib/mkdirs/index.js @@ -0,0 +1,14 @@ +'use strict' +const u = require('universalify').fromCallback +const mkdirs = u(require('./mkdirs')) +const mkdirsSync = require('./mkdirs-sync') + +module.exports = { + mkdirs: mkdirs, + mkdirsSync: mkdirsSync, + // alias + mkdirp: mkdirs, + mkdirpSync: mkdirsSync, + ensureDir: mkdirs, + ensureDirSync: mkdirsSync +} diff --git a/node_modules/fs-extra/lib/mkdirs/mkdirs-sync.js b/node_modules/fs-extra/lib/mkdirs/mkdirs-sync.js new file mode 100644 index 0000000..a3ece40 --- /dev/null +++ b/node_modules/fs-extra/lib/mkdirs/mkdirs-sync.js @@ -0,0 +1,59 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const invalidWin32Path = require('./win32').invalidWin32Path + +const o777 = parseInt('0777', 8) + +function mkdirsSync (p, opts, made) { + if (!opts || typeof opts !== 'object') { + opts = { mode: opts } + } + + let mode = opts.mode + const xfs = opts.fs || fs + + if (process.platform === 'win32' && invalidWin32Path(p)) { + const errInval = new Error(p + ' contains invalid WIN32 path characters.') + errInval.code = 'EINVAL' + throw errInval + } + + if (mode === undefined) { + mode = o777 & (~process.umask()) + } + if (!made) made = null + + p = path.resolve(p) + + try { + xfs.mkdirSync(p, mode) + made = made || p + } 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 + } + } + + return made +} + +module.exports = mkdirsSync diff --git a/node_modules/fs-extra/lib/mkdirs/mkdirs.js b/node_modules/fs-extra/lib/mkdirs/mkdirs.js new file mode 100644 index 0000000..1897533 --- /dev/null +++ b/node_modules/fs-extra/lib/mkdirs/mkdirs.js @@ -0,0 +1,63 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const invalidWin32Path = require('./win32').invalidWin32Path + +const o777 = parseInt('0777', 8) + +function mkdirs (p, opts, callback, made) { + if (typeof opts === 'function') { + callback = opts + opts = {} + } else if (!opts || typeof opts !== 'object') { + opts = { mode: opts } + } + + if (process.platform === 'win32' && invalidWin32Path(p)) { + const errInval = new Error(p + ' contains invalid WIN32 path characters.') + errInval.code = 'EINVAL' + return callback(errInval) + } + + let mode = opts.mode + const xfs = opts.fs || fs + + if (mode === undefined) { + mode = o777 & (~process.umask()) + } + if (!made) made = null + + callback = callback || function () {} + p = path.resolve(p) + + xfs.mkdir(p, mode, er => { + if (!er) { + made = made || p + return callback(null, made) + } + switch (er.code) { + case 'ENOENT': + if (path.dirname(p) === p) return callback(er) + mkdirs(path.dirname(p), opts, (er, made) => { + if (er) callback(er, made) + else mkdirs(p, opts, callback, 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: + xfs.stat(p, (er2, stat) => { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) callback(er, made) + else callback(null, made) + }) + break + } + }) +} + +module.exports = mkdirs diff --git a/node_modules/fs-extra/lib/mkdirs/win32.js b/node_modules/fs-extra/lib/mkdirs/win32.js new file mode 100644 index 0000000..99b3920 --- /dev/null +++ b/node_modules/fs-extra/lib/mkdirs/win32.js @@ -0,0 +1,25 @@ +'use strict' + +const path = require('path') + +// get drive on windows +function getRootPath (p) { + p = path.normalize(path.resolve(p)).split(path.sep) + if (p.length > 0) return p[0] + return null +} + +// http://stackoverflow.com/a/62888/10333 contains more accurate +// TODO: expand to include the rest +const INVALID_PATH_CHARS = /[<>:"|?*]/ + +function invalidWin32Path (p) { + const rp = getRootPath(p) + p = p.replace(rp, '') + return INVALID_PATH_CHARS.test(p) +} + +module.exports = { + getRootPath, + invalidWin32Path +} diff --git a/node_modules/fs-extra/lib/move-sync/index.js b/node_modules/fs-extra/lib/move-sync/index.js new file mode 100644 index 0000000..a5e9114 --- /dev/null +++ b/node_modules/fs-extra/lib/move-sync/index.js @@ -0,0 +1,118 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const copySync = require('../copy-sync').copySync +const removeSync = require('../remove').removeSync +const mkdirpSync = require('../mkdirs').mkdirsSync +const buffer = require('../util/buffer') + +function moveSync (src, dest, options) { + options = options || {} + const overwrite = options.overwrite || options.clobber || false + + src = path.resolve(src) + dest = path.resolve(dest) + + if (src === dest) return fs.accessSync(src) + + if (isSrcSubdir(src, dest)) throw new Error(`Cannot move '${src}' into itself '${dest}'.`) + + mkdirpSync(path.dirname(dest)) + tryRenameSync() + + function tryRenameSync () { + if (overwrite) { + try { + return fs.renameSync(src, dest) + } catch (err) { + if (err.code === 'ENOTEMPTY' || err.code === 'EEXIST' || err.code === 'EPERM') { + removeSync(dest) + options.overwrite = false // just overwriteed it, no need to do it again + return moveSync(src, dest, options) + } + + if (err.code !== 'EXDEV') throw err + return moveSyncAcrossDevice(src, dest, overwrite) + } + } else { + try { + fs.linkSync(src, dest) + return fs.unlinkSync(src) + } catch (err) { + if (err.code === 'EXDEV' || err.code === 'EISDIR' || err.code === 'EPERM' || err.code === 'ENOTSUP') { + return moveSyncAcrossDevice(src, dest, overwrite) + } + throw err + } + } + } +} + +function moveSyncAcrossDevice (src, dest, overwrite) { + const stat = fs.statSync(src) + + if (stat.isDirectory()) { + return moveDirSyncAcrossDevice(src, dest, overwrite) + } else { + return moveFileSyncAcrossDevice(src, dest, overwrite) + } +} + +function moveFileSyncAcrossDevice (src, dest, overwrite) { + const BUF_LENGTH = 64 * 1024 + const _buff = buffer(BUF_LENGTH) + + const flags = overwrite ? 'w' : 'wx' + + const fdr = fs.openSync(src, 'r') + const stat = fs.fstatSync(fdr) + 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) + fs.writeSync(fdw, _buff, 0, bytesRead) + pos += bytesRead + } + + fs.closeSync(fdr) + fs.closeSync(fdw) + return fs.unlinkSync(src) +} + +function moveDirSyncAcrossDevice (src, dest, overwrite) { + const options = { + overwrite: false + } + + if (overwrite) { + removeSync(dest) + tryCopySync() + } else { + tryCopySync() + } + + function tryCopySync () { + copySync(src, dest, options) + return removeSync(src) + } +} + +// 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) { + try { + return fs.statSync(src).isDirectory() && + src !== dest && + dest.indexOf(src) > -1 && + dest.split(path.dirname(src) + path.sep)[1].split(path.sep)[0] === path.basename(src) + } catch (e) { + return false + } +} + +module.exports = { + moveSync +} diff --git a/node_modules/fs-extra/lib/move/index.js b/node_modules/fs-extra/lib/move/index.js new file mode 100644 index 0000000..a718135 --- /dev/null +++ b/node_modules/fs-extra/lib/move/index.js @@ -0,0 +1,170 @@ +'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 remove = require('../remove').remove +const mkdirp = require('../mkdirs').mkdirs + +function move (src, dest, options, callback) { + if (typeof options === 'function') { + callback = options + options = {} + } + + const overwrite = options.overwrite || options.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() + }) + }) + + 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 (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 + } + + // 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) + }) + } + } +} + +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) + } + }) +} + +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) + } + }) + }) + + outs.on('error', err => { + ins.destroy() + outs.destroy() + outs.removeListener('close', onClose) + callback(err) + }) + + outs.once('close', onClose) + ins.pipe(outs) + + function onClose () { + fs.unlink(src, callback) + } +} + +function moveDirAcrossDevice (src, dest, overwrite, callback) { + const options = { + overwrite: false + } + + 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) => { + 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) +} diff --git a/node_modules/fs-extra/lib/output/index.js b/node_modules/fs-extra/lib/output/index.js new file mode 100644 index 0000000..53d5905 --- /dev/null +++ b/node_modules/fs-extra/lib/output/index.js @@ -0,0 +1,40 @@ +'use strict' + +const u = require('universalify').fromCallback +const fs = require('graceful-fs') +const path = require('path') +const mkdir = require('../mkdirs') +const pathExists = require('../path-exists').pathExists + +function outputFile (file, data, encoding, callback) { + if (typeof encoding === 'function') { + callback = encoding + encoding = 'utf8' + } + + const dir = path.dirname(file) + pathExists(dir, (err, itDoes) => { + if (err) return callback(err) + if (itDoes) return fs.writeFile(file, data, encoding, callback) + + mkdir.mkdirs(dir, err => { + if (err) return callback(err) + + fs.writeFile(file, data, encoding, callback) + }) + }) +} + +function outputFileSync (file, data, encoding) { + const dir = path.dirname(file) + if (fs.existsSync(dir)) { + return fs.writeFileSync.apply(fs, arguments) + } + mkdir.mkdirsSync(dir) + fs.writeFileSync.apply(fs, arguments) +} + +module.exports = { + outputFile: u(outputFile), + outputFileSync +} diff --git a/node_modules/fs-extra/lib/path-exists/index.js b/node_modules/fs-extra/lib/path-exists/index.js new file mode 100644 index 0000000..ddd9bc7 --- /dev/null +++ b/node_modules/fs-extra/lib/path-exists/index.js @@ -0,0 +1,12 @@ +'use strict' +const u = require('universalify').fromPromise +const fs = require('../fs') + +function pathExists (path) { + return fs.access(path).then(() => true).catch(() => false) +} + +module.exports = { + pathExists: u(pathExists), + pathExistsSync: fs.existsSync +} diff --git a/node_modules/fs-extra/lib/remove/index.js b/node_modules/fs-extra/lib/remove/index.js new file mode 100644 index 0000000..cee5340 --- /dev/null +++ b/node_modules/fs-extra/lib/remove/index.js @@ -0,0 +1,9 @@ +'use strict' + +const u = require('universalify').fromCallback +const rimraf = require('./rimraf') + +module.exports = { + remove: u(rimraf), + removeSync: rimraf.sync +} diff --git a/node_modules/fs-extra/lib/remove/rimraf.js b/node_modules/fs-extra/lib/remove/rimraf.js new file mode 100644 index 0000000..f078694 --- /dev/null +++ b/node_modules/fs-extra/lib/remove/rimraf.js @@ -0,0 +1,314 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const assert = require('assert') + +const isWindows = (process.platform === 'win32') + +function defaults (options) { + const methods = [ + 'unlink', + 'chmod', + 'stat', + 'lstat', + 'rmdir', + 'readdir' + ] + methods.forEach(m => { + options[m] = options[m] || fs[m] + m = m + 'Sync' + options[m] = options[m] || fs[m] + }) + + options.maxBusyTries = options.maxBusyTries || 3 +} + +function rimraf (p, options, cb) { + let busyTries = 0 + + if (typeof options === 'function') { + cb = options + options = {} + } + + 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(options, 'rimraf: invalid options argument provided') + assert.equal(typeof options, 'object', 'rimraf: options should be object') + + defaults(options) + + rimraf_(p, options, function CB (er) { + if (er) { + if ((er.code === 'EBUSY' || er.code === 'ENOTEMPTY' || er.code === 'EPERM') && + busyTries < options.maxBusyTries) { + busyTries++ + let time = busyTries * 100 + // try again, with the same exact callback as this one. + return setTimeout(() => rimraf_(p, options, CB), time) + } + + // already gone + if (er.code === 'ENOENT') er = null + } + + cb(er) + }) +} + +// Two possible strategies. +// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR +// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR +// +// Both result in an extra syscall when you guess wrong. However, there +// are likely far more normal files in the world than directories. This +// is based on the assumption that a the average number of files per +// directory is >= 1. +// +// If anyone ever complains about this, then I guess the strategy could +// be made configurable somehow. But until then, YAGNI. +function rimraf_ (p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + + // sunos lets the root user unlink directories, which is... weird. + // so we have to lstat here and make sure it's not a dir. + options.lstat(p, (er, st) => { + if (er && er.code === 'ENOENT') { + return cb(null) + } + + // Windows can EPERM on stat. Life is suffering. + if (er && er.code === 'EPERM' && isWindows) { + return fixWinEPERM(p, options, er, cb) + } + + if (st && st.isDirectory()) { + return rmdir(p, options, er, cb) + } + + options.unlink(p, er => { + if (er) { + if (er.code === 'ENOENT') { + return cb(null) + } + if (er.code === 'EPERM') { + return (isWindows) + ? fixWinEPERM(p, options, er, cb) + : rmdir(p, options, er, cb) + } + if (er.code === 'EISDIR') { + return rmdir(p, options, er, cb) + } + } + return cb(er) + }) + }) +} + +function fixWinEPERM (p, options, er, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + if (er) { + assert(er instanceof Error) + } + + options.chmod(p, 0o666, er2 => { + if (er2) { + cb(er2.code === 'ENOENT' ? null : er) + } else { + options.stat(p, (er3, stats) => { + if (er3) { + cb(er3.code === 'ENOENT' ? null : er) + } else if (stats.isDirectory()) { + rmdir(p, options, er, cb) + } else { + options.unlink(p, cb) + } + }) + } + }) +} + +function fixWinEPERMSync (p, options, er) { + let stats + + assert(p) + assert(options) + if (er) { + assert(er instanceof Error) + } + + try { + options.chmodSync(p, 0o666) + } catch (er2) { + if (er2.code === 'ENOENT') { + return + } else { + throw er + } + } + + try { + stats = options.statSync(p) + } catch (er3) { + if (er3.code === 'ENOENT') { + return + } else { + throw er + } + } + + if (stats.isDirectory()) { + rmdirSync(p, options, er) + } else { + options.unlinkSync(p) + } +} + +function rmdir (p, options, originalEr, cb) { + assert(p) + assert(options) + if (originalEr) { + assert(originalEr instanceof Error) + } + assert(typeof cb === 'function') + + // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) + // if we guessed wrong, and it's not a directory, then + // raise the original error. + options.rmdir(p, er => { + if (er && (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM')) { + rmkids(p, options, cb) + } else if (er && er.code === 'ENOTDIR') { + cb(originalEr) + } else { + cb(er) + } + }) +} + +function rmkids (p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + + options.readdir(p, (er, files) => { + if (er) return cb(er) + + let n = files.length + let errState + + if (n === 0) return options.rmdir(p, cb) + + files.forEach(f => { + rimraf(path.join(p, f), options, er => { + if (errState) { + return + } + if (er) return cb(errState = er) + if (--n === 0) { + options.rmdir(p, cb) + } + }) + }) + }) +} + +// this looks simpler, and is strictly *faster*, but will +// tie up the JavaScript thread and fail on excessively +// deep directory trees. +function rimrafSync (p, options) { + let st + + options = options || {} + defaults(options) + + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert(options, 'rimraf: missing options') + assert.equal(typeof options, 'object', 'rimraf: options should be object') + + try { + st = options.lstatSync(p) + } catch (er) { + if (er.code === 'ENOENT') { + return + } + + // Windows can EPERM on stat. Life is suffering. + if (er.code === 'EPERM' && isWindows) { + fixWinEPERMSync(p, options, er) + } + } + + try { + // sunos lets the root user unlink directories, which is... weird. + if (st && st.isDirectory()) { + rmdirSync(p, options, null) + } else { + options.unlinkSync(p) + } + } catch (er) { + if (er.code === 'ENOENT') { + return + } else if (er.code === 'EPERM') { + return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) + } else if (er.code !== 'EISDIR') { + throw er + } + rmdirSync(p, options, er) + } +} + +function rmdirSync (p, options, originalEr) { + assert(p) + assert(options) + if (originalEr) { + assert(originalEr instanceof Error) + } + + try { + options.rmdirSync(p) + } catch (er) { + if (er.code === 'ENOTDIR') { + throw originalEr + } else if (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM') { + rmkidsSync(p, options) + } else if (er.code !== 'ENOENT') { + throw er + } + } +} + +function rmkidsSync (p, options) { + assert(p) + assert(options) + options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), 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) +} + +module.exports = rimraf +rimraf.sync = rimrafSync diff --git a/node_modules/fs-extra/lib/util/assign.js b/node_modules/fs-extra/lib/util/assign.js new file mode 100644 index 0000000..317e5ec --- /dev/null +++ b/node_modules/fs-extra/lib/util/assign.js @@ -0,0 +1,16 @@ +'use strict' + +// simple mutable assign +function assign () { + const args = [].slice.call(arguments).filter(i => i) + const dest = args.shift() + args.forEach(src => { + Object.keys(src).forEach(key => { + dest[key] = src[key] + }) + }) + + return dest +} + +module.exports = assign diff --git a/node_modules/fs-extra/lib/util/buffer.js b/node_modules/fs-extra/lib/util/buffer.js new file mode 100644 index 0000000..93af51b --- /dev/null +++ b/node_modules/fs-extra/lib/util/buffer.js @@ -0,0 +1,11 @@ +/* eslint-disable node/no-deprecated-api */ +module.exports = function (size) { + if (typeof Buffer.allocUnsafe === 'function') { + try { + return Buffer.allocUnsafe(size) + } catch (e) { + return new Buffer(size) + } + } + return new Buffer(size) +} diff --git a/node_modules/fs-extra/lib/util/utimes.js b/node_modules/fs-extra/lib/util/utimes.js new file mode 100644 index 0000000..8916a1b --- /dev/null +++ b/node_modules/fs-extra/lib/util/utimes.js @@ -0,0 +1,79 @@ +'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) { + // if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback) + fs.open(path, 'r+', (err, fd) => { + if (err) return callback(err) + fs.futimes(fd, atime, mtime, futimesErr => { + fs.close(fd, closeErr => { + if (callback) callback(futimesErr || closeErr) + }) + }) + }) +} + +function utimesMillisSync (path, atime, mtime) { + const fd = fs.openSync(path, 'r+') + fs.futimesSync(fd, atime, mtime) + return fs.closeSync(fd) +} + +module.exports = { + hasMillisRes, + hasMillisResSync, + timeRemoveMillis, + utimesMillis, + utimesMillisSync +} |