Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 | 6 import codecs |
| 7 import copy | 7 import copy |
| 8 import optparse | 8 import optparse |
| 9 import os | 9 import os |
| 10 import pprint | |
| 11 import shutil | |
| 12 import socket | |
| 13 import subprocess | |
| 10 import sys | 14 import sys |
| 15 import time | |
| 11 import urlparse | 16 import urlparse |
| 12 | 17 |
| 18 import os.path as path | |
| 19 | |
| 13 | 20 |
| 14 RECOGNIZED_PATHS = { | 21 RECOGNIZED_PATHS = { |
| 15 # If SVN path matches key, the entire URL is rewritten to the Git url. | 22 # If SVN path matches key, the entire URL is rewritten to the Git url. |
| 16 '/chrome/trunk/src': | 23 '/chrome/trunk/src': |
| 17 'https://chromium.googlesource.com/chromium/src.git', | 24 'https://chromium.googlesource.com/chromium/src.git', |
| 18 '/chrome-internal/trunk/src-internal': | 25 '/chrome-internal/trunk/src-internal': |
| 19 'https://chrome-internal.googlesource.com/chrome/src-internal.git' | 26 'https://chrome-internal.googlesource.com/chrome/src-internal.git' |
| 20 } | 27 } |
| 21 | 28 |
| 22 | 29 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 44 The bot will perform a Git checkout in this step. | 51 The bot will perform a Git checkout in this step. |
| 45 The "gclient revert" and "update" steps are no-ops. | 52 The "gclient revert" and "update" steps are no-ops. |
| 46 | 53 |
| 47 """ | 54 """ |
| 48 | 55 |
| 49 NOT_ACTIVATED_MESSAGE = """INACTIVE. | 56 NOT_ACTIVATED_MESSAGE = """INACTIVE. |
| 50 This step does nothing. You actually want to look at the "update" step. | 57 This step does nothing. You actually want to look at the "update" step. |
| 51 | 58 |
| 52 """ | 59 """ |
| 53 | 60 |
| 61 | |
| 62 GCLIENT_TEMPLATE = """solutions = %(solutions)s | |
| 63 | |
| 64 cache_dir = %(cache_dir)s | |
| 65 """ | |
| 66 | |
| 54 ENABLED_MASTERS = ['chromium.git'] | 67 ENABLED_MASTERS = ['chromium.git'] |
| 55 # Master: Builders dict. | |
| 56 ENABLED_BUILDERS = {} | 68 ENABLED_BUILDERS = {} |
| 57 # Master: Slaves dict. | |
| 58 ENABLED_SLAVES = {} | 69 ENABLED_SLAVES = {} |
| 59 | 70 |
| 60 # Disabled filters get run AFTER enabled filters, so for example if a builder | 71 # Disabled filters get run AFTER enabled filters, so for example if a builder |
| 61 # config is enabled, but a bot on that builder is disabled, that bot will | 72 # config is enabled, but a bot on that builder is disabled, that bot will |
| 62 # be disabled. | 73 # be disabled. |
| 63 DISABLED_BUILDERS = {} | 74 DISABLED_BUILDERS = {} |
| 64 DISABLED_SLAVES = {} | 75 DISABLED_SLAVES = {} |
| 65 | 76 |
| 77 # How many times to retry failed subprocess calls. | |
| 78 RETRIES = 3 | |
| 79 | |
| 80 SCRIPTS_PATH = path.dirname(path.dirname(path.abspath(__file__))) | |
| 81 DEPS2GIT_DIR_PATH = path.join(SCRIPTS_PATH, 'tools', 'deps2git') | |
| 82 DEPS2GIT_PATH = path.join(DEPS2GIT_DIR_PATH, 'deps2git.py') | |
| 83 S2G_INTERNAL_FROM_PATH = path.join(SCRIPTS_PATH, 'tools', 'deps2git_internal', | |
| 84 'svn_to_git_internal.py') | |
| 85 S2G_INTERNAL_DEST_PATH = path.join(DEPS2GIT_DIR_PATH, 'svn_to_git_internal.py') | |
| 86 | |
| 87 # ../../cache_dir aka /b/build/slave/cache_dir | |
| 88 THIS_DIR = path.abspath(os.getcwd()) | |
| 89 BUILDER_DIR = path.dirname(THIS_DIR) | |
| 90 SLAVE_DIR = path.dirname(BUILDER_DIR) | |
| 91 CACHE_DIR = path.join(SLAVE_DIR, 'cache_dir') | |
| 92 | |
| 93 | |
| 94 class SubprocessFailed(Exception): | |
| 95 pass | |
| 96 | |
| 97 | |
| 98 def call(*args): | |
| 99 """Interactive subprocess call.""" | |
| 100 tries = 0 | |
|
iannucci
2014/02/08 03:37:21
don't need this var any more
Ryan Tseng
2014/02/10 23:11:28
Done.
| |
| 101 for tries in xrange(RETRIES): | |
|
iannucci
2014/02/08 03:37:21
this should be a singular word like 'attempt'
Ryan Tseng
2014/02/10 23:11:28
Done.
| |
| 102 tries_msg = '(retry #%d)' % tries if tries else '' | |
| 103 print '===Running %s%s===' % (' '.join(args), tries_msg) | |
| 104 start_time = time.time() | |
| 105 proc = subprocess.Popen(args, stdout=subprocess.PIPE, | |
| 106 stderr=subprocess.STDOUT) | |
| 107 # This is here because passing 'sys.stdout' into stdout for proc will | |
| 108 # produce out of order output. | |
| 109 while True: | |
| 110 buf = proc.stdout.read(1) | |
| 111 if not buf: | |
| 112 break | |
| 113 sys.stdout.write(buf) | |
| 114 code = proc.wait() | |
| 115 elapsed_time = ((time.time() - start_time) / 60.0) | |
| 116 if not code: | |
| 117 print '===Succeeded in %.1f mins===' % elapsed_time | |
| 118 print | |
| 119 return 0 | |
| 120 print '===Failed in %.1f mins===' % elapsed_time | |
| 121 print | |
| 122 tries += 1 | |
|
iannucci
2014/02/08 03:37:21
don't need this
Ryan Tseng
2014/02/10 23:11:28
Done.
| |
| 123 | |
| 124 raise SubprocessFailed('%s failed with code %d in %s after %d tries.' % | |
| 125 (' '.join(args), code, os.getcwd(), RETRIES)) | |
| 126 | |
| 127 | |
| 128 def get_gclient_spec(solutions): | |
| 129 return GCLIENT_TEMPLATE % { | |
| 130 'solutions': pprint.pformat(solutions, indent=4), | |
| 131 'cache_dir': '"%s"' % CACHE_DIR | |
| 132 } | |
| 133 | |
| 66 | 134 |
| 67 def check_enabled(master, builder, slave): | 135 def check_enabled(master, builder, slave): |
| 68 if master in ENABLED_MASTERS: | 136 if master in ENABLED_MASTERS: |
| 69 return True | 137 return True |
| 70 builder_list = ENABLED_BUILDERS.get(master) | 138 builder_list = ENABLED_BUILDERS.get(master) |
| 71 if builder_list and builder in builder_list: | 139 if builder_list and builder in builder_list: |
| 72 return True | 140 return True |
| 73 slave_list = ENABLED_SLAVES.get(master) | 141 slave_list = ENABLED_SLAVES.get(master) |
| 74 if slave_list and slave in slave_list: | 142 if slave_list and slave in slave_list: |
| 75 return True | 143 return True |
| 76 return False | 144 return False |
| 77 | 145 |
| 78 | 146 |
| 79 def check_disabled(master, builder, slave): | 147 def check_disabled(master, builder, slave): |
| 80 """Returns True if disabled, False if not disabled.""" | 148 """Returns True if disabled, False if not disabled.""" |
| 81 builder_list = DISABLED_BUILDERS.get(master) | 149 builder_list = DISABLED_BUILDERS.get(master) |
| 82 if builder_list and builder in builder_list: | 150 if builder_list and builder in builder_list: |
| 83 return True | 151 return True |
| 84 slave_list = DISABLED_SLAVES.get(master) | 152 slave_list = DISABLED_SLAVES.get(master) |
| 85 if slave_list and slave in slave_list: | 153 if slave_list and slave in slave_list: |
| 86 return True | 154 return True |
| 87 return False | 155 return False |
| 88 | 156 |
| 89 | 157 |
| 90 def check_valid_host(master, builder, slave): | 158 def check_valid_host(master, builder, slave): |
| 91 return False | 159 return (check_enabled(master, builder, slave) |
| 160 and not check_disabled(master, builder, slave)) | |
| 92 | 161 |
| 93 | 162 |
| 94 def solutions_printer(solutions): | 163 def solutions_printer(solutions): |
| 95 """Prints gclient solution to stdout.""" | 164 """Prints gclient solution to stdout.""" |
| 96 print 'Gclient Solutions' | 165 print 'Gclient Solutions' |
| 97 print '=================' | 166 print '=================' |
| 98 for solution in solutions: | 167 for solution in solutions: |
| 99 name = solution.get('name') | 168 name = solution.get('name') |
| 100 url = solution.get('url') | 169 url = solution.get('url') |
| 101 print '%s (%s)' % (name, url) | 170 print '%s (%s)' % (name, url) |
| 171 if solution.get('deps_file'): | |
| 172 print ' Dependencies file is %s' % solution['deps_file'] | |
| 173 if 'managed' in solution: | |
| 174 print ' Managed mode is %s' % ('ON' if solution['managed'] else 'OFF') | |
| 102 custom_vars = solution.get('custom_vars') | 175 custom_vars = solution.get('custom_vars') |
| 103 if custom_vars: | 176 if custom_vars: |
| 104 print ' Custom Variables:' | 177 print ' Custom Variables:' |
| 105 for var_name, var_value in sorted(custom_vars.iteritems()): | 178 for var_name, var_value in sorted(custom_vars.iteritems()): |
| 106 print ' %s = %s' % (var_name, var_value) | 179 print ' %s = %s' % (var_name, var_value) |
| 107 custom_deps = solution.get('custom_deps') | 180 custom_deps = solution.get('custom_deps') |
| 108 if 'custom_deps' in solution: | 181 if 'custom_deps' in solution: |
| 109 print ' Custom Dependencies:' | 182 print ' Custom Dependencies:' |
| 110 for deps_name, deps_value in sorted(custom_deps.iteritems()): | 183 for deps_name, deps_value in sorted(custom_deps.iteritems()): |
| 111 if deps_value: | 184 if deps_value: |
| 112 print ' %s -> %s' % (deps_name, deps_value) | 185 print ' %s -> %s' % (deps_name, deps_value) |
| 113 else: | 186 else: |
| 114 print ' %s: Ignore' % deps_name | 187 print ' %s: Ignore' % deps_name |
| 115 if solution.get('deps_file'): | |
| 116 print ' Dependencies file is %s' % solution['deps_file'] | |
| 117 if 'managed' in solution: | |
| 118 print ' Managed mode is %s' % ('ON' if solution['managed'] else 'OFF') | |
| 119 print | 188 print |
| 120 | 189 |
| 121 | 190 |
| 122 def solutions_to_git(input_solutions): | 191 def solutions_to_git(input_solutions): |
| 123 """Modifies urls in solutions to point at Git repos.""" | 192 """Modifies urls in solutions to point at Git repos.""" |
| 124 solutions = copy.deepcopy(input_solutions) | 193 solutions = copy.deepcopy(input_solutions) |
| 125 for solution in solutions: | 194 for solution in solutions: |
| 126 original_url = solution['url'] | 195 original_url = solution['url'] |
| 127 parsed_url = urlparse.urlparse(original_url) | 196 parsed_url = urlparse.urlparse(original_url) |
| 128 path = parsed_url.path | 197 parsed_path = parsed_url.path |
| 129 if path in RECOGNIZED_PATHS: | 198 if parsed_path in RECOGNIZED_PATHS: |
| 130 solution['url'] = RECOGNIZED_PATHS[path] | 199 solution['url'] = RECOGNIZED_PATHS[parsed_path] |
| 131 else: | 200 else: |
| 132 print 'Warning: path %s not recognized' % path | 201 print 'Warning: path %s not recognized' % parsed_path |
| 133 if solution.get('deps_file', 'DEPS') == 'DEPS': | 202 if solution.get('deps_file', 'DEPS') == 'DEPS': |
| 134 solution['deps_file'] = '.DEPS.git' | 203 solution['deps_file'] = '.DEPS.git' |
| 135 solution['managed'] = False | 204 solution['managed'] = False |
| 136 return solutions | 205 return solutions |
| 137 | 206 |
| 138 | 207 |
| 139 def ensure_no_git_checkout(): | 208 def ensure_no_checkout(dir_names, scm_dirname): |
| 140 """Ensure that there is no git checkout under build/. | 209 """Ensure that there is no git checkout under build/. |
| 141 | 210 |
| 142 If there is a git checkout under build/, then move build/ to build.dead/ | 211 If there is an incorrect checkout under build/, then |
| 212 move build/ to build.dead/ | |
| 213 This function will check each directory in dir_names. | |
| 214 | |
| 215 scm_dirname is expected to be either ['.svn', '.git'] | |
| 143 """ | 216 """ |
| 144 pass | 217 assert scm_dirname in ['.svn', '.git'] |
| 218 has_checkout = any(map(lambda dir_name: path.exists( | |
| 219 path.join(os.getcwd(), dir_name, scm_dirname)), dir_names)) | |
| 145 | 220 |
| 221 if has_checkout: | |
| 222 # cd .. && rm -rf ./build && mkdir ./build && cd build | |
| 223 build_dir = os.getcwd() | |
| 146 | 224 |
| 147 def ensure_no_svn_checkout(): | 225 os.chdir(path.dirname(os.getcwd())) |
| 148 """Ensure that there is no svn checkout under build/. | 226 print '%s detected in checkout, deleting %s...' % (scm_dirname, build_dir), |
| 227 shutil.rmtree(build_dir) | |
| 228 print 'done' | |
| 229 os.mkdir(build_dir) | |
| 230 os.chdir(build_dir) | |
| 149 | 231 |
| 150 If there is a svn checkout under build/, then move build/ to build.dead/ | |
| 151 """ | |
| 152 pass | |
| 153 | 232 |
| 154 | 233 |
| 155 def gclient_configure(solutions): | 234 def gclient_configure(solutions): |
| 156 pass | 235 """Should do the same thing as gclient --spec='...'.""" |
| 236 with codecs.open('.gclient', mode='w', encoding='utf-8') as f: | |
| 237 f.write(get_gclient_spec(solutions)) | |
| 157 | 238 |
| 158 | 239 |
| 159 def gclient_shallow_sync(): | 240 def gclient_sync(): |
| 160 pass | 241 call('gclient', 'sync', '--verbose', '--reset', '--force', |
| 242 '--nohooks', '--noprehooks') | |
| 161 | 243 |
| 162 | 244 |
| 163 def git_pull_and_clean(): | 245 def get_git_hash(revision, dir_name): |
| 164 pass | 246 match = "^git-svn-id: [^ ]*@%d" % revision |
| 247 cmd = ['git', 'log', '--grep', match, '--format=%H', dir_name] | |
| 248 return subprocess.check_output(cmd).strip() or None | |
| 249 | |
| 250 | |
| 251 def deps2git(sln_dirs): | |
| 252 for sln_dir in sln_dirs: | |
| 253 deps_file = path.join(os.getcwd(), sln_dir, 'DEPS') | |
| 254 deps_git_file = path.join(os.getcwd(), sln_dir, '.DEPS.git') | |
| 255 if not path.isfile(deps_file): | |
| 256 return | |
| 257 # Do we have a better way of doing this....? | |
| 258 repo_type = 'internal' if 'internal' in sln_dir else 'public' | |
| 259 # TODO(hinoka): This will be what populates the git caches on the first | |
| 260 # run for all of the bots. Since deps2git is single threaded, | |
| 261 # all of this will run in a single threaded context and be | |
| 262 # super slow. Should make deps2git multithreaded. | |
| 263 call(sys.executable, DEPS2GIT_PATH, '-t', repo_type, | |
| 264 '--cache_dir=%s' % CACHE_DIR, | |
| 265 '--deps=%s' % deps_file, '--out=%s' % deps_git_file) | |
| 266 | |
| 267 | |
| 268 def git_checkout(solutions, revision): | |
| 269 build_dir = os.getcwd() | |
| 270 # Revision only applies to the first solution. | |
| 271 first_solution = True | |
| 272 for sln in solutions: | |
| 273 name = sln['name'] | |
| 274 url = sln['url'] | |
| 275 sln_dir = path.join(build_dir, name) | |
| 276 if not path.isdir(sln_dir): | |
| 277 call('git', 'clone', url, sln_dir) | |
| 278 | |
| 279 # Clean out .DEPS.git changes first. | |
| 280 call('git', '-C', sln_dir, 'reset', '--hard') | |
| 281 call('git', '-C', sln_dir, 'clean', '-df') | |
| 282 call('git', '-C', sln_dir, 'pull', 'origin', 'master') | |
| 283 # TODO(hinoka): We probably have to make use of revision mapping. | |
| 284 if first_solution and revision and revision.lower() != 'head': | |
| 285 if revision and revision.isdigit() and len(revision) < 40: | |
| 286 # rev_num is really a svn revision number, convert it into a git hash. | |
| 287 git_ref = get_git_hash(revision, name) | |
| 288 else: | |
| 289 # rev_num is actually a git hash or ref, we can just use it. | |
| 290 git_ref = revision | |
| 291 call('git', '-C', sln_dir, 'checkout', git_ref) | |
| 292 else: | |
| 293 call('git', '-C', sln_dir, 'checkout', 'origin/master') | |
| 294 | |
| 295 first_solution = False | |
| 165 | 296 |
| 166 | 297 |
| 167 def apply_issue(issue, patchset, root, server): | 298 def apply_issue(issue, patchset, root, server): |
| 168 pass | 299 pass |
| 169 | 300 |
| 170 | 301 |
| 171 def deps2git(): | 302 def delete_flag(flag_file): |
| 172 pass | 303 """Remove bot update flag.""" |
| 304 if os.path.exists(flag_file): | |
| 305 os.remove(flag_file) | |
| 173 | 306 |
| 174 | 307 |
| 175 def gclient_sync(): | 308 def emit_flag(flag_file): |
| 176 pass | |
| 177 | |
| 178 | |
| 179 def deposit_bot_update_flag(): | |
| 180 """Deposit a bot update flag on the system to tell gclient not to run.""" | 309 """Deposit a bot update flag on the system to tell gclient not to run.""" |
| 181 pass | 310 print 'Emitting flag file at %s' % flag_file |
| 311 with open(flag_file, 'wb') as f: | |
| 312 f.write('Success!') | |
| 182 | 313 |
| 183 | 314 |
| 184 def parse_args(): | 315 def parse_args(): |
| 185 parse = optparse.OptionParser() | 316 parse = optparse.OptionParser() |
| 186 | 317 |
| 187 parse.add_option('-i', '--issue', help='Issue number to patch from.') | 318 parse.add_option('--issue', help='Issue number to patch from.') |
| 188 parse.add_option('-p', '--patchset', | 319 parse.add_option('--patchset', |
| 189 help='Patchset from issue to patch from, if applicable.') | 320 help='Patchset from issue to patch from, if applicable.') |
| 190 parse.add_option('-r', '--root', help='Repository root.') | 321 parse.add_option('--patch_url') |
|
iannucci
2014/02/08 03:37:21
help text?
"Optional URL to SVN patch"
Ryan Tseng
2014/02/10 23:11:28
Done.
| |
| 191 parse.add_option('-c', '--server', help='Rietveld server.') | 322 parse.add_option('--root', help='Repository root.') |
| 192 parse.add_option('-s', '--specs', help='Gcilent spec.') | 323 parse.add_option('--rietveld_server', help='Rietveld server.') |
| 193 parse.add_option('-m', '--master', help='Master name.') | 324 parse.add_option('--specs', help='Gcilent spec.') |
| 325 parse.add_option('--master', help='Master name.') | |
| 194 parse.add_option('-f', '--force', action='store_true', | 326 parse.add_option('-f', '--force', action='store_true', |
| 195 help='Bypass check to see if we want to be run. ' | 327 help='Bypass check to see if we want to be run. ' |
| 196 'Should ONLY be used locally.') | 328 'Should ONLY be used locally.') |
| 197 parse.add_option('-e', '--revision-mapping') | 329 # TODO(hinoka): We don't actually use this yet, we should factor this in. |
| 330 parse.add_option('--revision-mapping') | |
| 331 parse.add_option('--revision') | |
| 332 parse.add_option('--build_dir', default=os.getcwd()) | |
| 333 parse.add_option('--flag_file', default=path.join(os.getcwd(), | |
| 334 'update.flag')) | |
| 198 | 335 |
| 199 return parse.parse_args() | 336 return parse.parse_args() |
| 200 | 337 |
| 201 | 338 |
| 202 def main(): | 339 def main(): |
| 203 # Get inputs. | 340 # Get inputs. |
| 204 options, _ = parse_args() | 341 options, _ = parse_args() |
| 205 builder = os.environ.get('BUILDBOT_BUILDERNAME', None) | 342 builder = os.environ.get('BUILDBOT_BUILDERNAME', None) |
| 206 slave = os.environ.get('BUILDBOT_SLAVENAME', None) | 343 slave = os.environ.get('BUILDBOT_SLAVENAME', socket.getfqdn().split('.')[0]) |
| 207 master = options.master | 344 master = options.master |
| 345 if not options.revision: | |
| 346 options.revision = os.environ.get('BUILDBOT_REVISION') | |
| 208 | 347 |
| 209 # Check if this script should activate or not. | 348 # Check if this script should activate or not. |
| 210 active = check_valid_host(master, builder, slave) or options.force | 349 active = check_valid_host(master, builder, slave) or options.force |
| 211 | 350 |
| 212 # Print helpful messages to tell devs whats going on. | 351 # Print helpful messages to tell devs whats going on. |
| 213 print BOT_UPDATE_MESSAGE % { | 352 print BOT_UPDATE_MESSAGE % { |
| 214 'master': master, | 353 'master': master, |
| 215 'builder': builder, | 354 'builder': builder, |
| 216 'slave': slave, | 355 'slave': slave, |
| 217 }, | 356 }, |
| 218 # Print to stderr so that it shows up red on win/mac. | 357 # Print to stderr so that it shows up red on win/mac. |
| 219 print ACTIVATED_MESSAGE if active else NOT_ACTIVATED_MESSAGE | 358 print ACTIVATED_MESSAGE if active else NOT_ACTIVATED_MESSAGE |
| 220 | 359 |
| 221 # Parse, munipulate, and print the gclient solutions. | 360 # Parse, munipulate, and print the gclient solutions. |
| 222 specs = {} | 361 specs = {} |
| 223 exec(options.specs, specs) # TODO(hinoka): LOL this is terrible. | 362 exec(options.specs, specs) |
| 224 solutions = specs.get('solutions', []) | 363 svn_solutions = specs.get('solutions', []) |
| 225 git_solutions = solutions_to_git(solutions) | 364 git_solutions = solutions_to_git(svn_solutions) |
| 226 solutions_printer(git_solutions) | 365 solutions_printer(git_solutions) |
| 227 | 366 |
| 228 # Do the checkout. | 367 # Cleanup svn checkout if active, otherwise remove git checkout and exit. |
| 229 # TODO(hinoka): Uncomment these once they're implemented. | 368 dir_names = [sln.get('name') for sln in svn_solutions if 'name' in sln] |
| 230 # ensure_no_svn_checkout() | 369 if active: |
| 231 # gclient_configure(git_solutions) | 370 ensure_no_checkout(dir_names, '.svn') |
| 232 # gclient_shallow_sync() | 371 emit_flag(options.flag_file) |
| 233 # git_pull_and_clean() | 372 else: |
| 373 ensure_no_checkout(dir_names, '.git') | |
| 374 delete_flag(options.flag_file) | |
| 375 return | |
| 376 | |
| 377 # Get a checkout of each solution, without DEPS or hooks. | |
| 378 # Calling git directory because there is no way to run Gclient without | |
| 379 # invoking DEPS. | |
| 380 print 'Fetching Git checkout' | |
| 381 git_checkout(git_solutions, options.revision) | |
| 382 | |
| 383 # TODO(hinoka): This must be implemented before we can turn this on for TS. | |
| 234 # if options.issue: | 384 # if options.issue: |
| 235 # apply_issue(options.issue, options.patchset, options.root, options.server) | 385 # apply_issue(options.issue, options.patchset, options.root, options.server) |
| 236 # deps2git() | 386 |
| 237 # gclient_sync() | 387 # Magic to get deps2git to work with internal DEPS. |
| 388 shutil.copyfile(S2G_INTERNAL_FROM_PATH, S2G_INTERNAL_DEST_PATH) | |
| 389 deps2git(dir_names) | |
| 390 | |
| 391 gclient_configure(git_solutions) | |
| 392 gclient_sync() | |
| 238 | 393 |
| 239 | 394 |
| 240 if __name__ == '__main__': | 395 if __name__ == '__main__': |
| 241 sys.exit(main()) | 396 sys.exit(main()) |
| OLD | NEW |