diff --git a/doc/patool.1 b/doc/patool.1 index 052c2f8..4b7e7db 100644 --- a/doc/patool.1 +++ b/doc/patool.1 @@ -26,7 +26,7 @@ as a fallback with file(1). .PP \fBpatool\fP supports 7z (.7z), ZIP (.zip, .jar), GZIP (.gz), compress (.Z), BZIP2 (.bz2), TAR (.tar), ARJ (.arj), CAB (.cab), CPIO (.cpio), -RPM (.rpm), DEB (.deb), LZOP (.lzo), LZMA (.lzma) and RAR (.rar) formats. +RPM (.rpm), DEB (.deb), LZOP (.lzo), LZMA (.lzma), XZ (.xz) and RAR (.rar) formats. It relies on helper applications to handle those archive formats (for example bzip2 for BZIP2 archives). .SH COMMANDS diff --git a/doc/patool.txt b/doc/patool.txt index 56e9cf1..5c0f2fe 100644 --- a/doc/patool.txt +++ b/doc/patool.txt @@ -17,9 +17,9 @@ DESCRIPTION patool supports 7z (.7z), ZIP (.zip, .jar), GZIP (.gz), compress (.Z), BZIP2 (.bz2), TAR (.tar), ARJ (.arj), CAB (.cab), CPIO (.cpio), RPM - (.rpm), DEB (.deb), LZOP (.lzo), LZMA (.lzma) and RAR (.rar) formats. - It relies on helper applications to handle those archive formats (for - example bzip2 for BZIP2 archives). + (.rpm), DEB (.deb), LZOP (.lzo), LZMA (.lzma), XZ (.xz) and RAR (.rar) + formats. It relies on helper applications to handle those archive for‐ + mats (for example bzip2 for BZIP2 archives). COMMANDS Several commands and options are available. diff --git a/doc/todo.txt b/doc/todo.txt index ef2cbcf..e69de29 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -1 +0,0 @@ -- Support XZ archives diff --git a/patoolib/__init__.py b/patoolib/__init__.py index 3cedd62..6680b54 100644 --- a/patoolib/__init__.py +++ b/patoolib/__init__.py @@ -23,11 +23,11 @@ ArchiveCommands = ('list', 'extract', 'test', 'create') # Supported archive formats ArchiveFormats = ('gzip', 'bzip2', 'tar', 'zip', 'compress', '7z', 'rar', - 'cab', 'arj', 'cpio', 'rpm', 'deb', 'lzop', 'lzma') + 'cab', 'arj', 'cpio', 'rpm', 'deb', 'lzop', 'lzma', 'xz') # Supported encodings (used with tar for example) # Note that all encodings must also be archive formats -ArchiveEncodings = ('gzip', 'bzip2', 'compress', 'lzma') +ArchiveEncodings = ('gzip', 'bzip2', 'compress', 'lzma', 'xz') # Map MIME types to archive format ArchiveMimetypes = { @@ -48,7 +48,8 @@ ArchiveMimetypes = { 'application/x-rpm': 'rpm', 'application/x-debian-package': 'deb', 'application/x-lzop': 'lzop', - 'application/xxx': 'lzma', + 'application/x-lzma': 'lzma', + 'application/x-xz': 'xz', } # List of programs supporting the given archive format and command. @@ -104,7 +105,7 @@ ArchivePrograms = { 'create': ('cpio',), }, 'rpm': { - # XXX rpm2cpio depends on cpio which is not checked + # XXX rpm2cpio depends on cpio whose availability is not checked 'extract': ('rpm2cpio', '7z'), 'list': ('rpm', '7z'), 'test': ('rpm', '7z'), @@ -123,6 +124,12 @@ ArchivePrograms = { 'test': ('lzma',), 'create': ('lzma',), }, + 'xz': { + 'extract': ('xz',), + 'list': ('echo',), + 'test': ('xz',), + 'create': ('xz',), + }, } # only list those programs that have different python module names diff --git a/patoolib/programs/xz.py b/patoolib/programs/xz.py new file mode 100644 index 0000000..ce8d36a --- /dev/null +++ b/patoolib/programs/xz.py @@ -0,0 +1,56 @@ +# -*- 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 xz program.""" +import os +from .. import util + + +def extract_xz (archive, encoding, cmd, **kwargs): + """Extract a XZ archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['-c', '-d']) + cmdlist.append('--') + outfile = os.path.join(kwargs['outdir'], util.stripext(archive)) + cmdlist.extend([archive, '>', outfile]) + # note that for shell calls the command must be a string + cmd = " ".join([util.shell_quote(x) for x in cmdlist]) + return (cmd, {'shell': True}) + +def test_xz (archive, encoding, cmd, **kwargs): + """Test a XZ archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.append('-t') + cmdlist.append('--') + cmdlist.append(archive) + return cmdlist + +def create_xz (archive, encoding, cmd, *args, **kwargs): + """Create a XZ archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.append('-c') + cmdlist.append('--') + cmdlist.extend(args) + cmdlist.extend(['>', archive]) + # note that for shell calls the command must be a string + cmd = " ".join([util.shell_quote(x) for x in cmdlist]) + return (cmd, {'shell': True}) + diff --git a/patoolib/util.py b/patoolib/util.py index 727c438..eb82996 100644 --- a/patoolib/util.py +++ b/patoolib/util.py @@ -25,10 +25,12 @@ mimedb = mimetypes.MimeTypes(strict=False) # add missing encodings and mimetypes mimedb.encodings_map['.bz2'] = 'bzip2' mimedb.encodings_map['.lzma'] = 'lzma' +mimedb.encodings_map['.xz'] = 'xz' mimedb.suffix_map['.tbz2'] = '.tar.bz2' mimedb.add_type('application/x-lzop', '.lzo', strict=False) mimedb.add_type('application/x-arj', '.arj', strict=False) mimedb.add_type('application/x-lzma', '.lzma', strict=False) +mimedb.add_type('application/x-xz', '.xz', strict=False) class PatoolError (StandardError): diff --git a/tests/data/t.tar.xz b/tests/data/t.tar.xz new file mode 100644 index 0000000..34fbdd4 Binary files /dev/null and b/tests/data/t.tar.xz differ diff --git a/tests/data/t.xz b/tests/data/t.xz new file mode 100644 index 0000000..03545d7 Binary files /dev/null and b/tests/data/t.xz differ diff --git a/tests/test_archives.py b/tests/test_archives.py index b3938ee..3b8eb7c 100644 --- a/tests/test_archives.py +++ b/tests/test_archives.py @@ -32,6 +32,7 @@ class TestArchives (ArchiveTest): self.archive_commands('t.tar.bz2', cmd) self.archive_commands('t.tbz2', cmd) # XXXself.archive_commands('t.tar.lzma', cmd) + # XXXself.archive_command('t.tar.xz', cmd) @needs_cmd('bzip2') def test_bzip2 (self): @@ -162,3 +163,9 @@ class TestArchives (ArchiveTest): self.archive_extract('t.lzma', 'lzma') self.archive_create('t.lzma', 'lzma', singlefile=True) + @needs_cmd('xz') + def test_xz (self): + self.archive_test('t.xz', 'xz') + self.archive_extract('t.xz', 'xz') + self.archive_create('t.xz', 'xz', singlefile=True) +