Compare commits

..

10 commits

Author SHA1 Message Date
1e384904b9 i-dont-know fixture 2023-06-24 11:27:30 -03:00
Mathias Buus
6ed3778c66 3.1.4 2023-06-21 20:39:02 +02:00
Eli Smith
74abb99752
Add missing fast-fifo dependency (#156)
Co-authored-by: Eli Smith <eli@wavv.com>
2023-06-21 20:38:24 +02:00
Mathias Buus
0490aeda61 3.1.3 2023-06-20 12:56:28 +02:00
Mathias Buus
9629b4ab86 fix dbl stream.end 2023-06-20 12:56:25 +02:00
Mathias Buus
cd05668967 3.1.2 2023-06-19 11:51:04 +02:00
Vadim Dalecky
8f3767181a
fix: 🐛 take care of case when fs is empty object (#152)
In browser environment with current package.json `fs` is empty object,
which results in `constants` being undefined.
2023-06-19 11:50:46 +02:00
Mathias Buus
6c30681b3a 3.1.1 2023-06-17 21:47:48 +02:00
Mathias Buus
77070c668b defer end emit until a read happens 2023-06-17 21:47:29 +02:00
Mathias Buus
2fee69b72e test that streams emit end 2023-06-17 19:15:07 +02:00
8 changed files with 65 additions and 22 deletions

View file

@ -1,12 +1,14 @@
try { const constants = { // just for envs without fs
module.exports = require('fs').constants
} catch {
module.exports = { // just for envs without fs
S_IFMT: 61440, S_IFMT: 61440,
S_IFDIR: 16384, S_IFDIR: 16384,
S_IFCHR: 8192, S_IFCHR: 8192,
S_IFBLK: 24576, S_IFBLK: 24576,
S_IFIFO: 4096, S_IFIFO: 4096,
S_IFLNK: 40960 S_IFLNK: 40960
} }
try {
module.exports = require('fs').constants || constants
} catch {
module.exports = constants
} }

View file

@ -72,6 +72,9 @@ class Source extends Readable {
} }
_read (cb) { _read (cb) {
if (this.header.size === 0) {
this.push(null)
}
if (this._parent._stream === this) { if (this._parent._stream === this) {
this._parent._update() this._parent._update()
} }
@ -160,9 +163,7 @@ class Extract extends Writable {
this._applyLongHeaders() this._applyLongHeaders()
if (this._header.size === 0 || this._header.type === 'directory') { if (this._header.size === 0 || this._header.type === 'directory') {
const stream = this._createStream() this.emit('entry', this._header, this._createStream(), this._unlockBound)
stream.push(null)
this.emit('entry', this._header, stream, this._unlockBound)
return true return true
} }

20
pack.js
View file

@ -11,7 +11,7 @@ const END_OF_TAR = b4a.alloc(1024)
class Sink extends Writable { class Sink extends Writable {
constructor (pack, header, callback) { constructor (pack, header, callback) {
super({ mapWritable }) super({ mapWritable, eagerOpen: true })
this.written = 0 this.written = 0
this.header = header this.header = header
@ -49,6 +49,10 @@ class Sink extends Writable {
this._pack._encode(this.header) this._pack._encode(this.header)
} }
if (this._isVoid) {
this._finish()
}
cb(null) cb(null)
} }
@ -67,7 +71,10 @@ class Sink extends Writable {
this._pack._drain = cb this._pack._drain = cb
} }
_final (cb) { _finish () {
if (this._finished) return
this._finished = true
if (this._isLinkname) { if (this._isLinkname) {
this.header.linkname = this._linkname ? b4a.toString(this._linkname, 'utf-8') : '' this.header.linkname = this._linkname ? b4a.toString(this._linkname, 'utf-8') : ''
this._pack._encode(this.header) this._pack._encode(this.header)
@ -75,13 +82,15 @@ class Sink extends Writable {
overflow(this._pack, this.header.size) overflow(this._pack, this.header.size)
this._pack._done(this)
}
_final (cb) {
if (this.written !== this.header.size) { // corrupting tar if (this.written !== this.header.size) { // corrupting tar
return cb(new Error('Size mismatch')) return cb(new Error('Size mismatch'))
} }
this._pack._done(this) this._finish()
this._finished = true
cb(null) cb(null)
} }
@ -142,7 +151,6 @@ class Pack extends Readable {
} }
if (sink._isVoid) { if (sink._isVoid) {
sink.end()
return sink return sink
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "tar-stream", "name": "tar-stream",
"version": "3.1.0", "version": "3.1.4",
"description": "tar-stream is a streaming tar parser and generator and nothing else. It operates purely using streams which means you can easily extract/parse tarballs without ever hitting the file system.", "description": "tar-stream is a streaming tar parser and generator and nothing else. It operates purely using streams which means you can easily extract/parse tarballs without ever hitting the file system.",
"main": "index.js", "main": "index.js",
"files": [ "files": [
@ -24,6 +24,7 @@
"homepage": "https://github.com/mafintosh/tar-stream", "homepage": "https://github.com/mafintosh/tar-stream",
"dependencies": { "dependencies": {
"b4a": "^1.6.4", "b4a": "^1.6.4",
"fast-fifo": "^1.2.0",
"streamx": "^2.15.0" "streamx": "^2.15.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -251,7 +251,7 @@ test('pax', function (t) {
}) })
test('types', function (t) { test('types', function (t) {
t.plan(3) t.plan(5)
const extract = tar.extract() const extract = tar.extract()
let noEntries = false let noEntries = false
@ -283,6 +283,9 @@ test('types', function (t) {
stream.on('data', function () { stream.on('data', function () {
t.ok(false) t.ok(false)
}) })
stream.on('end', function () {
t.pass('ended')
})
extract.once('entry', onlink) extract.once('entry', onlink)
cb() cb()
} }
@ -306,6 +309,9 @@ test('types', function (t) {
stream.on('data', function () { stream.on('data', function () {
t.ok(false) t.ok(false)
}) })
stream.on('end', function () {
t.pass('ended')
})
noEntries = true noEntries = true
cb() cb()
} }
@ -670,6 +676,26 @@ test('gnu-incremental', function (t) {
extract.end(fs.readFileSync(fixtures.GNU_INCREMENTAL_TAR)) extract.end(fs.readFileSync(fixtures.GNU_INCREMENTAL_TAR))
}) })
test('i-dont-know', function (t) {
t.plan(1)
const extract = tar.extract()
extract.on('entry', function (header, stream, cb) {
console.debug(header.name)
stream.on('end', function () {
cb() // ready for next entry
})
stream.resume()
})
extract.on('finish', function () {
t.ok(true)
})
extract.end(fs.readFileSync(fixtures.I_DONT_KNOW))
})
test('v7 unsupported', function (t) { // correctly fails to parse v7 tarballs test('v7 unsupported', function (t) { // correctly fails to parse v7 tarballs
t.plan(1) t.plan(1)

1
test/fixtures/.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
i-dont-know.tgz filter=lfs diff=lfs merge=lfs -text

BIN
test/fixtures/i-dont-know.tgz (Stored with Git LFS) vendored Normal file

Binary file not shown.

View file

@ -25,3 +25,4 @@ exports.GNU_INCREMENTAL_TAR = path.join(__dirname, 'gnu-incremental.tar')
exports.UNKNOWN_FORMAT = path.join(__dirname, 'unknown-format.tar') exports.UNKNOWN_FORMAT = path.join(__dirname, 'unknown-format.tar')
// Created using gnu tar: tar cf v7.tar --format v7 test.txt // Created using gnu tar: tar cf v7.tar --format v7 test.txt
exports.V7_TAR = path.join(__dirname, 'v7.tar') exports.V7_TAR = path.join(__dirname, 'v7.tar')
exports.I_DONT_KNOW = path.join(__dirname, 'i-dont-know.tgz')