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 |