diff options
Diffstat (limited to 'setup_helper.py')
-rw-r--r-- | setup_helper.py | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/setup_helper.py b/setup_helper.py new file mode 100644 index 0000000..f290ea3 --- /dev/null +++ b/setup_helper.py @@ -0,0 +1,160 @@ +# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com> +# +# This file is part of paramiko. +# +# Paramiko is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Paramiko; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Note: Despite the copyright notice, this was submitted by John +# Arbash Meinel. Thanks John! + + +"""A small set of helper functions for dealing with setup issues""" + +import os +import tarfile + +from distutils import log +import distutils.archive_util +from distutils.dir_util import mkpath +from distutils.spawn import spawn + +try: + from pwd import getpwnam +except ImportError: + getpwnam = None + +try: + from grp import getgrnam +except ImportError: + getgrnam = None + + +def _get_gid(name): + """Returns a gid, given a group name.""" + if getgrnam is None or name is None: + return None + try: + result = getgrnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + + +def _get_uid(name): + """Returns an uid, given a user name.""" + if getpwnam is None or name is None: + return None + try: + result = getpwnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + + +def make_tarball( + base_name, + base_dir, + compress="gzip", + verbose=0, + dry_run=0, + owner=None, + group=None, +): + """Create a tar file from all the files under 'base_dir'. + This file may be compressed. + + :param compress: Compression algorithms. Supported algorithms are: + 'gzip': (the default) + 'compress' + 'bzip2' + None + For 'gzip' and 'bzip2' the internal tarfile module will be used. + For 'compress' the .tar will be created using tarfile, and then + we will spawn 'compress' afterwards. + The output tar file will be named 'base_name' + ".tar", + possibly plus the appropriate compression extension (".gz", + ".bz2" or ".Z"). Return the output filename. + """ + # XXX GNU tar 1.13 has a nifty option to add a prefix directory. + # It's pretty new, though, so we certainly can't require it -- + # but it would be nice to take advantage of it to skip the + # "create a tree of hardlinks" step! (Would also be nice to + # detect GNU tar to use its 'z' option and save a step.) + + compress_ext = {"gzip": ".gz", "bzip2": ".bz2", "compress": ".Z"} + + # flags for compression program, each element of list will be an argument + tarfile_compress_flag = {"gzip": "gz", "bzip2": "bz2"} + compress_flags = {"compress": ["-f"]} + + if compress is not None and compress not in compress_ext.keys(): + raise ValueError( + "bad value for 'compress': must be None, 'gzip'," + "'bzip2' or 'compress'" + ) + + archive_name = base_name + ".tar" + if compress and compress in tarfile_compress_flag: + archive_name += compress_ext[compress] + + mode = "w:" + tarfile_compress_flag.get(compress, "") + + mkpath(os.path.dirname(archive_name), dry_run=dry_run) + log.info(f"Creating tar file {archive_name} with mode {mode}") + + uid = _get_uid(owner) + gid = _get_gid(group) + + def _set_uid_gid(tarinfo): + if gid is not None: + tarinfo.gid = gid + tarinfo.gname = group + if uid is not None: + tarinfo.uid = uid + tarinfo.uname = owner + return tarinfo + + if not dry_run: + tar = tarfile.open(archive_name, mode=mode) + # This recursively adds everything underneath base_dir + try: + tar.add(base_dir, filter=_set_uid_gid) + finally: + tar.close() + + if compress and compress not in tarfile_compress_flag: + spawn( + [compress] + compress_flags[compress] + [archive_name], + dry_run=dry_run, + ) + return archive_name + compress_ext[compress] + else: + return archive_name + + +_custom_formats = { + "gztar": (make_tarball, [("compress", "gzip")], "gzip'ed tar-file"), + "bztar": (make_tarball, [("compress", "bzip2")], "bzip2'ed tar-file"), + "ztar": (make_tarball, [("compress", "compress")], "compressed tar file"), + "tar": (make_tarball, [("compress", None)], "uncompressed tar file"), +} + +# Hack in and insert ourselves into the distutils code base +def install_custom_make_tarball(): + distutils.archive_util.ARCHIVE_FORMATS.update(_custom_formats) |