| 1 | # customised version of 'waf dist' for Samba tools
|
|---|
| 2 | # uses git ls-files to get file lists
|
|---|
| 3 |
|
|---|
| 4 | import Utils, os, sys, tarfile, stat, Scripting, Logs, Options
|
|---|
| 5 | from samba_utils import *
|
|---|
| 6 |
|
|---|
| 7 | dist_dirs = None
|
|---|
| 8 | dist_blacklist = ""
|
|---|
| 9 |
|
|---|
| 10 | def add_symlink(tar, fname, abspath, basedir):
|
|---|
| 11 | '''handle symlinks to directories that may move during packaging'''
|
|---|
| 12 | if not os.path.islink(abspath):
|
|---|
| 13 | return False
|
|---|
| 14 | tinfo = tar.gettarinfo(name=abspath, arcname=fname)
|
|---|
| 15 | tgt = os.readlink(abspath)
|
|---|
| 16 |
|
|---|
| 17 | if dist_dirs:
|
|---|
| 18 | # we need to find the target relative to the main directory
|
|---|
| 19 | # this is here to cope with symlinks into the buildtools
|
|---|
| 20 | # directory from within the standalone libraries in Samba. For example,
|
|---|
| 21 | # a symlink to ../../builtools/scripts/autogen-waf.sh needs
|
|---|
| 22 | # to be rewritten as a symlink to buildtools/scripts/autogen-waf.sh
|
|---|
| 23 | # when the tarball for talloc is built
|
|---|
| 24 |
|
|---|
| 25 | # the filename without the appname-version
|
|---|
| 26 | rel_fname = '/'.join(fname.split('/')[1:])
|
|---|
| 27 |
|
|---|
| 28 | # join this with the symlink target
|
|---|
| 29 | tgt_full = os.path.join(os.path.dirname(rel_fname), tgt)
|
|---|
| 30 |
|
|---|
| 31 | # join with the base directory
|
|---|
| 32 | tgt_base = os.path.normpath(os.path.join(basedir, tgt_full))
|
|---|
| 33 |
|
|---|
| 34 | # see if this is inside one of our dist_dirs
|
|---|
| 35 | for dir in dist_dirs.split():
|
|---|
| 36 | if dir.find(':') != -1:
|
|---|
| 37 | destdir=dir.split(':')[1]
|
|---|
| 38 | dir=dir.split(':')[0]
|
|---|
| 39 | else:
|
|---|
| 40 | destdir = '.'
|
|---|
| 41 | if dir == basedir:
|
|---|
| 42 | # internal links don't get rewritten
|
|---|
| 43 | continue
|
|---|
| 44 | if dir == tgt_base[0:len(dir)] and tgt_base[len(dir)] == '/':
|
|---|
| 45 | new_tgt = destdir + tgt_base[len(dir):]
|
|---|
| 46 | tinfo.linkname = new_tgt
|
|---|
| 47 | break
|
|---|
| 48 |
|
|---|
| 49 | tinfo.uid = 0
|
|---|
| 50 | tinfo.gid = 0
|
|---|
| 51 | tinfo.uname = 'root'
|
|---|
| 52 | tinfo.gname = 'root'
|
|---|
| 53 | tar.addfile(tinfo)
|
|---|
| 54 | return True
|
|---|
| 55 |
|
|---|
| 56 | def add_tarfile(tar, fname, abspath, basedir):
|
|---|
| 57 | '''add a file to the tarball'''
|
|---|
| 58 | if add_symlink(tar, fname, abspath, basedir):
|
|---|
| 59 | return
|
|---|
| 60 | try:
|
|---|
| 61 | tinfo = tar.gettarinfo(name=abspath, arcname=fname)
|
|---|
| 62 | except OSError:
|
|---|
| 63 | Logs.error('Unable to find file %s - missing from git checkout?' % abspath)
|
|---|
| 64 | sys.exit(1)
|
|---|
| 65 | tinfo.uid = 0
|
|---|
| 66 | tinfo.gid = 0
|
|---|
| 67 | tinfo.uname = 'root'
|
|---|
| 68 | tinfo.gname = 'root'
|
|---|
| 69 | fh = open(abspath)
|
|---|
| 70 | tar.addfile(tinfo, fileobj=fh)
|
|---|
| 71 | fh.close()
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 | def vcs_dir_contents(path):
|
|---|
| 75 | """Return the versioned files under a path.
|
|---|
| 76 |
|
|---|
| 77 | :return: List of paths relative to path
|
|---|
| 78 | """
|
|---|
| 79 | repo = path
|
|---|
| 80 | while repo != "/":
|
|---|
| 81 | if os.path.isdir(os.path.join(repo, ".git")):
|
|---|
| 82 | ls_files_cmd = [ 'git', 'ls-files', '--full-name',
|
|---|
| 83 | os_path_relpath(path, repo) ]
|
|---|
| 84 | cwd = None
|
|---|
| 85 | env = dict(os.environ)
|
|---|
| 86 | env["GIT_DIR"] = os.path.join(repo, ".git")
|
|---|
| 87 | break
|
|---|
| 88 | elif os.path.isdir(os.path.join(repo, ".bzr")):
|
|---|
| 89 | ls_files_cmd = [ 'bzr', 'ls', '--recursive', '--versioned',
|
|---|
| 90 | os_path_relpath(path, repo)]
|
|---|
| 91 | cwd = repo
|
|---|
| 92 | env = None
|
|---|
| 93 | break
|
|---|
| 94 | repo = os.path.dirname(repo)
|
|---|
| 95 | if repo == "/":
|
|---|
| 96 | raise Exception("unsupported or no vcs for %s" % path)
|
|---|
| 97 | return Utils.cmd_output(ls_files_cmd, cwd=cwd, env=env).split()
|
|---|
| 98 |
|
|---|
| 99 |
|
|---|
| 100 | def dist(appname='',version=''):
|
|---|
| 101 | if not isinstance(appname, str) or not appname:
|
|---|
| 102 | # this copes with a mismatch in the calling arguments for dist()
|
|---|
| 103 | appname = Utils.g_module.APPNAME
|
|---|
| 104 | version = Utils.g_module.VERSION
|
|---|
| 105 | if not version:
|
|---|
| 106 | version = Utils.g_module.VERSION
|
|---|
| 107 |
|
|---|
| 108 | srcdir = os.path.normpath(os.path.join(os.path.dirname(Utils.g_module.root_path), Utils.g_module.srcdir))
|
|---|
| 109 |
|
|---|
| 110 | if not dist_dirs:
|
|---|
| 111 | Logs.error('You must use samba_dist.DIST_DIRS() to set which directories to package')
|
|---|
| 112 | sys.exit(1)
|
|---|
| 113 |
|
|---|
| 114 | dist_base = '%s-%s' % (appname, version)
|
|---|
| 115 |
|
|---|
| 116 | if Options.options.SIGN_RELEASE:
|
|---|
| 117 | dist_name = '%s.tar' % (dist_base)
|
|---|
| 118 | tar = tarfile.open(dist_name, 'w')
|
|---|
| 119 | else:
|
|---|
| 120 | dist_name = '%s.tar.gz' % (dist_base)
|
|---|
| 121 | tar = tarfile.open(dist_name, 'w:gz')
|
|---|
| 122 |
|
|---|
| 123 | blacklist = dist_blacklist.split()
|
|---|
| 124 |
|
|---|
| 125 | for dir in dist_dirs.split():
|
|---|
| 126 | if dir.find(':') != -1:
|
|---|
| 127 | destdir=dir.split(':')[1]
|
|---|
| 128 | dir=dir.split(':')[0]
|
|---|
| 129 | else:
|
|---|
| 130 | destdir = '.'
|
|---|
| 131 | absdir = os.path.join(srcdir, dir)
|
|---|
| 132 | try:
|
|---|
| 133 | files = vcs_dir_contents(absdir)
|
|---|
| 134 | except Exception, e:
|
|---|
| 135 | Logs.error('unable to get contents of %s: %s' % (absdir, e))
|
|---|
| 136 | sys.exit(1)
|
|---|
| 137 | for f in files:
|
|---|
| 138 | abspath = os.path.join(srcdir, f)
|
|---|
| 139 |
|
|---|
| 140 | if dir != '.':
|
|---|
| 141 | f = f[len(dir)+1:]
|
|---|
| 142 |
|
|---|
| 143 | # Remove files in the blacklist
|
|---|
| 144 | if f in dist_blacklist:
|
|---|
| 145 | continue
|
|---|
| 146 | blacklisted = False
|
|---|
| 147 | # Remove directories in the blacklist
|
|---|
| 148 | for d in blacklist:
|
|---|
| 149 | if f.startswith(d):
|
|---|
| 150 | blacklisted = True
|
|---|
| 151 | if blacklisted:
|
|---|
| 152 | continue
|
|---|
| 153 | if os.path.isdir(abspath):
|
|---|
| 154 | continue
|
|---|
| 155 | if destdir != '.':
|
|---|
| 156 | f = destdir + '/' + f
|
|---|
| 157 | fname = dist_base + '/' + f
|
|---|
| 158 | add_tarfile(tar, fname, abspath, dir)
|
|---|
| 159 |
|
|---|
| 160 | tar.close()
|
|---|
| 161 |
|
|---|
| 162 | if Options.options.SIGN_RELEASE:
|
|---|
| 163 | import gzip
|
|---|
| 164 | try:
|
|---|
| 165 | os.unlink(dist_name + '.asc')
|
|---|
| 166 | except OSError:
|
|---|
| 167 | pass
|
|---|
| 168 |
|
|---|
| 169 | cmd = "gpg --detach-sign --armor " + dist_name
|
|---|
| 170 | os.system(cmd)
|
|---|
| 171 | uncompressed_tar = open(dist_name, 'rb')
|
|---|
| 172 | compressed_tar = gzip.open(dist_name + '.gz', 'wb')
|
|---|
| 173 | while 1:
|
|---|
| 174 | buffer = uncompressed_tar.read(1048576)
|
|---|
| 175 | if buffer:
|
|---|
| 176 | compressed_tar.write(buffer)
|
|---|
| 177 | else:
|
|---|
| 178 | break
|
|---|
| 179 | uncompressed_tar.close()
|
|---|
| 180 | compressed_tar.close()
|
|---|
| 181 | os.unlink(dist_name)
|
|---|
| 182 | Logs.info('Created %s.gz %s.asc' % (dist_name, dist_name))
|
|---|
| 183 | dist_name = dist_name + '.gz'
|
|---|
| 184 | else:
|
|---|
| 185 | Logs.info('Created %s' % dist_name)
|
|---|
| 186 |
|
|---|
| 187 | return dist_name
|
|---|
| 188 |
|
|---|
| 189 |
|
|---|
| 190 | @conf
|
|---|
| 191 | def DIST_DIRS(dirs):
|
|---|
| 192 | '''set the directories to package, relative to top srcdir'''
|
|---|
| 193 | global dist_dirs
|
|---|
| 194 | if not dist_dirs:
|
|---|
| 195 | dist_dirs = dirs
|
|---|
| 196 |
|
|---|
| 197 | @conf
|
|---|
| 198 | def DIST_BLACKLIST(blacklist):
|
|---|
| 199 | '''set the files to exclude from packaging, relative to top srcdir'''
|
|---|
| 200 | global dist_blacklist
|
|---|
| 201 | if not dist_blacklist:
|
|---|
| 202 | dist_blacklist = blacklist
|
|---|
| 203 |
|
|---|
| 204 | Scripting.dist = dist
|
|---|