summaryrefslogtreecommitdiff
path: root/morphlib/stagingarea.py
diff options
context:
space:
mode:
authorLars Wirzenius <lars.wirzenius@codethink.co.uk>2012-04-26 14:49:07 +0100
committerLars Wirzenius <lars.wirzenius@codethink.co.uk>2012-04-26 14:49:07 +0100
commite8dffa484bc3c4ca7e9bb106b038056e20ba2725 (patch)
tree838e158e0b89431e76abe1b0267bdb56601ebd4a /morphlib/stagingarea.py
parent01eaed7aaec7e60d40bf07e3850547e548ce206e (diff)
downloadmorph-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.py31
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):