1# Copyright (C) 2011  Jeff Forcier <jeff@bitprophet.org>
2#
3# This file is part of ssh.
4#
5# 'ssh' is free software; you can redistribute it and/or modify it under the
6# terms of the GNU Lesser General Public License as published by the Free
7# Software Foundation; either version 2.1 of the License, or (at your option)
8# any later version.
9#
10# 'ssh' is distrubuted in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
13# details.
14#
15# You should have received a copy of the GNU Lesser General Public License
16# along with 'ssh'; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Suite 500, Boston, MA  02110-1335  USA.
18
19# Note: Despite the copyright notice, this was submitted by John
20# Arbash Meinel.  Thanks John!
21
22
23"""A small set of helper functions for dealing with setup issues"""
24
25import os
26import tarfile
27
28from distutils import log
29import distutils.archive_util
30from distutils.dir_util import mkpath
31from distutils.spawn import spawn
32
33
34def make_tarball(base_name, base_dir, compress='gzip',
35                 verbose=False, dry_run=False):
36    """Create a tar file from all the files under 'base_dir'.
37    This file may be compressed.
38
39    :param compress: Compression algorithms. Supported algorithms are:
40        'gzip': (the default)
41        'compress'
42        'bzip2'
43        None
44    For 'gzip' and 'bzip2' the internal tarfile module will be used.
45    For 'compress' the .tar will be created using tarfile, and then
46    we will spawn 'compress' afterwards.
47    The output tar file will be named 'base_name' + ".tar",
48    possibly plus the appropriate compression extension (".gz",
49    ".bz2" or ".Z").  Return the output filename.
50    """
51    # XXX GNU tar 1.13 has a nifty option to add a prefix directory.
52    # It's pretty new, though, so we certainly can't require it --
53    # but it would be nice to take advantage of it to skip the
54    # "create a tree of hardlinks" step!  (Would also be nice to
55    # detect GNU tar to use its 'z' option and save a step.)
56
57    compress_ext = { 'gzip': ".gz",
58                     'bzip2': '.bz2',
59                     'compress': ".Z" }
60
61    # flags for compression program, each element of list will be an argument
62    tarfile_compress_flag = {'gzip':'gz', 'bzip2':'bz2'}
63    compress_flags = {'compress': ["-f"]}
64
65    if compress is not None and compress not in compress_ext.keys():
66        raise ValueError("bad value for 'compress': must be None, 'gzip',"
67                         "'bzip2' or 'compress'")
68
69    archive_name = base_name + ".tar"
70    if compress and compress in tarfile_compress_flag:
71        archive_name += compress_ext[compress]
72
73    mode = 'w:' + tarfile_compress_flag.get(compress, '')
74
75    mkpath(os.path.dirname(archive_name), dry_run=dry_run)
76    log.info('Creating tar file %s with mode %s' % (archive_name, mode))
77
78    if not dry_run:
79        tar = tarfile.open(archive_name, mode=mode)
80        # This recursively adds everything underneath base_dir
81        tar.add(base_dir)
82        tar.close()
83
84    if compress and compress not in tarfile_compress_flag:
85        spawn([compress] + compress_flags[compress] + [archive_name],
86              dry_run=dry_run)
87        return archive_name + compress_ext[compress]
88    else:
89        return archive_name
90
91
92_custom_formats = {
93    'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
94    'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
95    'ztar':  (make_tarball, [('compress', 'compress')], "compressed tar file"),
96    'tar':   (make_tarball, [('compress', None)], "uncompressed tar file"),
97}
98
99# Hack in and insert ourselves into the distutils code base
100def install_custom_make_tarball():
101    distutils.archive_util.ARCHIVE_FORMATS.update(_custom_formats)
102
103