diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2012-04-26 14:49:07 +0100 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2012-04-26 14:49:07 +0100 |
commit | e8dffa484bc3c4ca7e9bb106b038056e20ba2725 (patch) | |
tree | 838e158e0b89431e76abe1b0267bdb56601ebd4a /morphlib/stagingarea.py | |
parent | 01eaed7aaec7e60d40bf07e3850547e548ce206e (diff) | |
download | morph-e8dffa484bc3c4ca7e9bb106b038056e20ba2725.tar.gz |
Monkey patch Python's tarfile.TarFile for proper errors, ignoring overwrites
Diffstat (limited to 'morphlib/stagingarea.py')
-rw-r--r-- | morphlib/stagingarea.py | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/morphlib/stagingarea.py b/morphlib/stagingarea.py index a34daede..59908d5f 100644 --- a/morphlib/stagingarea.py +++ b/morphlib/stagingarea.py @@ -14,6 +14,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import errno import logging import os import shutil @@ -91,6 +92,36 @@ class StagingArea(object): logging.debug('Installing artifact %s' % getattr(handle, 'name', 'unknown name')) tf = tarfile.open(fileobj=handle) + + # This is evil, but necessary. For some reason Python's system + # call wrappers (os.mknod and such) do not (always?) set the + # filename attribute of the OSError exception they raise. We + # fix that by monkey patching the tf instance with wrappers + # for the relevant methods to add things. The wrapper further + # ignores EEXIST errors, since we do not (currently!) care about + # overwriting files. + + def monkey_patcher(real): + def make_something(tarinfo, targetpath): + try: + return real(tarinfo, targetpath) + except OSError, e: + if e.errno == errno.EEXIST: + pass + elif e.filename is None: + e.filename = targetpath + raise e + else: + raise + return make_something + + tf.makedir = monkey_patcher(tf.makedir) + tf.makefile = monkey_patcher(tf.makefile) + tf.makeunknown = monkey_patcher(tf.makeunknown) + tf.makefifo = monkey_patcher(tf.makefifo) + tf.makedev = monkey_patcher(tf.makedev) + tf.makelink = monkey_patcher(tf.makelink) + tf.extractall(path=self.dirname) def remove(self): |