| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 # Monkeypatch IMapIterator so that Ctrl-C can kill everything properly. | 5 # Monkeypatch IMapIterator so that Ctrl-C can kill everything properly. |
| 6 # Derived from https://gist.github.com/aljungberg/626518 | 6 # Derived from https://gist.github.com/aljungberg/626518 |
| 7 import multiprocessing.pool | 7 import multiprocessing.pool |
| 8 from multiprocessing.pool import IMapIterator | 8 from multiprocessing.pool import IMapIterator |
| 9 def wrapper(func): | 9 def wrapper(func): |
| 10 def wrap(self, timeout=None): | 10 def wrap(self, timeout=None): |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 | 238 |
| 239 | 239 |
| 240 def branches(*args): | 240 def branches(*args): |
| 241 NO_BRANCH = ('* (no branch', '* (detached from ') | 241 NO_BRANCH = ('* (no branch', '* (detached from ') |
| 242 for line in run('branch', *args).splitlines(): | 242 for line in run('branch', *args).splitlines(): |
| 243 if line.startswith(NO_BRANCH): | 243 if line.startswith(NO_BRANCH): |
| 244 continue | 244 continue |
| 245 yield line.split()[-1] | 245 yield line.split()[-1] |
| 246 | 246 |
| 247 | 247 |
| 248 def run_with_retcode(*cmd, **kwargs): |
| 249 """Run a command but only return the status code.""" |
| 250 try: |
| 251 run(*cmd, **kwargs) |
| 252 return 0 |
| 253 except subprocess2.CalledProcessError as cpe: |
| 254 return cpe.returncode |
| 255 |
| 256 |
| 248 def config(option, default=None): | 257 def config(option, default=None): |
| 249 try: | 258 try: |
| 250 return run('config', '--get', option) or default | 259 return run('config', '--get', option) or default |
| 251 except subprocess2.CalledProcessError: | 260 except subprocess2.CalledProcessError: |
| 252 return default | 261 return default |
| 253 | 262 |
| 254 | 263 |
| 255 def config_list(option): | 264 def config_list(option): |
| 256 try: | 265 try: |
| 257 return run('config', '--get-all', option).split() | 266 return run('config', '--get-all', option).split() |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 | 324 |
| 316 return skipped, branch_tree | 325 return skipped, branch_tree |
| 317 | 326 |
| 318 | 327 |
| 319 def get_or_create_merge_base(branch, parent=None): | 328 def get_or_create_merge_base(branch, parent=None): |
| 320 """Finds the configured merge base for branch. | 329 """Finds the configured merge base for branch. |
| 321 | 330 |
| 322 If parent is supplied, it's used instead of calling upstream(branch). | 331 If parent is supplied, it's used instead of calling upstream(branch). |
| 323 """ | 332 """ |
| 324 base = branch_config(branch, 'base') | 333 base = branch_config(branch, 'base') |
| 334 parent = parent or upstream(branch) |
| 335 actual_merge_base = run('merge-base', parent, branch) |
| 336 |
| 337 def is_ancestor(a, b): |
| 338 return run_with_retcode('merge-base', '--is-ancestor', a, b) == 0 |
| 339 |
| 325 if base: | 340 if base: |
| 326 try: | 341 if not is_ancestor(base, branch): |
| 327 run('merge-base', '--is-ancestor', base, branch) | |
| 328 logging.debug('Found pre-set merge-base for %s: %s', branch, base) | |
| 329 except subprocess2.CalledProcessError: | |
| 330 logging.debug('Found WRONG pre-set merge-base for %s: %s', branch, base) | 342 logging.debug('Found WRONG pre-set merge-base for %s: %s', branch, base) |
| 331 base = None | 343 base = None |
| 344 elif is_ancestor(base, actual_merge_base): |
| 345 logging.debug('Found OLD pre-set merge-base for %s: %s', branch, base) |
| 346 base = None |
| 347 else: |
| 348 logging.debug('Found pre-set merge-base for %s: %s', branch, base) |
| 332 | 349 |
| 333 if not base: | 350 if not base: |
| 334 base = run('merge-base', parent or upstream(branch), branch) | 351 base = actual_merge_base |
| 335 manual_merge_base(branch, base) | 352 manual_merge_base(branch, base) |
| 336 | 353 |
| 337 return base | 354 return base |
| 338 | 355 |
| 339 | 356 |
| 340 def hash_multi(*reflike): | 357 def hash_multi(*reflike): |
| 341 return run('rev-parse', *reflike).splitlines() | 358 return run('rev-parse', *reflike).splitlines() |
| 342 | 359 |
| 343 | 360 |
| 344 def hash_one(reflike): | 361 def hash_one(reflike): |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 return None | 629 return None |
| 613 return ret | 630 return ret |
| 614 | 631 |
| 615 | 632 |
| 616 def upstream(branch): | 633 def upstream(branch): |
| 617 try: | 634 try: |
| 618 return run('rev-parse', '--abbrev-ref', '--symbolic-full-name', | 635 return run('rev-parse', '--abbrev-ref', '--symbolic-full-name', |
| 619 branch+'@{upstream}') | 636 branch+'@{upstream}') |
| 620 except subprocess2.CalledProcessError: | 637 except subprocess2.CalledProcessError: |
| 621 return None | 638 return None |
| OLD | NEW |