def create_archive(self, scm_object, **kwargs): """Create a tarball of repodir in destination directory.""" (workdir, topdir) = os.path.split(scm_object.arch_dir) args = kwargs['cli'] outdir = args.outdir dstname = kwargs['dstname'] extension = (args.extension or 'tar') exclude = args.exclude include = args.include package_metadata = args.package_meta timestamp = self.helpers.get_timestamp( scm_object, args, scm_object.clone_dir ) incl_patterns = [] excl_patterns = [] for i in include: # for backward compatibility add a trailing '*' if i isn't a # pattern if fnmatch.translate(i) == fnmatch.translate(i + r''): i += r'*' pat = fnmatch.translate(os.path.join(topdir, i)) incl_patterns.append(re.compile(pat)) for exc in exclude: pat = fnmatch.translate(os.path.join(topdir, exc)) excl_patterns.append(re.compile(pat)) def tar_exclude(filename): """ Exclude (return True) or add (return False) file to tar achive. """ if not package_metadata and METADATA_PATTERN.match(filename): return True if incl_patterns: for pat in incl_patterns: if pat.match(filename): return False return True for pat in excl_patterns: if pat.match(filename): return True return False def reset(tarinfo): """Python 2.7 only: reset uid/gid to 0/0 (root).""" tarinfo.uid = tarinfo.gid = 0 tarinfo.uname = tarinfo.gname = "root" if timestamp != 0: tarinfo.mtime = timestamp return tarinfo def tar_filter(tarinfo): if tar_exclude(tarinfo.name): return None return reset(tarinfo) cwd = os.getcwd() os.chdir(workdir) enc = locale.getpreferredencoding() out_file = os.path.join(outdir, dstname + '.' + extension) with tarfile.open(out_file, "w", encoding=enc) as tar: try: tar.add(topdir, recursive=False, filter=reset) except TypeError: # Python 2.6 compatibility tar.add(topdir, recursive=False) for entry in map(lambda x: os.path.join(topdir, x), sorted(os.listdir(topdir))): try: tar.add(entry, filter=tar_filter) except TypeError: # Python 2.6 compatibility tar.add(entry, exclude=tar_exclude) self.archivefile = tar.name os.chdir(cwd)