summaryrefslogtreecommitdiff
path: root/node_modules/tar/lib/extract.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/tar/lib/extract.js')
-rw-r--r--node_modules/tar/lib/extract.js113
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)