Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / node-pre-gyp / node_modules / tar / lib / list.js
1 'use strict'
2
3 const Buffer = require('./buffer.js')
4
5 // XXX: This shares a lot in common with extract.js
6 // maybe some DRY opportunity here?
7
8 // tar -t
9 const hlo = require('./high-level-opt.js')
10 const Parser = require('./parse.js')
11 const fs = require('fs')
12 const fsm = require('fs-minipass')
13 const path = require('path')
14
15 const t = module.exports = (opt_, files, cb) => {
16   if (typeof opt_ === 'function')
17     cb = opt_, files = null, opt_ = {}
18   else if (Array.isArray(opt_))
19     files = opt_, opt_ = {}
20
21   if (typeof files === 'function')
22     cb = files, files = null
23
24   if (!files)
25     files = []
26   else
27     files = Array.from(files)
28
29   const opt = hlo(opt_)
30
31   if (opt.sync && typeof cb === 'function')
32     throw new TypeError('callback not supported for sync tar functions')
33
34   if (!opt.file && typeof cb === 'function')
35     throw new TypeError('callback only supported with file option')
36
37   if (files.length)
38     filesFilter(opt, files)
39
40   if (!opt.noResume)
41     onentryFunction(opt)
42
43   return opt.file && opt.sync ? listFileSync(opt)
44     : opt.file ? listFile(opt, cb)
45     : list(opt)
46 }
47
48 const onentryFunction = opt => {
49   const onentry = opt.onentry
50   opt.onentry = onentry ? e => {
51     onentry(e)
52     e.resume()
53   } : e => e.resume()
54 }
55
56 // construct a filter that limits the file entries listed
57 // include child entries if a dir is included
58 const filesFilter = (opt, files) => {
59   const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true]))
60   const filter = opt.filter
61
62   const mapHas = (file, r) => {
63     const root = r || path.parse(file).root || '.'
64     const ret = file === root ? false
65       : map.has(file) ? map.get(file)
66       : mapHas(path.dirname(file), root)
67
68     map.set(file, ret)
69     return ret
70   }
71
72   opt.filter = filter
73     ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, ''))
74     : file => mapHas(file.replace(/\/+$/, ''))
75 }
76
77 const listFileSync = opt => {
78   const p = list(opt)
79   const file = opt.file
80   let threw = true
81   let fd
82   try {
83     const stat = fs.statSync(file)
84     const readSize = opt.maxReadSize || 16*1024*1024
85     if (stat.size < readSize) {
86       p.end(fs.readFileSync(file))
87     } else {
88       let pos = 0
89       const buf = Buffer.allocUnsafe(readSize)
90       fd = fs.openSync(file, 'r')
91       while (pos < stat.size) {
92         let bytesRead = fs.readSync(fd, buf, 0, readSize, pos)
93         pos += bytesRead
94         p.write(buf.slice(0, bytesRead))
95       }
96       p.end()
97     }
98     threw = false
99   } finally {
100     if (threw && fd)
101       try { fs.closeSync(fd) } catch (er) {}
102   }
103 }
104
105 const listFile = (opt, cb) => {
106   const parse = new Parser(opt)
107   const readSize = opt.maxReadSize || 16*1024*1024
108
109   const file = opt.file
110   const p = new Promise((resolve, reject) => {
111     parse.on('error', reject)
112     parse.on('end', resolve)
113
114     fs.stat(file, (er, stat) => {
115       if (er)
116         reject(er)
117       else {
118         const stream = new fsm.ReadStream(file, {
119           readSize: readSize,
120           size: stat.size
121         })
122         stream.on('error', reject)
123         stream.pipe(parse)
124       }
125     })
126   })
127   return cb ? p.then(cb, cb) : p
128 }
129
130 const list = opt => new Parser(opt)