Comparing version 6.1.15 to 6.2.0
@@ -82,10 +82,22 @@ 'use strict' | ||
this.zip = null | ||
if (opt.gzip) { | ||
if (typeof opt.gzip !== 'object') { | ||
opt.gzip = {} | ||
if (opt.gzip || opt.brotli) { | ||
if (opt.gzip && opt.brotli) { | ||
throw new TypeError('gzip and brotli are mutually exclusive') | ||
} | ||
if (this.portable) { | ||
opt.gzip.portable = true | ||
if (opt.gzip) { | ||
if (typeof opt.gzip !== 'object') { | ||
opt.gzip = {} | ||
} | ||
if (this.portable) { | ||
opt.gzip.portable = true | ||
} | ||
this.zip = new zlib.Gzip(opt.gzip) | ||
} | ||
this.zip = new zlib.Gzip(opt.gzip) | ||
if (opt.brotli) { | ||
if (typeof opt.brotli !== 'object') { | ||
opt.brotli = {} | ||
} | ||
this.zip = new zlib.BrotliCompress(opt.brotli) | ||
} | ||
this.zip.on('data', chunk => super.write(chunk)) | ||
@@ -92,0 +104,0 @@ this.zip.on('end', _ => super.end()) |
@@ -100,2 +100,12 @@ 'use strict' | ||
this.filter = typeof opt.filter === 'function' ? opt.filter : noop | ||
// Unlike gzip, brotli doesn't have any magic bytes to identify it | ||
// Users need to explicitly tell us they're extracting a brotli file | ||
// Or we infer from the file extension | ||
const isTBR = (opt.file && ( | ||
opt.file.endsWith('.tar.br') || opt.file.endsWith('.tbr'))) | ||
// if it's a tbr file it MIGHT be brotli, but we don't know until | ||
// we look at it and verify it's not a valid tar file. | ||
this.brotli = !opt.gzip && opt.brotli !== undefined ? opt.brotli | ||
: isTBR ? undefined | ||
: false | ||
@@ -351,3 +361,5 @@ // have to set this so that streams are ok piping into it | ||
// first write, might be gzipped | ||
if (this[UNZIP] === null && chunk) { | ||
const needSniff = this[UNZIP] === null || | ||
this.brotli === undefined && this[UNZIP] === false | ||
if (needSniff && chunk) { | ||
if (this[BUFFER]) { | ||
@@ -361,2 +373,4 @@ chunk = Buffer.concat([this[BUFFER], chunk]) | ||
} | ||
// look for gzip header | ||
for (let i = 0; this[UNZIP] === null && i < gzipHeader.length; i++) { | ||
@@ -367,6 +381,34 @@ if (chunk[i] !== gzipHeader[i]) { | ||
} | ||
if (this[UNZIP] === null) { | ||
const maybeBrotli = this.brotli === undefined | ||
if (this[UNZIP] === false && maybeBrotli) { | ||
// read the first header to see if it's a valid tar file. If so, | ||
// we can safely assume that it's not actually brotli, despite the | ||
// .tbr or .tar.br file extension. | ||
// if we ended before getting a full chunk, yes, def brotli | ||
if (chunk.length < 512) { | ||
if (this[ENDED]) { | ||
this.brotli = true | ||
} else { | ||
this[BUFFER] = chunk | ||
return true | ||
} | ||
} else { | ||
// if it's tar, it's pretty reliably not brotli, chances of | ||
// that happening are astronomical. | ||
try { | ||
new Header(chunk.slice(0, 512)) | ||
this.brotli = false | ||
} catch (_) { | ||
this.brotli = true | ||
} | ||
} | ||
} | ||
if (this[UNZIP] === null || (this[UNZIP] === false && this.brotli)) { | ||
const ended = this[ENDED] | ||
this[ENDED] = false | ||
this[UNZIP] = new zlib.Unzip() | ||
this[UNZIP] = this[UNZIP] === null | ||
? new zlib.Unzip() | ||
: new zlib.BrotliDecompress() | ||
this[UNZIP].on('data', chunk => this[CONSUMECHUNK](chunk)) | ||
@@ -509,2 +551,3 @@ this[UNZIP].on('error', er => this.abort(er)) | ||
this[ENDED] = true | ||
if (this.brotli === undefined) chunk = chunk || Buffer.alloc(0) | ||
this.write(chunk) | ||
@@ -511,0 +554,0 @@ } |
@@ -26,3 +26,3 @@ 'use strict' | ||
if (opt.gzip) { | ||
if (opt.gzip || opt.brotli || opt.file.endsWith('.br') || opt.file.endsWith('.tbr')) { | ||
throw new TypeError('cannot append to compressed archives') | ||
@@ -29,0 +29,0 @@ } |
@@ -16,3 +16,3 @@ 'use strict' | ||
if (opt.gzip) { | ||
if (opt.gzip || opt.brotli || opt.file.endsWith('.br') || opt.file.endsWith('.tbr')) { | ||
throw new TypeError('cannot append to compressed archives') | ||
@@ -19,0 +19,0 @@ } |
@@ -5,3 +5,3 @@ { | ||
"description": "tar for node", | ||
"version": "6.1.15", | ||
"version": "6.2.0", | ||
"repository": { | ||
@@ -13,9 +13,4 @@ "type": "git", | ||
"genparse": "node scripts/generate-parse-fixtures.js", | ||
"template-oss-apply": "template-oss-apply --force", | ||
"lint": "eslint \"**/*.js\"", | ||
"postlint": "template-oss-check", | ||
"lintfix": "npm run lint -- --fix", | ||
"snap": "tap", | ||
"test": "tap", | ||
"posttest": "npm run lint" | ||
"test": "tap" | ||
}, | ||
@@ -22,0 +17,0 @@ "dependencies": { |
165629
3822