aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2014-09-18 15:44:47 +0100
committerBryn M. Reeves <bmr@redhat.com>2014-09-18 15:44:47 +0100
commit1b15835a18c98b3adc4f7454652f2a8604bed4cf (patch)
treed03efc43d1f787a82a4b3fa25aad630024cf3584
parent4e2f91a4931b7cfe9b0c4a945f71de00186b3892 (diff)
downloadsos-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.py79
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],