This repository has been archived by the owner on Jul 3, 2019. It is now read-only.
/
extract-stream.js
108 lines (101 loc) · 2.98 KB
/
extract-stream.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
'use strict'
var chownr = require('chownr')
var gunzip = require('./util/gunzip-maybe')
var path = require('path')
var pipeline = require('mississippi').pipeline
var tar = require('tar-fs')
var to = require('mississippi').to
module.exports = extractStream
function extractStream (dest, opts) {
opts = opts || {}
var errEmitted = false
var tarStream = makeTarStream(dest, opts)
var target = to(function (chunk, enc, cb) {
tarStream.write(chunk, enc, cb)
}, function flush (cb) {
// TODO - there's a bug in tar-fs so we have to do this manually.
// This code ms.to() stunt can be removed afer the issue is fixed:
// https://github.com/mafintosh/tar-fs/issues/59
tarStream.end(function () {
if (
process.platform !== 'win32' &&
process.getuid &&
process.getuid() === 0 &&
(typeof opts.uid === 'number' || typeof opts.gid === 'number')
) {
chownr(
dest,
typeof opts.uid === 'number' ? opts.uid : process.getuid(),
typeof opts.gid === 'number' ? opts.gid : process.getgid(),
cb
)
} else {
cb()
}
})
})
target.on('error', function (err) {
if (!errEmitted) {
errEmitted = true
tarStream.emit('error', err)
}
})
tarStream.on('error', function (err) {
if (!errEmitted) {
errEmitted = true
target.emit('error', err)
}
})
return target
}
function makeTarStream (dest, opts) {
var sawIgnores = {}
return pipeline(gunzip(), tar.extract(dest, {
map: function (header) {
if (process.getuid && process.getuid() === 0) {
header.uid = opts.uid == null ? header.uid : opts.uid
header.gid = opts.gid == null ? header.gid : opts.gid
}
// Note: This mirrors logic in the fs read operations that are
// employed during tarball creation, in the fstream-npm module.
// It is duplicated here to handle tarballs that are created
// using other means, such as system tar or git archive.
if (header.type === 'file') {
var base = path.basename(header.name)
if (base === '.npmignore') {
sawIgnores[header.name] = true
} else if (base === '.gitignore') {
var npmignore = header.name.replace(/\.gitignore$/, '.npmignore')
if (!sawIgnores[npmignore]) {
// Rename, may be clobbered later.
header.name = npmignore
}
}
}
return header
},
ignore: makeIgnore(opts.log),
dmode: opts.dmode,
fmode: opts.fmode,
umask: opts.umask,
strip: 1
}))
}
function makeIgnore (log) {
var sawIgnores = {}
return function (name, header) {
return _ignore(name, header, sawIgnores, log)
}
}
function _ignore (name, header, sawIgnores, logger) {
if (header.type.match(/^.*link$/)) {
if (logger) {
logger.warn(
'extract-stream',
'excluding symbolic link',
header.name, '->', header.linkname)
}
return true
}
return false
}