1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/client.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,163 @@ 1.4 +#!/usr/bin/python 1.5 +# This Source Code Form is subject to the terms of the Mozilla Public 1.6 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.8 + 1.9 + 1.10 +LIBFFI_DIRS = (('js/ctypes/libffi', 'libffi'),) 1.11 +HG_EXCLUSIONS = ['.hg', '.hgignore', '.hgtags'] 1.12 + 1.13 +CVSROOT_LIBFFI = ':pserver:anoncvs@sources.redhat.com:/cvs/libffi' 1.14 + 1.15 +import os 1.16 +import sys 1.17 +import datetime 1.18 +import shutil 1.19 +import glob 1.20 +from optparse import OptionParser 1.21 +from subprocess import check_call 1.22 + 1.23 +topsrcdir = os.path.dirname(__file__) 1.24 +if topsrcdir == '': 1.25 + topsrcdir = '.' 1.26 + 1.27 +def check_call_noisy(cmd, *args, **kwargs): 1.28 + print "Executing command:", cmd 1.29 + check_call(cmd, *args, **kwargs) 1.30 + 1.31 +def do_hg_pull(dir, repository, hg): 1.32 + fulldir = os.path.join(topsrcdir, dir) 1.33 + # clone if the dir doesn't exist, pull if it does 1.34 + if not os.path.exists(fulldir): 1.35 + check_call_noisy([hg, 'clone', repository, fulldir]) 1.36 + else: 1.37 + cmd = [hg, 'pull', '-u', '-R', fulldir] 1.38 + if repository is not None: 1.39 + cmd.append(repository) 1.40 + check_call_noisy(cmd) 1.41 + check_call([hg, 'parent', '-R', fulldir, 1.42 + '--template=Updated to revision {node}.\n']) 1.43 + 1.44 +def do_hg_replace(dir, repository, tag, exclusions, hg): 1.45 + """ 1.46 + Replace the contents of dir with the contents of repository, except for 1.47 + files matching exclusions. 1.48 + """ 1.49 + fulldir = os.path.join(topsrcdir, dir) 1.50 + if os.path.exists(fulldir): 1.51 + shutil.rmtree(fulldir) 1.52 + 1.53 + assert not os.path.exists(fulldir) 1.54 + check_call_noisy([hg, 'clone', '-u', tag, repository, fulldir]) 1.55 + 1.56 + for thing in exclusions: 1.57 + for excluded in glob.iglob(os.path.join(fulldir, thing)): 1.58 + if os.path.isdir(excluded): 1.59 + shutil.rmtree(excluded) 1.60 + else: 1.61 + os.remove(excluded) 1.62 + 1.63 +def do_cvs_export(modules, tag, cvsroot, cvs): 1.64 + """Check out a CVS directory without CVS metadata, using "export" 1.65 + modules is a list of directories to check out and the corresponding 1.66 + cvs module, e.g. (('js/ctypes/libffi', 'libffi'),) 1.67 + """ 1.68 + for module_tuple in modules: 1.69 + module = module_tuple[0] 1.70 + cvs_module = module_tuple[1] 1.71 + fullpath = os.path.join(topsrcdir, module) 1.72 + if os.path.exists(fullpath): 1.73 + print "Removing '%s'" % fullpath 1.74 + shutil.rmtree(fullpath) 1.75 + 1.76 + (parent, leaf) = os.path.split(module) 1.77 + print "CVS export begin: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC") 1.78 + check_call_noisy([cvs, '-d', cvsroot, 1.79 + 'export', '-r', tag, '-d', leaf, cvs_module], 1.80 + cwd=os.path.join(topsrcdir, parent)) 1.81 + print "CVS export end: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC") 1.82 + 1.83 +def toggle_trailing_blank_line(depname): 1.84 + """If the trailing line is empty, then we'll delete it. 1.85 + Otherwise we'll add a blank line.""" 1.86 + lines = open(depname, "r").readlines() 1.87 + if not lines: 1.88 + print >>sys.stderr, "unexpected short file" 1.89 + return 1.90 + 1.91 + if not lines[-1].strip(): 1.92 + # trailing line is blank, removing it 1.93 + open(depname, "wb").writelines(lines[:-1]) 1.94 + else: 1.95 + # adding blank line 1.96 + open(depname, "ab").write("\n") 1.97 + 1.98 +def get_trailing_blank_line_state(depname): 1.99 + lines = open(depname, "r").readlines() 1.100 + if not lines: 1.101 + print >>sys.stderr, "unexpected short file" 1.102 + return "no blank line" 1.103 + 1.104 + if not lines[-1].strip(): 1.105 + return "has blank line" 1.106 + else: 1.107 + return "no blank line" 1.108 + 1.109 +def update_nspr_or_nss(tag, depfile, destination, hgpath): 1.110 + print "reverting to HG version of %s to get its blank line state" % depfile 1.111 + check_call_noisy([options.hg, 'revert', depfile]) 1.112 + old_state = get_trailing_blank_line_state(depfile) 1.113 + print "old state of %s is: %s" % (depfile, old_state) 1.114 + do_hg_replace(destination, hgpath, tag, HG_EXCLUSIONS, options.hg) 1.115 + new_state = get_trailing_blank_line_state(depfile) 1.116 + print "new state of %s is: %s" % (depfile, new_state) 1.117 + if old_state == new_state: 1.118 + print "toggling blank line in: ", depfile 1.119 + toggle_trailing_blank_line(depfile) 1.120 + tag_file = destination + "/TAG-INFO" 1.121 + print >>file(tag_file, "w"), tag 1.122 + 1.123 +o = OptionParser(usage="client.py [options] update_nspr tagname | update_nss tagname | update_libffi tagname") 1.124 +o.add_option("--skip-mozilla", dest="skip_mozilla", 1.125 + action="store_true", default=False, 1.126 + help="Obsolete") 1.127 + 1.128 +o.add_option("--cvs", dest="cvs", default=os.environ.get('CVS', 'cvs'), 1.129 + help="The location of the cvs binary") 1.130 +o.add_option("--cvsroot", dest="cvsroot", 1.131 + help="The CVSROOT for libffi (default : %s)" % CVSROOT_LIBFFI) 1.132 +o.add_option("--hg", dest="hg", default=os.environ.get('HG', 'hg'), 1.133 + help="The location of the hg binary") 1.134 +o.add_option("--repo", dest="repo", 1.135 + help="the repo to update from (default: upstream repo)") 1.136 + 1.137 +try: 1.138 + options, args = o.parse_args() 1.139 + action = args[0] 1.140 +except IndexError: 1.141 + o.print_help() 1.142 + sys.exit(2) 1.143 + 1.144 +if action in ('checkout', 'co'): 1.145 + print >>sys.stderr, "Warning: client.py checkout is obsolete." 1.146 + pass 1.147 +elif action in ('update_nspr'): 1.148 + tag, = args[1:] 1.149 + depfile = "nsprpub/config/prdepend.h" 1.150 + if not options.repo: 1.151 + options.repo = 'https://hg.mozilla.org/projects/nspr' 1.152 + update_nspr_or_nss(tag, depfile, 'nsprpub', options.repo) 1.153 +elif action in ('update_nss'): 1.154 + tag, = args[1:] 1.155 + depfile = "security/nss/coreconf/coreconf.dep" 1.156 + if not options.repo: 1.157 + options.repo = 'https://hg.mozilla.org/projects/nss' 1.158 + update_nspr_or_nss(tag, depfile, 'security/nss', options.repo) 1.159 +elif action in ('update_libffi'): 1.160 + tag, = args[1:] 1.161 + if not options.cvsroot: 1.162 + options.cvsroot = CVSROOT_LIBFFI 1.163 + do_cvs_export(LIBFFI_DIRS, tag, options.cvsroot, options.cvs) 1.164 +else: 1.165 + o.print_help() 1.166 + sys.exit(2)