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