lib/export.js
function exportArchiveToFilesystem (opts, cb) {
  return maybe(cb, async function () {
    assert(opts && typeof opts === 'object', 'opts object is required')

    // core arguments, dstPath and srcArchive
    var srcArchive = opts.srcArchive
    var dstPath = opts.dstPath
    assert(srcArchive && typeof srcArchive === 'object', 'srcArchive is required')
    assert(dstPath && typeof dstPath === 'string', 'dstPath is required')

    // options
    var srcPath = typeof opts.srcPath === 'string' ? opts.srcPath : '/'
    var overwriteExisting = opts.overwriteExisting === true
    var skipUndownloadedFiles = opts.skipUndownloadedFiles === true
    var ignore = Array.isArray(opts.ignore) ? opts.ignore : DEFAULT_IGNORE

    // abort if nonempty and not overwriting existing
    if (!overwriteExisting) {
      let files
      try {
        files = await fse.readdir(dstPath)
      } catch (e) {
        // target probably doesnt exist, continue and let ensureDirectory handle it
      }
      if (files && files.length > 0) {
        throw new DestDirectoryNotEmpty()
      }
    }

    const statThenExport = async function (srcPath, dstPath) {
      // apply ignore filter
      if (ignore && match(ignore, srcPath)) {
        return
      }

      // export by type
      var srcStat = await stat(srcArchive, srcPath)
      if (srcStat.isFile()) {
        await exportFile(srcPath, srcStat, dstPath)
      } else if (srcStat.isDirectory()) {
        await exportDirectory(srcPath, dstPath)
      }
    }

    const exportFile = async function (srcPath, srcStat, dstPath) {
      // skip undownloaded files
      if (skipUndownloadedFiles && srcStat.downloaded < srcStat.blocks) {
        return
      }

      // fetch dest stats
      var dstFileStats = null
      try {
        dstFileStats = await fse.stat(dstPath)
      } catch (e) {}

      // track the stats
      stats.fileCount++
      stats.totalSize += srcStat.size || 0
      if (dstFileStats) {
        if (dstFileStats.isDirectory()) {
          // delete the directory-tree
          await fse.remove(dstPath)
          stats.addedFiles.push(dstPath)
        } else {
          stats.updatedFiles.push(dstPath)
        }
      } else {
        stats.addedFiles.push(dstPath)
      }

      // write the file
      return new Promise((resolve, reject) => {
        pump(
          srcArchive.createReadStream(srcPath),
          fse.createWriteStream(dstPath),
          err => {
            if (err) reject(err)
            else resolve()
          }
        )
      })
    }

    const exportDirectory = async function (srcPath, dstPath) {
      // make sure the destination folder exists
      await fse.ensureDir(dstPath)

      // list the directory
      var fileNames = await readdir(srcArchive, srcPath)

      // recurse into each
      var promises = fileNames.map(name => {
        return statThenExport(path.join(srcPath, name), path.join(dstPath, name))
      })
      await Promise.all(promises)
    }

    // recursively export
    var stats = { addedFiles: [], updatedFiles: [], skipCount: 0, fileCount: 0, totalSize: 0 }
    await statThenExport(srcPath, dstPath)
    return stats
  })
}
function exportArchiveToFilesystem (opts, cb) {
  return maybe(cb, async function () {
    assert(opts && typeof opts === 'object', 'opts object is required')

    // core arguments, dstPath and srcArchive
    var srcArchive = opts.srcArchive
    var dstPath = opts.dstPath
    assert(srcArchive && typeof srcArchive === 'object', 'srcArchive is required')
    assert(dstPath && typeof dstPath === 'string', 'dstPath is required')

    // options
    var srcPath = typeof opts.srcPath === 'string' ? opts.srcPath : '/'
    var overwriteExisting = opts.overwriteExisting === true
    var skipUndownloadedFiles = opts.skipUndownloadedFiles === true
    var ignore = Array.isArray(opts.ignore) ? opts.ignore : DEFAULT_IGNORE

    // abort if nonempty and not overwriting existing
    if (!overwriteExisting) {
      let files
      try {
        files = await fse.readdir(dstPath)
      } catch (e) {
        // target probably doesnt exist, continue and let ensureDirectory handle it
      }
      if (files && files.length > 0) {
        throw new DestDirectoryNotEmpty()
      }
    }

    const statThenExport = async function (srcPath, dstPath) {
      // apply ignore filter
      if (ignore && match(ignore, srcPath)) {
        return
      }

      // export by type
      var srcStat = await stat(srcArchive, srcPath)
      if (srcStat.isFile()) {
        await exportFile(srcPath, srcStat, dstPath)
      } else if (srcStat.isDirectory()) {
        await exportDirectory(srcPath, dstPath)
      }
    }

    const exportFile = async function (srcPath, srcStat, dstPath) {
      // skip undownloaded files
      if (skipUndownloadedFiles && srcStat.downloaded < srcStat.blocks) {
        return
      }

      // fetch dest stats
      var dstFileStats = null
      try {
        dstFileStats = await fse.stat(dstPath)
      } catch (e) {}

      // track the stats
      stats.fileCount++
      stats.totalSize += srcStat.size || 0
      if (dstFileStats) {
        if (dstFileStats.isDirectory()) {
          // delete the directory-tree
          await fse.remove(dstPath)
          stats.addedFiles.push(dstPath)
        } else {
          stats.updatedFiles.push(dstPath)
        }
      } else {
        stats.addedFiles.push(dstPath)
      }

      // write the file
      return new Promise((resolve, reject) => {
        pump(
          srcArchive.createReadStream(srcPath),
          fse.createWriteStream(dstPath),
          err => {
            if (err) reject(err)
            else resolve()
          }
        )
      })
    }

    const exportDirectory = async function (srcPath, dstPath) {
      // make sure the destination folder exists
      await fse.ensureDir(dstPath)

      // list the directory
      var fileNames = await readdir(srcArchive, srcPath)

      // recurse into each
      var promises = fileNames.map(name => {
        return statThenExport(path.join(srcPath, name), path.join(dstPath, name))
      })
      await Promise.all(promises)
    }

    // recursively export
    var stats = { addedFiles: [], updatedFiles: [], skipCount: 0, fileCount: 0, totalSize: 0 }
    await statThenExport(srcPath, dstPath)
    return stats
  })
}
function exportArchiveToFilesystem ( opts , cb ) { return maybe ( cb , async function ( ) { assert ( opts && typeof opts === 'object' , 'opts object is required' ) // core arguments, dstPath and srcArchive var srcArchive = opts . srcArchive var dstPath = opts . dstPath assert ( srcArchive && typeof srcArchive === 'object' , 'srcArchive is required' ) assert ( dstPath && typeof dstPath === 'string' , 'dstPath is required' ) // options var srcPath = typeof opts . srcPath === 'string' ? opts . srcPath : '/' var overwriteExisting = opts . overwriteExisting === true var skipUndownloadedFiles = opts . skipUndownloadedFiles === true var ignore = Array . isArray ( opts . ignore ) ? opts . ignore : DEFAULT_IGNORE // abort if nonempty and not overwriting existing if ( ! overwriteExisting ) { let files try { files = await fse . readdir ( dstPath ) } catch ( e ) { // target probably doesnt exist, continue and let ensureDirectory handle it } if ( files && files . length > 0 ) { throw new DestDirectoryNotEmpty ( ) } } const statThenExport = async function ( srcPath , dstPath ) { // apply ignore filter if ( ignore && match ( ignore , srcPath ) ) { return } // export by type var srcStat = await stat ( srcArchive , srcPath ) if ( srcStat . isFile ( ) ) { await exportFile ( srcPath , srcStat , dstPath ) } else if ( srcStat . isDirectory ( ) ) { await exportDirectory ( srcPath , dstPath ) } } const exportFile = async function ( srcPath , srcStat , dstPath ) { // skip undownloaded files if ( skipUndownloadedFiles && srcStat . downloaded < srcStat . blocks ) { return } // fetch dest stats var dstFileStats = null try { dstFileStats = await fse . stat ( dstPath ) } catch ( e ) { } // track the stats stats . fileCount ++ stats . totalSize += srcStat . size || 0 if ( dstFileStats ) { if ( dstFileStats . isDirectory ( ) ) { // delete the directory-tree await fse . remove ( dstPath ) stats . addedFiles . push ( dstPath ) } else { stats . updatedFiles . push ( dstPath ) } } else { stats . addedFiles . push ( dstPath ) } // write the file return new Promise ( ( resolve , reject ) => { pump ( srcArchive . createReadStream ( srcPath ) , fse . createWriteStream ( dstPath ) , err => { if ( err ) reject ( err ) else resolve ( ) } ) } ) } const exportDirectory = async function ( srcPath , dstPath ) { // make sure the destination folder exists await fse . ensureDir ( dstPath ) // list the directory var fileNames = await readdir ( srcArchive , srcPath ) // recurse into each var promises = fileNames . map ( name => { return statThenExport ( path . join ( srcPath , name ) , path . join ( dstPath , name ) ) } ) await Promise . all ( promises ) } // recursively export var stats = { addedFiles : [ ] , updatedFiles : [ ] , skipCount : 0 , fileCount : 0 , totalSize : 0 } await statThenExport ( srcPath , dstPath ) return stats } ) }
copy files from an archive into the filesystem
copy files from an archive into the filesystem