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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 def _inner_gen(): | 274 def _inner_gen(): |
275 yield function() | 275 yield function() |
276 while True: | 276 while True: |
277 yield | 277 yield |
278 return _inner_gen().next | 278 return _inner_gen().next |
279 | 279 |
280 | 280 |
281 ## Git functions | 281 ## Git functions |
282 | 282 |
283 | 283 |
| 284 def blame(filename, revision=None, porcelain=False, *args): |
| 285 command = ['blame'] |
| 286 if porcelain: |
| 287 command.append('-p') |
| 288 if revision is not None: |
| 289 command.append(revision) |
| 290 command.extend(['--', filename]) |
| 291 return run(*command) |
| 292 |
| 293 |
284 def branch_config(branch, option, default=None): | 294 def branch_config(branch, option, default=None): |
285 return config('branch.%s.%s' % (branch, option), default=default) | 295 return config('branch.%s.%s' % (branch, option), default=default) |
286 | 296 |
287 | 297 |
288 def config_regexp(pattern): | 298 def config_regexp(pattern): |
289 if IS_WIN: # pragma: no cover | 299 if IS_WIN: # pragma: no cover |
290 # this madness is because we call git.bat which calls git.exe which calls | 300 # this madness is because we call git.bat which calls git.exe which calls |
291 # bash.exe (or something to that effect). Each layer divides the number of | 301 # bash.exe (or something to that effect). Each layer divides the number of |
292 # ^'s by 2. | 302 # ^'s by 2. |
293 pattern = pattern.replace('^', '^' * 8) | 303 pattern = pattern.replace('^', '^' * 8) |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 if abort: | 549 if abort: |
540 run_with_retcode('rebase', '--abort') # ignore failure | 550 run_with_retcode('rebase', '--abort') # ignore failure |
541 return RebaseRet(False, cpe.stdout, cpe.stderr) | 551 return RebaseRet(False, cpe.stdout, cpe.stderr) |
542 | 552 |
543 | 553 |
544 def remove_merge_base(branch): | 554 def remove_merge_base(branch): |
545 del_branch_config(branch, 'base') | 555 del_branch_config(branch, 'base') |
546 del_branch_config(branch, 'base-upstream') | 556 del_branch_config(branch, 'base-upstream') |
547 | 557 |
548 | 558 |
| 559 def repo_root(): |
| 560 """Returns the absolute path to the repository root.""" |
| 561 return run('rev-parse', '--show-toplevel') |
| 562 |
| 563 |
549 def root(): | 564 def root(): |
550 return config('depot-tools.upstream', 'origin/master') | 565 return config('depot-tools.upstream', 'origin/master') |
551 | 566 |
552 | 567 |
| 568 @contextlib.contextmanager |
| 569 def less(): # pragma: no cover |
| 570 """Runs 'less' as context manager yielding its stdin as a PIPE. |
| 571 |
| 572 Automatically checks if sys.stdout is a non-TTY stream. If so, it avoids |
| 573 running less and just yields sys.stdout. |
| 574 """ |
| 575 if not sys.stdout.isatty(): |
| 576 yield sys.stdout |
| 577 return |
| 578 |
| 579 # Run with the same options that git uses (see setup_pager in git repo). |
| 580 # -F: Automatically quit if the output is less than one screen. |
| 581 # -R: Don't escape ANSI color codes. |
| 582 # -X: Don't clear the screen before starting. |
| 583 cmd = ('less', '-FRX') |
| 584 try: |
| 585 proc = subprocess2.Popen(cmd, stdin=subprocess2.PIPE) |
| 586 yield proc.stdin |
| 587 finally: |
| 588 proc.stdin.close() |
| 589 proc.wait() |
| 590 |
| 591 |
553 def run(*cmd, **kwargs): | 592 def run(*cmd, **kwargs): |
554 """The same as run_with_stderr, except it only returns stdout.""" | 593 """The same as run_with_stderr, except it only returns stdout.""" |
555 return run_with_stderr(*cmd, **kwargs)[0] | 594 return run_with_stderr(*cmd, **kwargs)[0] |
556 | 595 |
557 | 596 |
558 def run_with_retcode(*cmd, **kwargs): | 597 def run_with_retcode(*cmd, **kwargs): |
559 """Run a command but only return the status code.""" | 598 """Run a command but only return the status code.""" |
560 try: | 599 try: |
561 run(*cmd, **kwargs) | 600 run(*cmd, **kwargs) |
562 return 0 | 601 return 0 |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 ['HEAD']) | 899 ['HEAD']) |
861 | 900 |
862 | 901 |
863 def clone_file(repository, new_workdir, link, operation): | 902 def clone_file(repository, new_workdir, link, operation): |
864 if not os.path.exists(os.path.join(repository, link)): | 903 if not os.path.exists(os.path.join(repository, link)): |
865 return | 904 return |
866 link_dir = os.path.dirname(os.path.join(new_workdir, link)) | 905 link_dir = os.path.dirname(os.path.join(new_workdir, link)) |
867 if not os.path.exists(link_dir): | 906 if not os.path.exists(link_dir): |
868 os.makedirs(link_dir) | 907 os.makedirs(link_dir) |
869 operation(os.path.join(repository, link), os.path.join(new_workdir, link)) | 908 operation(os.path.join(repository, link), os.path.join(new_workdir, link)) |
OLD | NEW |