diff --git a/pisi-spec.rng b/pisi-spec.rng
index fa3f8ff9..aef76d28 100644
--- a/pisi-spec.rng
+++ b/pisi-spec.rng
@@ -1336,6 +1336,7 @@
bzip2
lzma
xz
+ 7z
binary
diff --git a/pisi/archive.py b/pisi/archive.py
index 25248600..26e325e2 100644
--- a/pisi/archive.py
+++ b/pisi/archive.py
@@ -32,6 +32,9 @@ import pisi.context as ctx
class UnknownArchiveType(Exception):
pass
+class ArchiveHandlerNotInstalled(Exception):
+ pass
+
# Proxy class inspired from tarfile._BZ2Proxy
class _LZMAProxy(object):
@@ -461,6 +464,25 @@ class ArchiveTarZ(ArchiveBase):
pass
self.tar.close()
+class Archive7Zip(ArchiveBase):
+ """ArchiveZip handles 7-Zip archives."""
+
+ def __init__(self, file_path, arch_type="7z"):
+ super(Archive7Zip, self).__init__(file_path, arch_type)
+ self.cmd = pisi.util.search_executable(arch_type)
+ if not self.cmd:
+ raise ArchiveHandlerNotInstalled
+
+ def unpack(self, target_dir, clean_dir=False):
+ super(Archive7Zip, self).unpack(target_dir, clean_dir)
+ self.unpack_dir(target_dir)
+
+ def unpack_dir(self, target_dir):
+ """Unpack 7z archive to a given target directory(target_dir)."""
+
+ # e.g. 7z x -bd -o
+ pisi.util.run_batch("%s x -bd -o%s %s" % (self.cmd, target_dir, self.file_path))
+
class ArchiveZip(ArchiveBase):
"""ArchiveZip handles zip archives.
@@ -639,6 +661,7 @@ class Archive:
'bzip2': ArchiveBzip2,
'lzma': ArchiveLzma,
'xz': ArchiveLzma,
+ '7z': Archive7Zip,
'binary': ArchiveBinary}
handler = handlers.get(arch_type)
@@ -659,6 +682,7 @@ class Archive:
("bz2", (".bz2", ".bz")),
("lzma", (".lzma",)),
("xz", (".xz",)),
+ ("7z", (".7z",)),
("binary", (".bin", ".run", ".sh")))
for _type, extensions in types:
diff --git a/pisi/sourcearchive.py b/pisi/sourcearchive.py
index 09ddac59..400efb84 100644
--- a/pisi/sourcearchive.py
+++ b/pisi/sourcearchive.py
@@ -123,6 +123,9 @@ class SourceArchive:
except pisi.archive.UnknownArchiveType:
raise Error(_("Unknown archive type '%s' is given for '%s'.")
% (self.archive.type, self.url.filename()))
+ except pisi.archive.ArchiveHandlerNotInstalled:
+ raise Error(_("Pisi needs %s to unpack this archive but it is not installed.")
+ % self.archive.type)
target_dir = os.path.join(target_dir, self.archive.target or "")
archive.unpack(target_dir, clean_dir)