Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit e5e9e6d

Browse files
authored
Merge pull request #14 from YtvwlD/bzip2
Support bzip2
2 parents 5b08c9b + fa6c8d3 commit e5e9e6d

12 files changed

+259
-2
lines changed

Diff for: README.md

+14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ Supported file extensions:
1111
* .tar
1212
* .tar.gz
1313
* .tgz
14+
* .tar.bz2
15+
* .tbz
16+
* .tbz2
1417
* .war
1518
* .zip
1619
* .egg
@@ -69,6 +72,17 @@ Buffer contents of the uncompressed paths. The `callback` gets two arguments
6972
`callback` - The function to call after reading completes with an error or
7073
the Buffer contents.
7174

75+
### archive.readBzip(bzipArchivePath, callback)
76+
77+
Read the contents of the bzipped archive path and invoke the callback with the
78+
Buffer contents of the uncompressed paths. The `callback` gets two arguments
79+
`(error, pathContents)`.
80+
81+
`bzipArchivePath` - The string path to the bzipped archive file.
82+
83+
`callback` - The function to call after reading completes with an error or
84+
the Buffer contents.
85+
7286
### ArchiveEntry
7387

7488
Class representing a path entry inside an archive file.

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"async": "~0.2.9",
5555
"colors": "~0.6.2",
5656
"rimraf": "~2.2.6",
57+
"unbzip2-stream": "^1.3.3",
5758
"yauzl": "^2.9.1"
5859
}
5960
}

Diff for: spec/bzip-spec.coffee

+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
archive = require '../lib/ls-archive'
2+
path = require 'path'
3+
4+
describe "bzipped tar files", ->
5+
fixturesRoot = null
6+
7+
beforeEach ->
8+
fixturesRoot = path.join(__dirname, 'fixtures')
9+
10+
describe ".list()", ->
11+
describe "when the archive file exists", ->
12+
it "returns files in the bzipped tar archive", ->
13+
bzipPaths = null
14+
callback = (error, paths) -> bzipPaths = paths
15+
archive.list(path.join(fixturesRoot, 'one-file.tar.bz2'), callback)
16+
waitsFor -> bzipPaths?
17+
runs ->
18+
expect(bzipPaths.length).toBe 1
19+
expect(bzipPaths[0].path).toBe 'file.txt'
20+
expect(bzipPaths[0].isDirectory()).toBe false
21+
expect(bzipPaths[0].isFile()).toBe true
22+
expect(bzipPaths[0].isSymbolicLink()).toBe false
23+
24+
it "returns files in the bzipped tar archive", ->
25+
bzipPaths = null
26+
callback = (error, paths) -> bzipPaths = paths
27+
archive.list(path.join(fixturesRoot, 'one-file.tbz'), callback)
28+
waitsFor -> bzipPaths?
29+
runs ->
30+
expect(bzipPaths.length).toBe 1
31+
expect(bzipPaths[0].path).toBe 'file.txt'
32+
expect(bzipPaths[0].isDirectory()).toBe false
33+
expect(bzipPaths[0].isFile()).toBe true
34+
expect(bzipPaths[0].isSymbolicLink()).toBe false
35+
36+
it "returns files in the bzipped tar archive", ->
37+
bzipPaths = null
38+
callback = (error, paths) -> bzipPaths = paths
39+
archive.list(path.join(fixturesRoot, 'one-file.tbz2'), callback)
40+
waitsFor -> bzipPaths?
41+
runs ->
42+
expect(bzipPaths.length).toBe 1
43+
expect(bzipPaths[0].path).toBe 'file.txt'
44+
expect(bzipPaths[0].isDirectory()).toBe false
45+
expect(bzipPaths[0].isFile()).toBe true
46+
expect(bzipPaths[0].isSymbolicLink()).toBe false
47+
48+
it "returns folders in the bzipped tar archive", ->
49+
bzipPaths = null
50+
callback = (error, paths) -> bzipPaths = paths
51+
archive.list(path.join(fixturesRoot, 'one-folder.tar.bz2'), callback)
52+
waitsFor -> bzipPaths?
53+
runs ->
54+
expect(bzipPaths.length).toBe 1
55+
expect(bzipPaths[0].path).toBe 'folder'
56+
expect(bzipPaths[0].isDirectory()).toBe true
57+
expect(bzipPaths[0].isFile()).toBe false
58+
expect(bzipPaths[0].isSymbolicLink()).toBe false
59+
60+
it "returns folders in the bzipped tar archive", ->
61+
bzipPaths = null
62+
callback = (error, paths) -> bzipPaths = paths
63+
archive.list(path.join(fixturesRoot, 'one-folder.tbz'), callback)
64+
waitsFor -> bzipPaths?
65+
runs ->
66+
expect(bzipPaths.length).toBe 1
67+
expect(bzipPaths[0].path).toBe 'folder'
68+
expect(bzipPaths[0].isDirectory()).toBe true
69+
expect(bzipPaths[0].isFile()).toBe false
70+
expect(bzipPaths[0].isSymbolicLink()).toBe false
71+
72+
it "returns folders in the bzipped tar archive", ->
73+
bzipPaths = null
74+
callback = (error, paths) -> bzipPaths = paths
75+
archive.list(path.join(fixturesRoot, 'one-folder.tbz2'), callback)
76+
waitsFor -> bzipPaths?
77+
runs ->
78+
expect(bzipPaths.length).toBe 1
79+
expect(bzipPaths[0].path).toBe 'folder'
80+
expect(bzipPaths[0].isDirectory()).toBe true
81+
expect(bzipPaths[0].isFile()).toBe false
82+
expect(bzipPaths[0].isSymbolicLink()).toBe false
83+
84+
describe "when the archive path does not exist", ->
85+
it "calls back with an error", ->
86+
archivePath = path.join(fixturesRoot, 'not-a-file.tar.bz2')
87+
pathError = null
88+
callback = (error) -> pathError = error
89+
archive.list(archivePath, callback)
90+
waitsFor -> pathError?
91+
runs -> expect(pathError.message.length).toBeGreaterThan 0
92+
93+
describe "when the archive path isn't a valid bzipped tar file", ->
94+
it "calls back with an error", ->
95+
archivePath = path.join(fixturesRoot, 'invalid.tar.bz2')
96+
pathError = null
97+
callback = (error) -> pathError = error
98+
archive.list(archivePath, callback)
99+
waitsFor -> pathError?
100+
runs -> expect(pathError.message.length).toBeGreaterThan 0
101+
102+
describe "when the second to last extension isn't .tar", ->
103+
it "calls back with an error", ->
104+
archivePath = path.join(fixturesRoot, 'invalid.txt.bz2')
105+
pathError = null
106+
callback = (error, contents) -> pathError = error
107+
archive.list(archivePath, callback)
108+
waitsFor -> pathError?
109+
runs -> expect(pathError.message.length).toBeGreaterThan 0
110+
111+
describe ".readFile()", ->
112+
describe "when the path exists in the archive", ->
113+
it "calls back with the contents of the given path", ->
114+
archivePath = path.join(fixturesRoot, 'one-file.tar.bz2')
115+
pathContents = null
116+
callback = (error, contents) -> pathContents = contents
117+
archive.readFile(archivePath, 'file.txt', callback)
118+
waitsFor -> pathContents?
119+
runs -> expect(pathContents.toString()).toBe 'hello\n'
120+
121+
it "calls back with the contents of the given path", ->
122+
archivePath = path.join(fixturesRoot, 'one-file.tbz')
123+
pathContents = null
124+
callback = (error, contents) -> pathContents = contents
125+
archive.readFile(archivePath, 'file.txt', callback)
126+
waitsFor -> pathContents?
127+
runs -> expect(pathContents.toString()).toBe 'hello\n'
128+
129+
it "calls back with the contents of the given path", ->
130+
archivePath = path.join(fixturesRoot, 'one-file.tbz2')
131+
pathContents = null
132+
callback = (error, contents) -> pathContents = contents
133+
archive.readFile(archivePath, 'file.txt', callback)
134+
waitsFor -> pathContents?
135+
runs -> expect(pathContents.toString()).toBe 'hello\n'
136+
137+
describe "when the path does not exist in the archive", ->
138+
it "calls back with an error", ->
139+
archivePath = path.join(fixturesRoot, 'one-file.tar.bz2')
140+
pathError = null
141+
callback = (error, contents) -> pathError = error
142+
archive.readFile(archivePath, 'not-a-file.txt', callback)
143+
waitsFor -> pathError?
144+
runs -> expect(pathError.message.length).toBeGreaterThan 0
145+
146+
describe "when the archive path does not exist", ->
147+
it "calls back with an error", ->
148+
archivePath = path.join(fixturesRoot, 'not-a-file.tar.bz2')
149+
pathError = null
150+
callback = (error, contents) -> pathError = error
151+
archive.readFile(archivePath, 'not-a-file.txt', callback)
152+
waitsFor -> pathError?
153+
runs -> expect(pathError.message.length).toBeGreaterThan 0
154+
155+
describe "when the archive path isn't a valid bzipped tar file", ->
156+
it "calls back with an error", ->
157+
archivePath = path.join(fixturesRoot, 'invalid.tar.bz2')
158+
pathError = null
159+
callback = (error, contents) -> pathError = error
160+
archive.readFile(archivePath, 'invalid.txt', callback)
161+
waitsFor -> pathError?
162+
runs -> expect(pathError.message.length).toBeGreaterThan 0
163+
164+
describe "when the second to last extension isn't .tar", ->
165+
it "calls back with an error", ->
166+
archivePath = path.join(fixturesRoot, 'invalid.txt.bz2')
167+
pathError = null
168+
callback = (error, contents) -> pathError = error
169+
archive.readFile(archivePath, 'invalid.txt', callback)
170+
waitsFor -> pathError?
171+
runs -> expect(pathError.message.length).toBeGreaterThan 0
172+
173+
describe ".readBzip()", ->
174+
it "calls back with the string contents of the archive", ->
175+
archivePath = path.join(fixturesRoot, 'file.txt.bz2')
176+
archiveContents = null
177+
callback = (error, contents) -> archiveContents = contents
178+
archive.readBzip(archivePath, callback)
179+
waitsFor -> archiveContents?
180+
runs -> expect(archiveContents.toString()).toBe 'hello\n'
181+
182+
describe "when the archive path isn't a valid bzipped tar file", ->
183+
it "calls back with an error", ->
184+
archivePath = path.join(fixturesRoot, 'invalid.tar.bz2')
185+
readError = null
186+
callback = (error, contents) -> readError = error
187+
archive.readBzip(archivePath, callback)
188+
waitsFor -> readError?
189+
runs -> expect(readError.message.length).toBeGreaterThan 0
190+
191+
describe "when the archive path does not exist", ->
192+
it "calls back with an error", ->
193+
archivePath = path.join(fixturesRoot, 'not-a-file.tar.bz2')
194+
readError = null
195+
callback = (error, contents) -> readError = error
196+
archive.readBzip(archivePath, callback)
197+
waitsFor -> readError?
198+
runs -> expect(readError.message.length).toBeGreaterThan 0

Diff for: spec/fixtures/file.txt.bz2

42 Bytes
Binary file not shown.

Diff for: spec/fixtures/one-file.tar.bz2

135 Bytes
Binary file not shown.

Diff for: spec/fixtures/one-file.tbz

135 Bytes
Binary file not shown.

Diff for: spec/fixtures/one-file.tbz2

135 Bytes
Binary file not shown.

Diff for: spec/fixtures/one-folder.tar.bz2

126 Bytes
Binary file not shown.

Diff for: spec/fixtures/one-folder.tbz

126 Bytes
Binary file not shown.

Diff for: spec/fixtures/one-folder.tbz2

126 Bytes
Binary file not shown.

Diff for: src/ls-archive-cli.coffee

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = ->
1010
1111
List the files and folders inside an archive file.
1212
13-
Supports .zip, .tar, .tar.gz, and .tgz files.
13+
Supports .zip, .tar, .tar.gz, .tgz, .tar.bz2, .tbz and .tbz2 files.
1414
""")
1515
.describe('colors', 'Enable colored output').default('colors', true).boolean('colors')
1616
.describe('help', 'Show this message').alias('h', 'help')

Diff for: src/ls-archive.coffee

+45-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ listGzip = (archivePath, options, callback) ->
9191
gzipStream.on 'error', callback
9292
listTarStream(gzipStream, options, callback)
9393

94+
listBzip = (archivePath, options, callback) ->
95+
bzip = require 'unbzip2-stream'
96+
fileStream = fs.createReadStream(archivePath)
97+
fileStream.on 'error', callback
98+
bzipStream = fileStream.pipe(bzip())
99+
bzipStream.on 'error', callback
100+
listTarStream(bzipStream, options, callback)
101+
94102
listTar = (archivePath, options, callback) ->
95103
fileStream = fs.createReadStream(archivePath)
96104
fileStream.on 'error', callback
@@ -139,6 +147,15 @@ readFileFromGzip = (archivePath, filePath, callback) ->
139147
callback("#{filePath} does not exist in the archive: #{archivePath}")
140148
readFileFromTarStream(gzipStream, archivePath, filePath, callback)
141149

150+
readFileFromBzip = (archivePath, filePath, callback) ->
151+
fileStream = fs.createReadStream(archivePath)
152+
fileStream.on 'error', callback
153+
bzipStream = fileStream.pipe(require('unbzip2-stream')())
154+
bzipStream.on 'error', callback
155+
bzipStream.on 'end', ->
156+
callback("#{filePath} does not exist in the archive: #{archivePath}")
157+
readFileFromTarStream(bzipStream, archivePath, filePath, callback)
158+
142159
readFileFromTar = (archivePath, filePath, callback) ->
143160
fileStream = fs.createReadStream(archivePath)
144161
fileStream.on 'error', callback
@@ -175,10 +192,18 @@ isGzipPath = (archivePath) ->
175192
path.extname(archivePath) is '.tgz' or
176193
path.extname(path.basename(archivePath, '.gz')) is '.tar'
177194

195+
isBzipPath = (archivePath) ->
196+
path.extname(archivePath) is '.tbz' or
197+
path.extname(archivePath) is '.tbz2' or
198+
path.extname(path.basename(archivePath, '.bz2')) is '.tar'
199+
178200
module.exports =
179201
isPathSupported: (archivePath) ->
180202
return false unless archivePath
181-
isTarPath(archivePath) or isZipPath(archivePath) or isGzipPath(archivePath)
203+
isTarPath(archivePath) or
204+
isZipPath(archivePath) or
205+
isGzipPath(archivePath) or
206+
isBzipPath(archivePath)
182207

183208
list: (archivePath, options={}, callback) ->
184209
if typeof options is 'function'
@@ -189,6 +214,8 @@ module.exports =
189214
listTar(archivePath, options, wrapCallback(callback))
190215
else if isGzipPath(archivePath)
191216
listGzip(archivePath, options, wrapCallback(callback))
217+
else if isBzipPath(archivePath)
218+
listBzip(archivePath, options, wrapCallback(callback))
192219
else if isZipPath(archivePath)
193220
listZip(archivePath, options, wrapCallback(callback))
194221
else
@@ -200,6 +227,8 @@ module.exports =
200227
readFileFromTar(archivePath, filePath, wrapCallback(callback))
201228
else if isGzipPath(archivePath)
202229
readFileFromGzip(archivePath, filePath, wrapCallback(callback))
230+
else if isBzipPath(archivePath)
231+
readFileFromBzip(archivePath, filePath, wrapCallback(callback))
203232
else if isZipPath(archivePath)
204233
readFileFromZip(archivePath, filePath, wrapCallback(callback))
205234
else
@@ -220,3 +249,18 @@ module.exports =
220249
chunks.push(chunk)
221250
gzipStream.on 'end', ->
222251
callback(null, Buffer.concat(chunks))
252+
253+
readBzip: (bzipArchivePath, callback) ->
254+
callback = wrapCallback(callback)
255+
256+
bzip = require 'unbzip2-stream'
257+
fileStream = fs.createReadStream(bzipArchivePath)
258+
fileStream.on 'error', callback
259+
bzipStream = fileStream.pipe(bzip())
260+
bzipStream.on 'error', callback
261+
262+
chunks = []
263+
bzipStream.on 'data', (chunk) ->
264+
chunks.push(chunk)
265+
bzipStream.on 'end', ->
266+
callback(null, Buffer.concat(chunks))

0 commit comments

Comments
 (0)