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