2016-11-30 05:21:53 +00:00
|
|
|
"""Python native TGZ creation."""
|
|
|
|
|
|
|
|
from __future__ import absolute_import, print_function
|
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
import abc
|
2016-11-30 05:21:53 +00:00
|
|
|
import tarfile
|
|
|
|
import os
|
|
|
|
|
2017-05-05 08:23:00 +00:00
|
|
|
from lib.util import (
|
|
|
|
display,
|
2017-10-26 07:21:46 +00:00
|
|
|
ABC,
|
2017-05-05 08:23:00 +00:00
|
|
|
)
|
|
|
|
|
2016-11-30 05:21:53 +00:00
|
|
|
# improve performance by disabling uid/gid lookups
|
|
|
|
tarfile.pwd = None
|
|
|
|
tarfile.grp = None
|
|
|
|
|
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
class TarFilter(ABC):
|
|
|
|
"""Filter to use when creating a tar file."""
|
|
|
|
@abc.abstractmethod
|
|
|
|
def ignore(self, item):
|
|
|
|
"""
|
|
|
|
:type item: tarfile.TarInfo
|
|
|
|
:rtype: tarfile.TarInfo | None
|
|
|
|
"""
|
|
|
|
pass
|
2016-11-30 05:21:53 +00:00
|
|
|
|
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
class DefaultTarFilter(TarFilter):
|
2016-11-30 05:21:53 +00:00
|
|
|
"""
|
2017-10-26 07:21:46 +00:00
|
|
|
To reduce archive time and size, ignore non-versioned files which are large or numerous.
|
|
|
|
Also ignore miscellaneous git related files since the .git directory is ignored.
|
2016-11-30 05:21:53 +00:00
|
|
|
"""
|
2017-10-26 07:21:46 +00:00
|
|
|
def __init__(self):
|
|
|
|
self.ignore_dirs = (
|
|
|
|
'.tox',
|
|
|
|
'.git',
|
|
|
|
'.idea',
|
2018-10-13 17:44:11 +00:00
|
|
|
'.pytest_cache',
|
2017-10-26 07:21:46 +00:00
|
|
|
'__pycache__',
|
|
|
|
'ansible.egg-info',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.ignore_files = (
|
|
|
|
'.gitignore',
|
|
|
|
'.gitdir',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.ignore_extensions = (
|
|
|
|
'.pyc',
|
|
|
|
'.retry',
|
|
|
|
)
|
|
|
|
|
|
|
|
def ignore(self, item):
|
|
|
|
"""
|
|
|
|
:type item: tarfile.TarInfo
|
|
|
|
:rtype: tarfile.TarInfo | None
|
|
|
|
"""
|
|
|
|
filename = os.path.basename(item.path)
|
|
|
|
name, ext = os.path.splitext(filename)
|
|
|
|
dirs = os.path.split(item.path)
|
|
|
|
|
|
|
|
if not item.isdir():
|
|
|
|
if item.path.startswith('./test/results/'):
|
|
|
|
return None
|
|
|
|
|
|
|
|
if item.path.startswith('./docs/docsite/_build/'):
|
|
|
|
return None
|
|
|
|
|
|
|
|
if name in self.ignore_files:
|
|
|
|
return None
|
2016-11-30 05:21:53 +00:00
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
if ext in self.ignore_extensions:
|
2016-11-30 05:21:53 +00:00
|
|
|
return None
|
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
if any(d in self.ignore_dirs for d in dirs):
|
2016-11-30 05:21:53 +00:00
|
|
|
return None
|
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
return item
|
2016-11-30 05:21:53 +00:00
|
|
|
|
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
class AllowGitTarFilter(DefaultTarFilter):
|
|
|
|
"""
|
|
|
|
Filter that allows git related files normally excluded by the default tar filter.
|
|
|
|
"""
|
|
|
|
def __init__(self):
|
|
|
|
super(AllowGitTarFilter, self).__init__()
|
2016-11-30 05:21:53 +00:00
|
|
|
|
2017-10-26 07:21:46 +00:00
|
|
|
self.ignore_dirs = tuple(d for d in self.ignore_dirs if not d.startswith('.git'))
|
|
|
|
self.ignore_files = tuple(f for f in self.ignore_files if not f.startswith('.git'))
|
2016-11-30 05:21:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
def create_tarfile(dst_path, src_path, tar_filter):
|
|
|
|
"""
|
|
|
|
:type dst_path: str
|
|
|
|
:type src_path: str
|
2017-10-26 07:21:46 +00:00
|
|
|
:type tar_filter: TarFilter
|
2016-11-30 05:21:53 +00:00
|
|
|
"""
|
2017-05-05 08:23:00 +00:00
|
|
|
display.info('Creating a compressed tar archive of path: %s' % src_path, verbosity=1)
|
|
|
|
|
2016-11-30 05:21:53 +00:00
|
|
|
with tarfile.TarFile.gzopen(dst_path, mode='w', compresslevel=4) as tar:
|
2017-10-26 07:21:46 +00:00
|
|
|
tar.add(src_path, filter=tar_filter.ignore)
|
2017-05-05 08:23:00 +00:00
|
|
|
|
|
|
|
display.info('Resulting archive is %d bytes.' % os.path.getsize(dst_path), verbosity=1)
|