diff --git a/doc/changelog.txt b/doc/changelog.txt index 2105d9f..fe54617 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -1,6 +1,7 @@ 0.7 "" (released xx.xx.xxxx) * Added support for ALZIP (.alz) archives. + * Added support for ARC (.arc) archives. 0.6 "Waking Ned" (released 6.3.2010) diff --git a/doc/patool.1 b/doc/patool.1 index 12b62e8..3d048cb 100644 --- a/doc/patool.1 +++ b/doc/patool.1 @@ -26,7 +26,8 @@ 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), ALZIP (.alz), AR (.a), ARJ (.arj), +\fBpatool\fP supports 7z (.7z), ACE (.ace), ALZIP (.alz), AR (.a), +ARC (.arc), ARJ (.arj), BZIP2 (.bz2), CAB (.cab), compress (.Z), CPIO (.cpio), DEB (.deb), GZIP (.gz), LZH (.lha, .lzh), LZIP (.lz), LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar), TAR (.tar), XZ (.xz) and ZIP (.zip, .jar) formats. diff --git a/doc/patool.txt b/doc/patool.txt index daa5fed..6de9d28 100644 --- a/doc/patool.txt +++ b/doc/patool.txt @@ -18,12 +18,12 @@ DESCRIPTION The archive format is determined by the file(1) program and as a fall‐ back by the archive file extension. - patool supports 7z (.7z), ACE (.ace), ALZIP (.alz), AR (.a), ARJ - (.arj), BZIP2 (.bz2), CAB (.cab), compress (.Z), CPIO (.cpio), DEB - (.deb), GZIP (.gz), LZH (.lha, .lzh), LZIP (.lz), LZMA (.lzma), LZOP - (.lzo), RPM (.rpm), RAR (.rar), TAR (.tar), XZ (.xz) and ZIP (.zip, - .jar) formats. It relies on helper applications to handle those ar‐ - chive formats (for example bzip2 for BZIP2 archives). + patool supports 7z (.7z), ACE (.ace), ALZIP (.alz), AR (.a), ARC + (.arc), ARJ (.arj), BZIP2 (.bz2), CAB (.cab), compress (.Z), CPIO + (.cpio), DEB (.deb), GZIP (.gz), LZH (.lha, .lzh), LZIP (.lz), LZMA + (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar), TAR (.tar), XZ (.xz) and + ZIP (.zip, .jar) formats. It relies on helper applications to handle + those archive formats (for example bzip2 for BZIP2 archives). EXAMPLES patool extract archive.zip otherarchive.rar diff --git a/doc/todo.txt b/doc/todo.txt index e69de29..749c7d7 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -0,0 +1 @@ +nomarch diff --git a/patool.bash-completion b/patool.bash-completion index ea3269c..3cf781c 100644 --- a/patool.bash-completion +++ b/patool.bash-completion @@ -23,22 +23,11 @@ _patool() if [[ "$cur" == -* ]]; then # possible options for the command + options='' case $command in - extract) - options='--verbose --force' - ;; - list) + extract|list|test|create) options='--verbose' ;; - test) - options='--verbose' - ;; - create) - options='--verbose --force' - ;; - formats) - options='' - ;; esac options="$options --help" diff --git a/patoolib/__init__.py b/patoolib/__init__.py index 8b64ce8..f364f0a 100644 --- a/patoolib/__init__.py +++ b/patoolib/__init__.py @@ -22,13 +22,13 @@ from patoolib import util ArchiveCommands = ('list', 'extract', 'test', 'create') # Supported archive formats -ArchiveFormats = ('gzip', 'bzip2', 'tar', 'zip', 'compress', '7z', 'rar', - 'cab', 'arj', 'cpio', 'rpm', 'deb', 'lzop', 'lzma', 'xz', 'lzip', 'ace', - 'ar', 'lzh', 'alzip') +ArchiveFormats = ('7z', 'ace', 'alzip', 'ar', 'arc', 'arj', 'bzip2', + 'cab', 'compress', 'cpio', 'deb', 'gzip', 'lzh', 'lzip', 'lzma', + 'lzop', 'rar', 'rpm', 'tar', 'xz', 'zip') # Supported encodings (used with tar for example) # Note that all encodings must also be archive formats -ArchiveEncodings = ('gzip', 'bzip2', 'compress', 'lzma', 'xz', 'lzip') +ArchiveEncodings = ('bzip2', 'compress', 'gzip', 'lzip', 'lzma', 'xz') # Map MIME types to archive format ArchiveMimetypes = { @@ -57,6 +57,7 @@ ArchiveMimetypes = { 'application/x-lha': 'lzh', 'application/x-lzh': 'lzh', 'application/x-alzip': 'alzip', + 'application/x-arc': 'arc', } # List of programs supporting the given encoding @@ -86,6 +87,9 @@ ArchivePrograms = { 'ar': { None: ('ar',), }, + 'arc': { + None: ('arc',), + }, 'bzip2': { 'extract': ('pbzip2', 'bzip2', '7z'), 'test': ('pbzip2', 'bzip2', '7z'), @@ -393,15 +397,23 @@ def _handle_archive (archive, command, *args, **kwargs): # prepare func() call arguments kwargs = dict(verbose=config['verbose']) outdir = None + origarchive = None if command == 'extract': outdir = util.tmpdir(dir=os.getcwd()) kwargs['outdir'] = outdir + elif command == 'create' and os.path.basename(program) == 'arc' and \ + ".arc" in archive and not archive.endswith(".arc"): + # the arc program mangles the archive name if it contains ".arc" + origarchive = archive + archive = util.tmpfile(dir=os.path.dirname(archive), suffix=".arc") try: cmdlist = get_archive_cmdlist(archive, encoding, program, *args, **kwargs) run_archive_cmdlist(cmdlist) if command == 'extract': target = cleanup_outdir(archive, outdir) print "%s: extracted to %s" % (archive, target) + elif command == 'create' and origarchive: + shutil.move(archive, origarchive) finally: if outdir: try: diff --git a/patoolib/programs/arc.py b/patoolib/programs/arc.py new file mode 100644 index 0000000..e77d066 --- /dev/null +++ b/patoolib/programs/arc.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Archive commands for the arc program.""" + +def extract_arc (archive, encoding, cmd, **kwargs): + """Extract a ARC archive.""" + # Since extracted files will be placed in the current directory, + # the cwd argument has to be the output directory. + cmdlist = [cmd, 'x', archive] + return (cmdlist, {'cwd': kwargs['outdir']}) + +def list_arc (archive, encoding, cmd, **kwargs): + """List a ARC archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('v') + else: + cmdlist.append('l') + cmdlist.append(archive) + return cmdlist + +def test_arc (archive, encoding, cmd, **kwargs): + """Test a ARC archive.""" + return [cmd, 't', archive] + +def create_arc (archive, encoding, cmd, *args, **kwargs): + """Create a ARC archive.""" + cmdlist = [cmd, 'a', archive] + cmdlist.extend(args) + return cmdlist diff --git a/patoolib/util.py b/patoolib/util.py index ca68f02..ef86f12 100644 --- a/patoolib/util.py +++ b/patoolib/util.py @@ -43,6 +43,7 @@ mimedb.add_type('application/x-ace', '.ace', strict=False) # Since .a is already a common type, strict=True must be used. mimedb.add_type('application/x-archive', '.a', strict=True) mimedb.add_type('application/x-alzip', '.alz', strict=False) +mimedb.add_type('application/x-arc', '.arc', strict=False) class PatoolError (StandardError): @@ -199,6 +200,7 @@ FileText2Mime = { "lzip compressed data": "application/x-lzip", "current ar archive": "application/x-archive", "LHa ": "application/x-lha", + "ARC archive data": "application/x-arc", } def guess_mime_file_text (file_prog, filename): @@ -245,6 +247,11 @@ def tmpdir (dir=None): return tempfile.mkdtemp(suffix='', prefix='Unpack_', dir=dir) +def tmpfile (dir=None, prefix="temp", suffix=None): + """Return a temporary file.""" + return tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)[1] + + def shell_quote (value): """Quote all shell metacharacters in given string value.""" return '%s' % value diff --git a/tests/data/t.arc b/tests/data/t.arc new file mode 100644 index 0000000..b3aa8de Binary files /dev/null and b/tests/data/t.arc differ diff --git a/tests/data/t.arc.foo b/tests/data/t.arc.foo new file mode 100644 index 0000000..b3aa8de Binary files /dev/null and b/tests/data/t.arc.foo differ diff --git a/tests/test_archives.py b/tests/test_archives.py index 7205fff..7d892c7 100644 --- a/tests/test_archives.py +++ b/tests/test_archives.py @@ -290,3 +290,8 @@ class TestArchives (ArchiveTest): def test_lha (self): self.program = 'lha' self.archive_commands('t.lha') + + @needs_program('arc') + def test_arc (self): + self.program = 'arc' + self.archive_commands('t.arc', singlefile=True) diff --git a/tests/test_foo_archives.py b/tests/test_foo_archives.py index a1dad4d..c703685 100644 --- a/tests/test_foo_archives.py +++ b/tests/test_foo_archives.py @@ -335,3 +335,8 @@ class TestArchives (ArchiveTest): # self.archive_test('t.alz.foo') # self.archive_list('t.alz.foo') # self.archive_extract('t.alz.foo') + + @needs_program('arc') + def test_arc (self): + self.program = 'arc' + self.archive_commands('t.arc.foo', format="arc", singlefile=True) diff --git a/tests/test_mime.py b/tests/test_mime.py index fec6161..afc5d69 100644 --- a/tests/test_mime.py +++ b/tests/test_mime.py @@ -109,7 +109,8 @@ class TestMime (unittest.TestCase): # file(1) does not recognize .alz files #self.mime_test_mimedb("t.alz", "application/x-alzip", None) #self.mime_test_mimedb("t.alz.foo", "application/x-alzip", None) - + self.mime_test_file("t.arc", "application/x-arc", None) + self.mime_test_file("t.arc.foo", "application/x-arc", None) def test_mime_mimedb (self): self.mime_test_mimedb("t.7z", "application/x-7z-compressed", None) @@ -144,3 +145,4 @@ class TestMime (unittest.TestCase): self.mime_test_mimedb("t.lha", "application/x-lha", None) self.mime_test_mimedb("t.lzh", "application/x-lzh", None) self.mime_test_mimedb("t.alz", "application/x-alzip", None) + self.mime_test_mimedb("t.arc", "application/x-arc", None)