Support comic book archives

This commit is contained in:
Bastian Kleineidam 2016-01-09 20:58:15 +01:00
parent 1d121c4c79
commit 06166e7b1d
28 changed files with 99 additions and 31 deletions

View File

@ -3,26 +3,26 @@ Patool
Patool is an archive file manager.
Various archive formats can be created, extracted, tested, listed,
searched, repacked and compared with patool. The advantage of patool is its simplicity in
handling archive files without having to remember a myriad of
programs and options.
Various archive formats can be created, extracted, tested, listed,
searched, repacked and compared with patool. The advantage of patool is
its simplicity in handling archive files without having to remember a
myriad of programs and options.
The archive format is determined by the file(1) program and as
a fallback by the archive file extension.
patool supports 7z (.7z), ACE (.ace), ADF (.adf), ALZIP (.alz),
patool supports 7z (.7z, .cb7), ACE (.ace, .cba), ADF (.adf), ALZIP (.alz),
APE (.ape), AR (.a), ARC (.arc), ARJ (.arj), BZIP2 (.bz2),
CAB (.cab), COMPRESS (.Z), CPIO (.cpio), DEB (.deb), DMS (.dms),
FLAC (.flac), GZIP (.gz), ISO (.iso), LRZIP (.lrz), LZH (.lha, .lzh),
LZIP (.lz), LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar),
RZIP (.rz), SHN (.shn), TAR (.tar), XZ (.xz), ZIP (.zip, .jar) and
ZOO (.zoo) formats. It relies on helper applications to handle
those archive formats (for example bzip2 for BZIP2 archives).
LZIP (.lz), LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar, .cbr),
RZIP (.rz), SHN (.shn), TAR (.tar, .cbt), XZ (.xz),
ZIP (.zip, .jar, .cbz) and ZOO (.zoo) archive formats.
It relies on helper applications to handle those archive formats
(for example bzip2 for BZIP2 archives).
The archive formats TAR, ZIP, BZIP2 and GZIP
are supported natively and do not require helper
applications to be installed.
The archive formats TAR, ZIP, BZIP2 and GZIP are supported natively
and do not require helper applications to be installed.
Examples
---------

View File

@ -1,6 +1,8 @@
1.11 (released xx.xx.216)
* Fix 7z unpacking when only p7zip with /usr/bin/7zr is installed.
* Support comic book archives: .cb7 for 7z, .cba for ACE, .cbr for RAR,
.cbt for TAR and .cbz for ZIP archives.
1.10 (released 10.12.2015)

View File

@ -25,12 +25,14 @@ files without having to remember a myriad of programs and options.
The archive format is determined by the file(1) program and as a fallback
by the archive file extension.
.PP
\fBpatool\fP supports 7z (.7z), ACE (.ace), ADF (.adf), ALZIP (.alz),
APE (.ape), AR (.a), ARC (.arc), ARJ (.arj),
\fBpatool\fP supports 7z (.7z, .cb7), ACE (.ace, .cba), ADF (.adf),
ALZIP (.alz), APE (.ape), AR (.a), ARC (.arc), ARJ (.arj),
BZIP2 (.bz2), CAB (.cab), COMPRESS (.Z), CPIO (.cpio), DEB (.deb), DMS (.dms),
FLAC (.flac), GZIP (.gz), ISO (.iso), LRZIP (.lrz), LZH (.lha, .lzh), LZIP (.lz),
LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar), RZIP (.rz), SHN (.shn),
TAR (.tar), XZ (.xz), ZIP (.zip, .jar), ZOO (.zoo) and ZPAQ (.zpaq) formats.
FLAC (.flac), GZIP (.gz), ISO (.iso), LRZIP (.lrz), LZH (.lha, .lzh),
LZIP (.lz), LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar, .cbr),
RZIP (.rz), SHN (.shn), TAR (.tar, .cbt), XZ (.xz), ZIP (.zip, .jar, .cbz),
ZOO (.zoo) and ZPAQ (.zpaq) archive formats.
.br
It relies on helper applications to handle those archive formats
(for example bzip2 for BZIP2 archives).
.PP

View File

@ -20,15 +20,16 @@ DESCRIPTION
The archive format is determined by the file(1) program and as
a fallback by the archive file extension.
patool supports 7z (.7z), ACE (.ace), ADF (.adf), ALZIP (.alz),
APE (.ape), AR (.a), ARC (.arc), ARJ (.arj), BZIP2 (.bz2), CAB
(.cab), COMPRESS (.Z), CPIO (.cpio), DEB (.deb), DMS (.dms),
FLAC (.flac), GZIP (.gz), ISO (.iso), LRZIP (.lrz), LZH (.lha,
.lzh), LZIP (.lz), LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR
(.rar), RZIP (.rz), SHN (.shn), TAR (.tar), XZ (.xz), ZIP
(.zip, .jar), ZOO (.zoo) and ZPAQ (.zpaq) formats. It relies
on helper applications to handle those archive formats (for
example bzip2 for BZIP2 archives).
patool supports 7z (.7z, .cb7), ACE (.ace, .cba), ADF (.adf),
ALZIP (.alz), APE (.ape), AR (.a), ARC (.arc), ARJ (.arj),
BZIP2 (.bz2), CAB (.cab), COMPRESS (.Z), CPIO (.cpio), DEB
(.deb), DMS (.dms), FLAC (.flac), GZIP (.gz), ISO (.iso), LRZIP
(.lrz), LZH (.lha, .lzh), LZIP (.lz), LZMA (.lzma), LZOP
(.lzo), RPM (.rpm), RAR (.rar, .cbr), RZIP (.rz), SHN (.shn),
TAR (.tar, .cbt), XZ (.xz), ZIP (.zip, .jar, .cbz), ZOO (.zoo)
and ZPAQ (.zpaq) archive formats.
It relies on helper applications to handle those archive for
mats (for example bzip2 for BZIP2 archives).
The archive formats TAR, ZIP, BZIP2 and GZIP are supported
natively and do not require helper applications to be

View File

@ -109,11 +109,14 @@ def add_mimedb_data(mimedb):
add_mimetype(mimedb, 'application/x-xz', '.xz')
add_mimetype(mimedb, 'application/java-archive', '.jar')
add_mimetype(mimedb, 'application/x-rar', '.rar')
add_mimetype(mimedb, 'application/x-rar', '.cbr')
add_mimetype(mimedb, 'application/x-7z-compressed', '.7z')
add_mimetype(mimedb, 'application/x-7z-compressed', '.cb7')
add_mimetype(mimedb, 'application/x-cab', '.cab')
add_mimetype(mimedb, 'application/x-rpm', '.rpm')
add_mimetype(mimedb, 'application/x-debian-package', '.deb')
add_mimetype(mimedb, 'application/x-ace', '.ace')
add_mimetype(mimedb, 'application/x-ace', '.cba')
add_mimetype(mimedb, 'application/x-archive', '.a')
add_mimetype(mimedb, 'application/x-alzip', '.alz')
add_mimetype(mimedb, 'application/x-arc', '.arc')
@ -125,12 +128,14 @@ def add_mimedb_data(mimedb):
add_mimetype(mimedb, 'application/x-dms', '.dms')
add_mimetype(mimedb, 'application/x-zip-compressed', '.crx')
add_mimetype(mimedb, 'application/x-shar', '.shar')
add_mimetype(mimedb, 'application/x-tar', '.cbt')
add_mimetype(mimedb, 'application/x-vhd', '.vhd')
add_mimetype(mimedb, 'audio/x-ape', '.ape')
add_mimetype(mimedb, 'audio/x-shn', '.shn')
add_mimetype(mimedb, 'audio/flac', '.flac')
add_mimetype(mimedb, 'application/x-chm', '.chm')
add_mimetype(mimedb, 'application/x-iso9660-image', '.iso')
add_mimetype(mimedb, 'application/zip', '.cbz')
add_mimetype(mimedb, 'application/zip', '.epub')
add_mimetype(mimedb, 'application/zip', '.apk')
add_mimetype(mimedb, 'application/zpaq', '.zpaq')

View File

@ -23,7 +23,9 @@ class Test7z (ArchiveTest):
@needs_program(program)
def test_7z (self):
self.archive_commands('t .7z')
self.archive_commands('t .cb7')
self.archive_commands('t.zip')
self.archive_commands('t.cbz')
self.archive_commands('t.txt.xz', check=Content.Singlefile)
self.archive_list('t.txt.gz')
self.archive_list('t.txt.bz2')
@ -75,7 +77,9 @@ class Test7z (ArchiveTest):
@needs_program(program)
def test_7z_file (self):
self.archive_commands('t.7z.foo', skip_create=True)
self.archive_commands('t.cb7.foo', skip_create=True)
self.archive_commands('t.zip.foo', skip_create=True)
self.archive_commands('t.cbz.foo', skip_create=True)
self.archive_commands('t.txt.xz.foo', skip_create=True, check=Content.Singlefile)
self.archive_list('t.txt.gz.foo')
self.archive_list('t.txt.bz2.foo')

View File

@ -23,7 +23,9 @@ class Test7za (ArchiveTest):
@needs_program(program)
def test_p7azip (self):
self.archive_commands('t .7z')
self.archive_commands('t .cb7')
self.archive_commands('t.zip')
self.archive_commands('t.cbz')
self.archive_list('t.txt.gz')
self.archive_list('t.txt.bz2')
self.archive_list('t.jar')
@ -47,7 +49,9 @@ class Test7za (ArchiveTest):
@needs_program(program)
def test_7za_file (self):
self.archive_commands('t.7z.foo', skip_create=True)
self.archive_commands('t.cb7.foo', skip_create=True)
self.archive_commands('t.zip.foo', skip_create=True)
self.archive_commands('t.cbz.foo', skip_create=True)
self.archive_list('t.txt.gz.foo')
self.archive_list('t.txt.bz2.foo')
self.archive_list('t.jar.foo')

View File

@ -23,8 +23,10 @@ class Test7zr (ArchiveTest):
@needs_program(program)
def test_7zr (self):
self.archive_commands('t .7z')
self.archive_commands('t .cb7')
@needs_program('file')
@needs_program(program)
def test_7z_file (self):
self.archive_commands('t.7z.foo', skip_create=True)
self.archive_commands('t.cb7.foo', skip_create=True)

View File

@ -23,6 +23,7 @@ class TestBsdtar (ArchiveTest):
@needs_program(program)
def test_bsdtar (self):
self.archive_commands('t.tar')
self.archive_commands('t.cbt')
@needs_codec(program, 'gzip')
def test_bsdtar_gz (self):
@ -58,6 +59,7 @@ class TestBsdtar (ArchiveTest):
@needs_program(program)
def test_bsdtar_file (self):
self.archive_commands('t.tar.foo', skip_create=True)
self.archive_commands('t.cbt.foo', skip_create=True)
@needs_program('file')
@needs_codec(program, 'gzip')

View File

@ -22,6 +22,7 @@ class TestPytarfile (ArchiveTest):
def test_py_tarfile (self):
self.archive_commands('t.tar')
self.archive_commands('t.cbt')
def test_py_tarfile_gz (self):
self.archive_commands('t.tar.gz')
@ -34,6 +35,7 @@ class TestPytarfile (ArchiveTest):
@needs_program('file')
def test_py_tarfile_file (self):
self.archive_commands('t.tar.foo', skip_create=True)
self.archive_commands('t.cbt.foo', skip_create=True)
@needs_program('file')
def test_py_tarfile_gz_file (self):
@ -44,4 +46,3 @@ class TestPytarfile (ArchiveTest):
def test_py_tarfile_bz2_file (self):
self.archive_commands('t.tar.bz2.foo', skip_create=True)
self.archive_commands('t.tbz2.foo', skip_create=True)

View File

@ -22,8 +22,10 @@ class TestPyzipfile (ArchiveTest):
def test_py_zipfile(self):
self.archive_commands('t.zip')
self.archive_commands('t.cbz')
@needs_program('file')
def test_py_zipfile_file(self):
self.archive_commands('t.zip.foo', skip_create=True)
self.archive_commands('t.cbz.foo', skip_create=True)

View File

@ -23,9 +23,11 @@ class TestRar (ArchiveTest):
@needs_program(program)
def test_rar(self):
self.archive_commands('t.rar')
self.archive_commands('t.cbr')
@needs_program('file')
@needs_program(program)
def test_rar_file(self):
self.archive_commands('t.rar.foo', skip_create=True)
self.archive_commands('t.cbr.foo', skip_create=True)

View File

@ -23,6 +23,7 @@ class TestStar (ArchiveTest):
@needs_program(program)
def test_star (self):
self.archive_commands('t.tar')
self.archive_commands('t.cbt')
@needs_codec(program, 'gzip')
def test_star_gz (self):
@ -57,6 +58,7 @@ class TestStar (ArchiveTest):
@needs_program(program)
def test_star_file (self):
self.archive_commands('t.tar.foo', skip_create=True)
self.archive_commands('t.cbt.foo', skip_create=True)
@needs_program('file')
@needs_codec(program, 'gzip')
@ -91,4 +93,3 @@ class TestStar (ArchiveTest):
@needs_codec(program, 'xz')
def test_star_xz_file (self):
self.archive_commands('t.tar.xz.foo', skip_create=True)

View File

@ -23,6 +23,7 @@ class TestTar (ArchiveTest):
@needs_program(program)
def test_tar (self):
self.archive_commands('t.tar')
self.archive_commands('t.cbt')
@needs_codec(program, 'gzip')
def test_tar_gz (self):
@ -59,6 +60,7 @@ class TestTar (ArchiveTest):
@needs_program(program)
def test_tar_file (self):
self.archive_commands('t.tar.foo', skip_create=True)
self.archive_commands('t.cbt.foo', skip_create=True)
@needs_program('file')
@needs_codec(program, 'gzip')
@ -96,4 +98,3 @@ class TestTar (ArchiveTest):
@needs_codec(program, 'xz')
def test_tar_xz_file (self):
self.archive_commands('t.tar.xz.foo', skip_create=True)

View File

@ -25,6 +25,9 @@ class TestUnace (ArchiveTest):
self.archive_list('t.ace')
self.archive_test('t.ace')
self.archive_extract('t.ace')
self.archive_list('t.cba')
self.archive_test('t.cba')
self.archive_extract('t.cba')
@needs_program('file')
@needs_program(program)
@ -32,4 +35,6 @@ class TestUnace (ArchiveTest):
self.archive_list('t.ace.foo')
self.archive_test('t.ace.foo')
self.archive_extract('t.ace.foo')
self.archive_list('t.cba.foo')
self.archive_test('t.cba.foo')
self.archive_extract('t.cba.foo')

View File

@ -25,12 +25,16 @@ class TestUnzip (ArchiveTest):
self.archive_extract('t.zip', check=None)
self.archive_list('t.zip')
self.archive_test('t.zip')
self.archive_extract('t.cbz', check=None)
self.archive_list('t.cbz')
self.archive_test('t.cbz')
self.archive_extract('t.jar', check=None)
self.archive_list('t.jar')
self.archive_test('t.jar')
self.archive_extract('t.epub', check=None)
self.archive_list('t.epub')
self.archive_test('t.epub')
self.archive_extract('t.apk', check=None)
self.archive_list('t.apk')
self.archive_test('t.apk')
@ -40,11 +44,15 @@ class TestUnzip (ArchiveTest):
self.archive_extract('t.zip.foo', check=None)
self.archive_list('t.zip.foo')
self.archive_test('t.zip.foo')
self.archive_extract('t.cbz.foo', check=None)
self.archive_list('t.cbz.foo')
self.archive_test('t.cbz.foo')
self.archive_extract('t.jar.foo', check=None)
self.archive_list('t.jar.foo')
self.archive_test('t.jar.foo')
self.archive_extract('t.epub.foo', check=None)
self.archive_list('t.epub.foo')
self.archive_test('t.epub.foo')
self.archive_extract('t.apk.foo', check=None)
self.archive_list('t.apk.foo')
self.archive_test('t.apk.foo')

View File

@ -24,8 +24,20 @@ class TestZip (ArchiveTest):
def test_zip (self):
self.archive_create('t.zip')
self.archive_test('t.zip')
self.archive_create('t.cbz')
self.archive_test('t.cbz')
self.archive_create('t.apk')
self.archive_test('t.apk')
self.archive_create('t.jar')
self.archive_test('t.jar')
self.archive_create('t.epub')
self.archive_test('t.epub')
@needs_program('file')
@needs_program(program)
def test_zip_file (self):
self.archive_test('t.zip.foo')
self.archive_test('t.cbz.foo')
self.archive_test('t.apk.foo')
self.archive_test('t.jar.foo')
self.archive_test('t.epub.foo')

BIN
tests/data/t .cb7 Normal file

Binary file not shown.

BIN
tests/data/t.cb7.foo Normal file

Binary file not shown.

BIN
tests/data/t.cba Normal file

Binary file not shown.

BIN
tests/data/t.cba.foo Normal file

Binary file not shown.

BIN
tests/data/t.cbr Normal file

Binary file not shown.

BIN
tests/data/t.cbr.foo Normal file

Binary file not shown.

BIN
tests/data/t.cbt Normal file

Binary file not shown.

BIN
tests/data/t.cbt.foo Normal file

Binary file not shown.

BIN
tests/data/t.cbz Normal file

Binary file not shown.

BIN
tests/data/t.cbz.foo Normal file

Binary file not shown.

View File

@ -46,7 +46,8 @@ class TestMime (unittest.TestCase):
@needs_program('file')
def test_mime_file (self):
self.mime_test_file("t .7z", "application/x-7z-compressed")
self.mime_test_file("t.7z.foo", "application/x-7z-compressed")
self.mime_test_file("t .cb7", "application/x-7z-compressed")
self.mime_test_file("t.cb7.foo", "application/x-7z-compressed")
self.mime_test_file("t.arj", "application/x-arj")
self.mime_test_file("t.arj.foo", "application/x-arj")
self.mime_test_file("t.txt.bz2", "application/x-bzip2")
@ -69,10 +70,14 @@ class TestMime (unittest.TestCase):
self.mime_test_file("t.txt.lzo.foo", "application/x-lzop")
self.mime_test_file("t.rar", "application/x-rar")
self.mime_test_file("t.rar.foo", "application/x-rar")
self.mime_test_file("t.cbr", "application/x-rar")
self.mime_test_file("t.cbr.foo", "application/x-rar")
self.mime_test_file("t.rpm", "application/x-rpm")
self.mime_test_file("t.rpm.foo", "application/x-rpm")
self.mime_test_file("t.tar", "application/x-tar")
self.mime_test_file("t.tar.foo", "application/x-tar")
self.mime_test_file("t.cbt", "application/x-tar")
self.mime_test_file("t.cbt.foo", "application/x-tar")
self.mime_test_file("t.tar.lz", "application/x-tar", "lzip")
self.mime_test_file("t.tar.bz2", "application/x-tar", "bzip2")
self.mime_test_file("t.tbz2", "application/x-tar", "bzip2")
@ -92,8 +97,12 @@ class TestMime (unittest.TestCase):
self.mime_test_file("t.jar.foo", "application/zip")
self.mime_test_file("t.zip", "application/zip")
self.mime_test_file("t.zip.foo", "application/zip")
self.mime_test_file("t.cbz", "application/zip")
self.mime_test_file("t.cbz.foo", "application/zip")
self.mime_test_file("t.ace", "application/x-ace")
self.mime_test_file("t.ace.foo", "application/x-ace")
self.mime_test_file("t.cba", "application/x-ace")
self.mime_test_file("t.cba.foo", "application/x-ace")
self.mime_test_file("t.txt.a", "application/x-archive")
self.mime_test_file("t.txt.a.foo", "application/x-archive")
self.mime_test_file("t.lha", "application/x-lha")
@ -159,9 +168,11 @@ class TestMime (unittest.TestCase):
def test_mime_mimedb (self):
self.mime_test_mimedb("t .7z", "application/x-7z-compressed")
self.mime_test_mimedb("t .cb7", "application/x-7z-compressed")
self.mime_test_mimedb("t.arj", "application/x-arj")
self.mime_test_mimedb("t .bz2", "application/x-bzip2")
self.mime_test_mimedb("t.cab", "application/x-cab")
self.mime_test_mimedb("t.cbr", ("application/rar", "application/x-rar"))
self.mime_test_mimedb("t.cpio", "application/x-cpio")
self.mime_test_mimedb("t.deb", "application/x-debian-package")
self.mime_test_mimedb("t.gz", "application/gzip")
@ -172,6 +183,7 @@ class TestMime (unittest.TestCase):
self.mime_test_mimedb("t.rar", ("application/rar", "application/x-rar"))
self.mime_test_mimedb("t.rpm", ("application/x-redhat-package-manager", "application/x-rpm"))
self.mime_test_mimedb("t.tar", "application/x-tar")
self.mime_test_mimedb("t.cbt", "application/x-tar")
self.mime_test_mimedb("t.tar.bz2", "application/x-tar", "bzip2")
self.mime_test_mimedb("t.tar.gz", "application/x-tar", "gzip")
self.mime_test_mimedb("t.tar.lzma", "application/x-tar", "lzma")
@ -186,7 +198,9 @@ class TestMime (unittest.TestCase):
self.mime_test_mimedb("t .xz", "application/x-xz")
self.mime_test_mimedb("t.Z", "application/x-compress")
self.mime_test_mimedb("t.zip", ("application/zip", "application/x-zip-compressed"))
self.mime_test_mimedb("t.cbz", ("application/zip", "application/x-zip-compressed"))
self.mime_test_mimedb("t.ace", "application/x-ace")
self.mime_test_mimedb("t.cba", "application/x-ace")
self.mime_test_mimedb("t.a", "application/x-archive")
self.mime_test_mimedb("t.lha", "application/x-lha")
self.mime_test_mimedb("t.lzh", "application/x-lzh")