Skip to content
This repository was archived by the owner on Apr 25, 2024. It is now read-only.

Commit 6f3aeb2

Browse files
courajsmafintosh
authored andcommitted
Add finalize: false option to pack(), to allow advanced tar stream manipulation (#65)
* Failing test for finish hooks * Add finish hook support for packing and extracting * Add test for tar.pack() with finalize: false * Add opts.finalize support to tar.pack * Document advanced tar-stream usage
1 parent 4c89247 commit 6f3aeb2

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,26 @@ Copying a directory with permissions and mtime intact is as simple as
130130
tar.pack('source-directory').pipe(tar.extract('dest-directory'))
131131
```
132132

133+
## Interaction with [`tar-stream`](https://github.com/mafintosh/tar-stream)
134+
135+
Use `finalize: false` and the `finish` hook to
136+
leave the pack stream open for further entries (see
137+
[`tar-stream#pack`](https://github.com/mafintosh/tar-stream#packing)),
138+
and use `pack` to pass an existing pack stream.
139+
140+
``` js
141+
var mypack = tar.pack('./my-directory', {
142+
finalize: false,
143+
finish: function(sameAsMypack) {
144+
mypack.entry({name: 'generated-file.txt'}, "hello")
145+
tar.pack('./other-directory', {
146+
pack: sameAsMypack
147+
})
148+
}
149+
})
150+
```
151+
152+
133153
## Performance
134154

135155
Packing and extracting a 6.1 GB with 2496 directories and 2398 files yields the following results on my Macbook Air.

index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ exports.pack = function (cwd, opts) {
7272
var dmode = typeof opts.dmode === 'number' ? opts.dmode : 0
7373
var fmode = typeof opts.fmode === 'number' ? opts.fmode : 0
7474
var pack = opts.pack || tar.pack()
75+
var finish = opts.finish || noop
7576

7677
if (opts.strip) map = strip(map, opts.strip)
7778

@@ -94,7 +95,10 @@ exports.pack = function (cwd, opts) {
9495

9596
var onstat = function (err, filename, stat) {
9697
if (err) return pack.destroy(err)
97-
if (!filename) return pack.finalize()
98+
if (!filename) {
99+
if (opts.finalize !== false) pack.finalize()
100+
return finish(pack)
101+
}
98102

99103
if (stat.isSocket()) return onnextentry() // tar does not support sockets...
100104

@@ -309,6 +313,8 @@ exports.extract = function (cwd, opts) {
309313
})
310314
})
311315

316+
if (opts.finish) extract.on('finish', opts.finish)
317+
312318
return extract
313319
}
314320

test/index.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,70 @@ test('check type while mapping header on packing', function (t) {
225225

226226
tar.pack(e, { map: checkHeaderType })
227227
})
228+
229+
test('finish callbacks', function (t) {
230+
t.plan(3)
231+
232+
var a = path.join(__dirname, 'fixtures', 'a')
233+
var b = path.join(__dirname, 'fixtures', 'copy', 'a')
234+
235+
rimraf.sync(b)
236+
237+
var packEntries = 0
238+
var extractEntries = 0
239+
240+
var countPackEntry = function (header) { packEntries++ }
241+
var countExtractEntry = function (header) { extractEntries++ }
242+
243+
var pack
244+
var onPackFinish = function (passedPack) {
245+
t.equal(packEntries, 2, 'All entries have been packed') // 2 entries - the file and base directory
246+
t.equal(passedPack, pack, 'The finish hook passes the pack')
247+
}
248+
249+
var onExtractFinish = function () { t.equal(extractEntries, 2) }
250+
251+
pack = tar.pack(a, {map: countPackEntry, finish: onPackFinish})
252+
253+
pack.pipe(tar.extract(b, {map: countExtractEntry, finish: onExtractFinish}))
254+
.on('finish', function () {
255+
t.end()
256+
})
257+
})
258+
259+
test('not finalizing the pack', function (t) {
260+
t.plan(2)
261+
262+
var a = path.join(__dirname, 'fixtures', 'a')
263+
var b = path.join(__dirname, 'fixtures', 'b')
264+
265+
var out = path.join(__dirname, 'fixtures', 'copy', 'merged-packs')
266+
267+
rimraf.sync(out)
268+
269+
var prefixer = function (prefix) {
270+
return function (header) {
271+
header.name = path.join(prefix, header.name)
272+
return header
273+
}
274+
}
275+
276+
tar.pack(a, {
277+
map: prefixer('a-files'),
278+
finalize: false,
279+
finish: packB
280+
})
281+
282+
function packB (pack) {
283+
tar.pack(b, {pack: pack, map: prefixer('b-files')})
284+
.pipe(tar.extract(out))
285+
.on('finish', assertResults)
286+
}
287+
288+
function assertResults () {
289+
var containers = fs.readdirSync(out)
290+
t.deepEqual(containers, ['a-files', 'b-files'])
291+
var aFiles = fs.readdirSync(path.join(out, 'a-files'))
292+
t.deepEqual(aFiles, ['hello.txt'])
293+
}
294+
})

0 commit comments

Comments
 (0)