github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/repository/trusty/haproxy/cm.py (about) 1 # Copyright 2010-2013 Canonical Ltd. All rights reserved. 2 import os 3 import re 4 import sys 5 import errno 6 import hashlib 7 import subprocess 8 import optparse 9 10 from os import curdir 11 from bzrlib.branch import Branch 12 from bzrlib.plugin import load_plugins 13 load_plugins() 14 from bzrlib.plugins.launchpad import account as lp_account 15 16 if 'GlobalConfig' in dir(lp_account): 17 from bzrlib.config import LocationConfig as LocationConfiguration 18 _ = LocationConfiguration 19 else: 20 from bzrlib.config import LocationStack as LocationConfiguration 21 _ = LocationConfiguration 22 23 24 def get_branch_config(config_file): 25 """ 26 Retrieves the sourcedeps configuration for an source dir. 27 Returns a dict of (branch, revspec) tuples, keyed by branch name. 28 """ 29 branches = {} 30 with open(config_file, 'r') as stream: 31 for line in stream: 32 line = line.split('#')[0].strip() 33 bzr_match = re.match(r'(\S+)\s+' 34 'lp:([^;]+)' 35 '(?:;revno=(\d+))?', line) 36 if bzr_match: 37 name, branch, revno = bzr_match.group(1, 2, 3) 38 if revno is None: 39 revspec = -1 40 else: 41 revspec = revno 42 branches[name] = (branch, revspec) 43 continue 44 dir_match = re.match(r'(\S+)\s+' 45 '\(directory\)', line) 46 if dir_match: 47 name = dir_match.group(1) 48 branches[name] = None 49 return branches 50 51 52 def main(config_file, parent_dir, target_dir, verbose): 53 """Do the deed.""" 54 55 try: 56 os.makedirs(parent_dir) 57 except OSError, e: 58 if e.errno != errno.EEXIST: 59 raise 60 61 branches = sorted(get_branch_config(config_file).items()) 62 for branch_name, spec in branches: 63 if spec is None: 64 # It's a directory, just create it and move on. 65 destination_path = os.path.join(target_dir, branch_name) 66 if not os.path.isdir(destination_path): 67 os.makedirs(destination_path) 68 continue 69 70 (quoted_branch_spec, revspec) = spec 71 revno = int(revspec) 72 73 # qualify mirror branch name with hash of remote repo path to deal 74 # with changes to the remote branch URL over time 75 branch_spec_digest = hashlib.sha1(quoted_branch_spec).hexdigest() 76 branch_directory = branch_spec_digest 77 78 source_path = os.path.join(parent_dir, branch_directory) 79 destination_path = os.path.join(target_dir, branch_name) 80 81 # Remove leftover symlinks/stray files. 82 try: 83 os.remove(destination_path) 84 except OSError, e: 85 if e.errno != errno.EISDIR and e.errno != errno.ENOENT: 86 raise 87 88 lp_url = "lp:" + quoted_branch_spec 89 90 # Create the local mirror branch if it doesn't already exist 91 if verbose: 92 sys.stderr.write('%30s: ' % (branch_name,)) 93 sys.stderr.flush() 94 95 fresh = False 96 if not os.path.exists(source_path): 97 subprocess.check_call(['bzr', 'branch', '-q', '--no-tree', 98 '--', lp_url, source_path]) 99 fresh = True 100 101 if not fresh: 102 source_branch = Branch.open(source_path) 103 if revno == -1: 104 orig_branch = Branch.open(lp_url) 105 fresh = source_branch.revno() == orig_branch.revno() 106 else: 107 fresh = source_branch.revno() == revno 108 109 # Freshen the source branch if required. 110 if not fresh: 111 subprocess.check_call(['bzr', 'pull', '-q', '--overwrite', '-r', 112 str(revno), '-d', source_path, 113 '--', lp_url]) 114 115 if os.path.exists(destination_path): 116 # Overwrite the destination with the appropriate revision. 117 subprocess.check_call(['bzr', 'clean-tree', '--force', '-q', 118 '--ignored', '-d', destination_path]) 119 subprocess.check_call(['bzr', 'pull', '-q', '--overwrite', 120 '-r', str(revno), 121 '-d', destination_path, '--', source_path]) 122 else: 123 # Create a new branch. 124 subprocess.check_call(['bzr', 'branch', '-q', '--hardlink', 125 '-r', str(revno), 126 '--', source_path, destination_path]) 127 128 # Check the state of the destination branch. 129 destination_branch = Branch.open(destination_path) 130 destination_revno = destination_branch.revno() 131 132 if verbose: 133 sys.stderr.write('checked out %4s of %s\n' % 134 ("r" + str(destination_revno), lp_url)) 135 sys.stderr.flush() 136 137 if revno != -1 and destination_revno != revno: 138 raise RuntimeError("Expected revno %d but got revno %d" % 139 (revno, destination_revno)) 140 141 if __name__ == '__main__': 142 parser = optparse.OptionParser( 143 usage="%prog [options]", 144 description=( 145 "Add a lightweight checkout in <target> for each " 146 "corresponding file in <parent>."), 147 add_help_option=False) 148 parser.add_option( 149 '-p', '--parent', dest='parent', 150 default=None, 151 help=("The directory of the parent tree."), 152 metavar="DIR") 153 parser.add_option( 154 '-t', '--target', dest='target', default=curdir, 155 help=("The directory of the target tree."), 156 metavar="DIR") 157 parser.add_option( 158 '-c', '--config', dest='config', default=None, 159 help=("The config file to be used for config-manager."), 160 metavar="DIR") 161 parser.add_option( 162 '-q', '--quiet', dest='verbose', action='store_false', 163 help="Be less verbose.") 164 parser.add_option( 165 '-v', '--verbose', dest='verbose', action='store_true', 166 help="Be more verbose.") 167 parser.add_option( 168 '-h', '--help', action='help', 169 help="Show this help message and exit.") 170 parser.set_defaults(verbose=True) 171 172 options, args = parser.parse_args() 173 174 if options.parent is None: 175 options.parent = os.environ.get( 176 "SOURCEDEPS_DIR", 177 os.path.join(curdir, ".sourcecode")) 178 179 if options.target is None: 180 parser.error( 181 "Target directory not specified.") 182 183 if options.config is None: 184 config = [arg for arg in args 185 if arg != "update"] 186 if not config or len(config) > 1: 187 parser.error("Config not specified") 188 options.config = config[0] 189 190 sys.exit(main(config_file=options.config, 191 parent_dir=options.parent, 192 target_dir=options.target, 193 verbose=options.verbose))