diff options
author | Bryn M. Reeves <bmr@redhat.com> | 2014-09-18 15:44:47 +0100 |
---|---|---|
committer | Bryn M. Reeves <bmr@redhat.com> | 2014-09-18 15:44:47 +0100 |
commit | 1b15835a18c98b3adc4f7454652f2a8604bed4cf (patch) | |
tree | d03efc43d1f787a82a4b3fa25aad630024cf3584 | |
parent | 4e2f91a4931b7cfe9b0c4a945f71de00186b3892 (diff) | |
download | sos-1b15835a18c98b3adc4f7454652f2a8604bed4cf.tar.gz |
[archive] introduce py2.6 TarFile compat wrapper
Python 2.6 lacks the filter parameter to TarFile.add() that the
TarFileArchive uses to preserve permissions on archive content.
Work around this by creating a wrapper class that implements the
missing functionality (duplicated from the py2.7.5 tarfile.py)
and use it whenever running on a python version less than 2.7.
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
-rw-r--r-- | sos/archive.py | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/sos/archive.py b/sos/archive.py index 6d3b3494..245f904f 100644 --- a/sos/archive.py +++ b/sos/archive.py @@ -24,6 +24,8 @@ import logging import shlex import re import codecs +import sys + # required for compression callout (FIXME: move to policy?) from subprocess import Popen, PIPE @@ -233,6 +235,77 @@ class FileCacheArchive(Archive): return self._compress() +# Compatibility version of the tarfile.TarFile class. This exists to allow +# compatibility with PY2 runtimes that lack the 'filter' parameter to the +# TarFile.add() method. The wrapper class is used on python2.6 and earlier +# only; all later versions include 'filter' and the native TarFile class is +# used directly. +class _TarFile(tarfile.TarFile): + + # Taken from the python 2.7.5 tarfile.py + def add(self, name, arcname=None, recursive=True, + exclude=None, filter=None): + """Add the file `name' to the archive. `name' may be any type of file + (directory, fifo, symbolic link, etc.). If given, `arcname' + specifies an alternative name for the file in the archive. + Directories are added recursively by default. This can be avoided by + setting `recursive' to False. `exclude' is a function that should + return True for each filename to be excluded. `filter' is a function + that expects a TarInfo object argument and returns the changed + TarInfo object, if it returns None the TarInfo object will be + excluded from the archive. + """ + self._check("aw") + + if arcname is None: + arcname = name + + # Exclude pathnames. + if exclude is not None: + import warnings + warnings.warn("use the filter argument instead", + DeprecationWarning, 2) + if exclude(name): + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Skip if somebody tries to archive the archive... + if self.name is not None and os.path.abspath(name) == self.name: + self._dbg(2, "tarfile: Skipped %r" % name) + return + + self._dbg(1, name) + + # Create a TarInfo object from the file. + tarinfo = self.gettarinfo(name, arcname) + + if tarinfo is None: + self._dbg(1, "tarfile: Unsupported type %r" % name) + return + + # Change or exclude the TarInfo object. + if filter is not None: + tarinfo = filter(tarinfo) + if tarinfo is None: + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Append the tar header and data to the archive. + if tarinfo.isreg(): + with tarfile.bltn_open(name, "rb") as f: + self.addfile(tarinfo, f) + + elif tarinfo.isdir(): + self.addfile(tarinfo) + if recursive: + for f in os.listdir(name): + self.add(os.path.join(name, f), os.path.join(arcname, f), + recursive, exclude, filter) + + else: + self.addfile(tarinfo) + + class TarFileArchive(FileCacheArchive): """ archive class using python TarFile to create tar archives""" @@ -283,7 +356,11 @@ class TarFileArchive(FileCacheArchive): return "%s.%s" % (self._name, self._suffix) def _build_archive(self): - tar = tarfile.open(self._archive_name, mode="w") + # python2.6 TarFile lacks the filter parameter + if six.PY2 and sys.version_info[1] < 7: + tar = _TarFile.open(self._archive_name, mode="w") + else: + tar = tarfile.open(self._archive_name, mode="w") # we need to pass the absolute path to the archive root but we # want the names used in the archive to be relative. tar.add(self._archive_root, arcname=os.path.split(self._name)[1], |