diff options
Diffstat (limited to 'node_modules/tar/lib/extract.js')
-rw-r--r-- | node_modules/tar/lib/extract.js | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/node_modules/tar/lib/extract.js b/node_modules/tar/lib/extract.js new file mode 100644 index 0000000..5476798 --- /dev/null +++ b/node_modules/tar/lib/extract.js @@ -0,0 +1,113 @@ +'use strict' + +// tar -x +const hlo = require('./high-level-opt.js') +const Unpack = require('./unpack.js') +const fs = require('fs') +const fsm = require('fs-minipass') +const path = require('path') +const stripSlash = require('./strip-trailing-slashes.js') + +module.exports = (opt_, files, cb) => { + if (typeof opt_ === 'function') { + cb = opt_, files = null, opt_ = {} + } else if (Array.isArray(opt_)) { + files = opt_, opt_ = {} + } + + if (typeof files === 'function') { + cb = files, files = null + } + + if (!files) { + files = [] + } else { + files = Array.from(files) + } + + const opt = hlo(opt_) + + if (opt.sync && typeof cb === 'function') { + throw new TypeError('callback not supported for sync tar functions') + } + + if (!opt.file && typeof cb === 'function') { + throw new TypeError('callback only supported with file option') + } + + if (files.length) { + filesFilter(opt, files) + } + + return opt.file && opt.sync ? extractFileSync(opt) + : opt.file ? extractFile(opt, cb) + : opt.sync ? extractSync(opt) + : extract(opt) +} + +// construct a filter that limits the file entries listed +// include child entries if a dir is included +const filesFilter = (opt, files) => { + const map = new Map(files.map(f => [stripSlash(f), true])) + const filter = opt.filter + + const mapHas = (file, r) => { + const root = r || path.parse(file).root || '.' + const ret = file === root ? false + : map.has(file) ? map.get(file) + : mapHas(path.dirname(file), root) + + map.set(file, ret) + return ret + } + + opt.filter = filter + ? (file, entry) => filter(file, entry) && mapHas(stripSlash(file)) + : file => mapHas(stripSlash(file)) +} + +const extractFileSync = opt => { + const u = new Unpack.Sync(opt) + + const file = opt.file + const stat = fs.statSync(file) + // This trades a zero-byte read() syscall for a stat + // However, it will usually result in less memory allocation + const readSize = opt.maxReadSize || 16 * 1024 * 1024 + const stream = new fsm.ReadStreamSync(file, { + readSize: readSize, + size: stat.size, + }) + stream.pipe(u) +} + +const extractFile = (opt, cb) => { + const u = new Unpack(opt) + const readSize = opt.maxReadSize || 16 * 1024 * 1024 + + const file = opt.file + const p = new Promise((resolve, reject) => { + u.on('error', reject) + u.on('close', resolve) + + // This trades a zero-byte read() syscall for a stat + // However, it will usually result in less memory allocation + fs.stat(file, (er, stat) => { + if (er) { + reject(er) + } else { + const stream = new fsm.ReadStream(file, { + readSize: readSize, + size: stat.size, + }) + stream.on('error', reject) + stream.pipe(u) + } + }) + }) + return cb ? p.then(cb, cb) : p +} + +const extractSync = opt => new Unpack.Sync(opt) + +const extract = opt => new Unpack(opt) |