OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # git-cl -- a git-command for integrating reviews on Rietveld | 2 # git-cl -- a git-command for integrating reviews on Rietveld |
3 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 3 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
4 | 4 |
5 import errno | 5 import errno |
6 import logging | 6 import logging |
7 import optparse | 7 import optparse |
8 import os | 8 import os |
9 import re | 9 import re |
10 import StringIO | 10 import StringIO |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 | 475 |
476 SetProperty(settings.GetCCList(), 'CC list', 'cc') | 476 SetProperty(settings.GetCCList(), 'CC list', 'cc') |
477 SetProperty(settings.GetTreeStatusUrl(error_ok=True), 'Tree status URL', | 477 SetProperty(settings.GetTreeStatusUrl(error_ok=True), 'Tree status URL', |
478 'tree-status-url') | 478 'tree-status-url') |
479 SetProperty(settings.GetViewVCUrl(), 'ViewVC URL', 'viewvc-url') | 479 SetProperty(settings.GetViewVCUrl(), 'ViewVC URL', 'viewvc-url') |
480 | 480 |
481 # TODO: configure a default branch to diff against, rather than this | 481 # TODO: configure a default branch to diff against, rather than this |
482 # svn-based hackery. | 482 # svn-based hackery. |
483 | 483 |
484 | 484 |
485 class HookResults(object): | |
486 """Contains the parsed output of the presubmit hooks.""" | |
487 def __init__(self, output_from_hooks=None): | |
488 self.reviewers = [] | |
489 self.output = None | |
490 self._ParseOutputFromHooks(output_from_hooks) | |
491 | |
492 def _ParseOutputFromHooks(self, output_from_hooks): | |
493 if not output_from_hooks: | |
494 return | |
495 lines = [] | |
496 reviewers = [] | |
497 reviewer_regexp = re.compile('ADD: R=(.+)') | |
498 for l in output_from_hooks.splitlines(): | |
499 m = reviewer_regexp.match(l) | |
500 if m: | |
501 reviewers.extend(m.group(1).split(',')) | |
502 else: | |
503 lines.append(l) | |
504 self.output = '\n'.join(lines) | |
505 self.reviewers = ','.join(reviewers) | |
506 | |
507 | |
508 class ChangeDescription(object): | 485 class ChangeDescription(object): |
509 """Contains a parsed form of the change description.""" | 486 """Contains a parsed form of the change description.""" |
510 def __init__(self, subject, log_desc, reviewers): | 487 def __init__(self, subject, log_desc, reviewers): |
511 self.subject = subject | 488 self.subject = subject |
512 self.log_desc = log_desc | 489 self.log_desc = log_desc |
513 self.reviewers = reviewers | 490 self.reviewers = reviewers |
514 self.description = self.log_desc | 491 self.description = self.log_desc |
515 | 492 |
516 def Update(self): | 493 def Update(self): |
517 initial_text = """# Enter a description of the change. | 494 initial_text = """# Enter a description of the change. |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 issue, patchset) | 742 issue, patchset) |
766 | 743 |
767 # Apply watchlists on upload. | 744 # Apply watchlists on upload. |
768 if not committing: | 745 if not committing: |
769 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | 746 watchlist = watchlists.Watchlists(change.RepositoryRoot()) |
770 files = [f.LocalPath() for f in change.AffectedFiles()] | 747 files = [f.LocalPath() for f in change.AffectedFiles()] |
771 watchers = watchlist.GetWatchersForPaths(files) | 748 watchers = watchlist.GetWatchersForPaths(files) |
772 RunCommand(['git', 'config', '--replace-all', | 749 RunCommand(['git', 'config', '--replace-all', |
773 'rietveld.extracc', ','.join(watchers)]) | 750 'rietveld.extracc', ','.join(watchers)]) |
774 | 751 |
775 output = StringIO.StringIO() | 752 output = presubmit_support.DoPresubmitChecks(change, committing, |
776 should_continue = presubmit_support.DoPresubmitChecks(change, committing, | 753 verbose=False, output_stream=sys.stdout, input_stream=sys.stdin, |
777 verbose=None, output_stream=output, input_stream=sys.stdin, | 754 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, |
778 default_presubmit=None, may_prompt=False, tbr=tbr, | |
779 host_url=cl.GetRietveldServer()) | 755 host_url=cl.GetRietveldServer()) |
780 hook_results = HookResults(output.getvalue()) | |
781 if hook_results.output: | |
782 print hook_results.output | |
783 | 756 |
784 # TODO(dpranke): We should propagate the error out instead of calling exit(). | 757 # TODO(dpranke): We should propagate the error out instead of calling exit(). |
785 if should_continue and hook_results.output and ( | 758 if not output.should_continue(): |
786 '** Presubmit ERRORS **\n' in hook_results.output or | 759 sys.exit(1) |
787 '** Presubmit WARNINGS **\n' in hook_results.output): | |
788 should_continue = False | |
789 | |
790 if not should_continue: | |
791 if may_prompt: | |
792 response = raw_input('Are you sure you want to continue? (y/N): ') | |
793 if not response.lower().startswith('y'): | |
794 sys.exit(1) | |
795 else: | |
796 sys.exit(1) | |
797 | |
798 | |
799 return hook_results | |
800 | 760 |
801 | 761 |
802 def CMDpresubmit(parser, args): | 762 def CMDpresubmit(parser, args): |
803 """run presubmit tests on the current changelist""" | 763 """run presubmit tests on the current changelist""" |
804 parser.add_option('--upload', action='store_true', | 764 parser.add_option('--upload', action='store_true', |
805 help='Run upload hook instead of the push/dcommit hook') | 765 help='Run upload hook instead of the push/dcommit hook') |
806 (options, args) = parser.parse_args(args) | 766 (options, args) = parser.parse_args(args) |
807 | 767 |
808 # Make sure index is up-to-date before running diff-index. | 768 # Make sure index is up-to-date before running diff-index. |
809 RunGit(['update-index', '--refresh', '-q'], error_ok=True) | 769 RunGit(['update-index', '--refresh', '-q'], error_ok=True) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 base_branch = args[0] | 827 base_branch = args[0] |
868 else: | 828 else: |
869 # Default to diffing against the "upstream" branch. | 829 # Default to diffing against the "upstream" branch. |
870 base_branch = cl.GetUpstreamBranch() | 830 base_branch = cl.GetUpstreamBranch() |
871 args = [base_branch + "..."] | 831 args = [base_branch + "..."] |
872 | 832 |
873 if not options.bypass_hooks: | 833 if not options.bypass_hooks: |
874 hook_results = RunHook(committing=False, upstream_branch=base_branch, | 834 hook_results = RunHook(committing=False, upstream_branch=base_branch, |
875 rietveld_server=cl.GetRietveldServer(), tbr=False, | 835 rietveld_server=cl.GetRietveldServer(), tbr=False, |
876 may_prompt=(not options.force)) | 836 may_prompt=(not options.force)) |
877 else: | 837 if not options.reviewers and hook_results.reviewers: |
878 hook_results = HookResults() | 838 options.reviewers = hook_results.reviewers |
879 | 839 |
880 if not options.reviewers and hook_results.reviewers: | |
881 options.reviewers = hook_results.reviewers | |
882 | 840 |
883 # --no-ext-diff is broken in some versions of Git, so try to work around | 841 # --no-ext-diff is broken in some versions of Git, so try to work around |
884 # this by overriding the environment (but there is still a problem if the | 842 # this by overriding the environment (but there is still a problem if the |
885 # git config key "diff.external" is used). | 843 # git config key "diff.external" is used). |
886 env = os.environ.copy() | 844 env = os.environ.copy() |
887 if 'GIT_EXTERNAL_DIFF' in env: | 845 if 'GIT_EXTERNAL_DIFF' in env: |
888 del env['GIT_EXTERNAL_DIFF'] | 846 del env['GIT_EXTERNAL_DIFF'] |
889 subprocess.call(['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, | 847 subprocess.call(['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, |
890 env=env) | 848 env=env) |
891 | 849 |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 1366 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
1409 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1367 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
1410 | 1368 |
1411 # Not a known command. Default to help. | 1369 # Not a known command. Default to help. |
1412 GenUsage(parser, 'help') | 1370 GenUsage(parser, 'help') |
1413 return CMDhelp(parser, argv) | 1371 return CMDhelp(parser, argv) |
1414 | 1372 |
1415 | 1373 |
1416 if __name__ == '__main__': | 1374 if __name__ == '__main__': |
1417 sys.exit(main(sys.argv[1:])) | 1375 sys.exit(main(sys.argv[1:])) |
OLD | NEW |