OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
7 | 7 |
8 """A git-command for integrating reviews on Rietveld.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
9 | 9 |
10 import errno | 10 import errno |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 """Set this branch's issue. If issue=0, clears the issue.""" | 504 """Set this branch's issue. If issue=0, clears the issue.""" |
505 if issue: | 505 if issue: |
506 RunGit(['config', self._IssueSetting(), str(issue)]) | 506 RunGit(['config', self._IssueSetting(), str(issue)]) |
507 if self.rietveld_server: | 507 if self.rietveld_server: |
508 RunGit(['config', self._RietveldServer(), self.rietveld_server]) | 508 RunGit(['config', self._RietveldServer(), self.rietveld_server]) |
509 else: | 509 else: |
510 RunGit(['config', '--unset', self._IssueSetting()]) | 510 RunGit(['config', '--unset', self._IssueSetting()]) |
511 self.SetPatchset(0) | 511 self.SetPatchset(0) |
512 self.has_issue = False | 512 self.has_issue = False |
513 | 513 |
514 def RunHook(self, committing, upstream_branch, tbr, may_prompt, verbose): | |
515 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" | |
516 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() | |
517 if not root: | |
M-A Ruel
2011/04/18 14:43:11
While at it;
root = os.path.abspath(root or '.')
| |
518 root = '.' | |
519 absroot = os.path.abspath(root) | |
520 if not root: | |
521 raise Exception('Could not get root directory.') | |
522 | |
523 # We use the sha1 of HEAD as a name of this change. | |
524 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() | |
525 files = scm.GIT.CaptureStatus([root], upstream_branch) | |
526 | |
527 issue = ConvertToInteger(self.GetIssue()) | |
528 patchset = ConvertToInteger(self.GetPatchset()) | |
529 if issue: | |
530 description = self.GetDescription() | |
531 else: | |
532 # If the change was never uploaded, use the log messages of all commits | |
533 # up to the branch point, as git cl upload will prefill the description | |
534 # with these log messages. | |
535 description = RunCommand(['git', 'log', '--pretty=format:%s%n%n%b', | |
536 '%s...' % (upstream_branch)]).strip() | |
537 change = presubmit_support.GitChange( | |
538 name, | |
539 description, | |
540 absroot, | |
541 files, | |
542 issue, | |
543 patchset, | |
544 None) | |
545 | |
546 # Apply watchlists on upload. | |
547 if not committing: | |
548 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | |
549 files = [f.LocalPath() for f in change.AffectedFiles()] | |
550 self.SetWatchers(watchlist.GetWatchersForPaths(files)) | |
551 | |
552 try: | |
553 output = presubmit_support.DoPresubmitChecks(change, committing, | |
554 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, | |
555 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, | |
556 rietveld=self.RpcServer()) | |
557 except presubmit_support.PresubmitFailure, e: | |
558 DieWithError( | |
559 ('%s\nMaybe your depot_tools is out of date?\n' | |
560 'If all fails, contact maruel@') % e) | |
561 | |
562 # TODO(dpranke): We should propagate the error out instead of calling | |
563 # exit(). | |
564 if not output.should_continue(): | |
565 sys.exit(1) | |
566 | |
567 return output | |
568 | |
514 def CloseIssue(self): | 569 def CloseIssue(self): |
515 rpc_server = self.RpcServer() | 570 rpc_server = self.RpcServer() |
516 # Newer versions of Rietveld require us to pass an XSRF token to POST, so | 571 # Newer versions of Rietveld require us to pass an XSRF token to POST, so |
517 # we fetch it from the server. (The version used by Chromium has been | 572 # we fetch it from the server. (The version used by Chromium has been |
518 # modified so the token isn't required when closing an issue.) | 573 # modified so the token isn't required when closing an issue.) |
519 xsrf_token = rpc_server.Send('/xsrf_token', | 574 xsrf_token = rpc_server.Send('/xsrf_token', |
520 extra_headers={'X-Requesting-XSRF-Token': '1'}) | 575 extra_headers={'X-Requesting-XSRF-Token': '1'}) |
521 | 576 |
522 # You cannot close an issue with a GET. | 577 # You cannot close an issue with a GET. |
523 # We pass an empty string for the data so it is a POST rather than a GET. | 578 # We pass an empty string for the data so it is a POST rather than a GET. |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
805 | 860 |
806 | 861 |
807 def ConvertToInteger(inputval): | 862 def ConvertToInteger(inputval): |
808 """Convert a string to integer, but returns either an int or None.""" | 863 """Convert a string to integer, but returns either an int or None.""" |
809 try: | 864 try: |
810 return int(inputval) | 865 return int(inputval) |
811 except (TypeError, ValueError): | 866 except (TypeError, ValueError): |
812 return None | 867 return None |
813 | 868 |
814 | 869 |
815 def RunHook(committing, upstream_branch, rietveld_server, tbr, may_prompt, | |
816 verbose): | |
817 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" | |
818 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() | |
819 if not root: | |
820 root = '.' | |
821 absroot = os.path.abspath(root) | |
822 if not root: | |
823 raise Exception('Could not get root directory.') | |
824 | |
825 # We use the sha1 of HEAD as a name of this change. | |
826 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() | |
827 files = scm.GIT.CaptureStatus([root], upstream_branch) | |
828 | |
829 cl = Changelist() | |
830 issue = ConvertToInteger(cl.GetIssue()) | |
831 patchset = ConvertToInteger(cl.GetPatchset()) | |
832 if issue: | |
833 description = cl.GetDescription() | |
834 else: | |
835 # If the change was never uploaded, use the log messages of all commits | |
836 # up to the branch point, as git cl upload will prefill the description | |
837 # with these log messages. | |
838 description = RunCommand(['git', 'log', '--pretty=format:%s%n%n%b', | |
839 '%s...' % (upstream_branch)]).strip() | |
840 change = presubmit_support.GitChange( | |
841 name, | |
842 description, | |
843 absroot, | |
844 files, | |
845 issue, | |
846 patchset, | |
847 None) | |
848 | |
849 # Apply watchlists on upload. | |
850 if not committing: | |
851 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | |
852 files = [f.LocalPath() for f in change.AffectedFiles()] | |
853 cl.SetWatchers(watchlist.GetWatchersForPaths(files)) | |
854 | |
855 try: | |
856 output = presubmit_support.DoPresubmitChecks(change, committing, | |
857 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, | |
858 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, | |
859 rietveld=cl.RpcServer()) | |
860 except presubmit_support.PresubmitFailure, e: | |
861 DieWithError( | |
862 ('%s\nMaybe your depot_tools is out of date?\n' | |
863 'If all fails, contact maruel@') % e) | |
864 | |
865 # TODO(dpranke): We should propagate the error out instead of calling exit(). | |
866 if not output.should_continue(): | |
867 sys.exit(1) | |
868 | |
869 return output | |
870 | |
871 | |
872 def CMDpresubmit(parser, args): | 870 def CMDpresubmit(parser, args): |
873 """run presubmit tests on the current changelist""" | 871 """run presubmit tests on the current changelist""" |
874 parser.add_option('--upload', action='store_true', | 872 parser.add_option('--upload', action='store_true', |
875 help='Run upload hook instead of the push/dcommit hook') | 873 help='Run upload hook instead of the push/dcommit hook') |
876 (options, args) = parser.parse_args(args) | 874 (options, args) = parser.parse_args(args) |
877 | 875 |
878 # Make sure index is up-to-date before running diff-index. | 876 # Make sure index is up-to-date before running diff-index. |
879 RunGit(['update-index', '--refresh', '-q'], error_ok=True) | 877 RunGit(['update-index', '--refresh', '-q'], error_ok=True) |
880 if RunGit(['diff-index', 'HEAD']): | 878 if RunGit(['diff-index', 'HEAD']): |
881 # TODO(maruel): Is this really necessary? | 879 # TODO(maruel): Is this really necessary? |
882 print 'Cannot presubmit with a dirty tree. You must commit locally first.' | 880 print 'Cannot presubmit with a dirty tree. You must commit locally first.' |
883 return 1 | 881 return 1 |
884 | 882 |
885 cl = Changelist() | 883 cl = Changelist() |
886 if args: | 884 if args: |
887 base_branch = args[0] | 885 base_branch = args[0] |
888 else: | 886 else: |
889 # Default to diffing against the "upstream" branch. | 887 # Default to diffing against the "upstream" branch. |
890 base_branch = cl.GetUpstreamBranch() | 888 base_branch = cl.GetUpstreamBranch() |
891 | 889 |
892 RunHook(committing=not options.upload, upstream_branch=base_branch, | 890 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, |
893 rietveld_server=cl.GetRietveldServer(), tbr=False, | 891 tbr=False, may_prompt=False, verbose=options.verbose) |
894 may_prompt=False, verbose=options.verbose) | |
895 return 0 | 892 return 0 |
896 | 893 |
897 | 894 |
898 @usage('[args to "git diff"]') | 895 @usage('[args to "git diff"]') |
899 def CMDupload(parser, args): | 896 def CMDupload(parser, args): |
900 """upload the current changelist to codereview""" | 897 """upload the current changelist to codereview""" |
901 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', | 898 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', |
902 help='bypass upload presubmit hook') | 899 help='bypass upload presubmit hook') |
903 parser.add_option('-f', action='store_true', dest='force', | 900 parser.add_option('-f', action='store_true', dest='force', |
904 help="force yes to questions (don't prompt)") | 901 help="force yes to questions (don't prompt)") |
(...skipping 21 matching lines...) Expand all Loading... | |
926 | 923 |
927 cl = Changelist() | 924 cl = Changelist() |
928 if args: | 925 if args: |
929 base_branch = args[0] | 926 base_branch = args[0] |
930 else: | 927 else: |
931 # Default to diffing against the "upstream" branch. | 928 # Default to diffing against the "upstream" branch. |
932 base_branch = cl.GetUpstreamBranch() | 929 base_branch = cl.GetUpstreamBranch() |
933 args = [base_branch + "..."] | 930 args = [base_branch + "..."] |
934 | 931 |
935 if not options.bypass_hooks and not options.force: | 932 if not options.bypass_hooks and not options.force: |
936 hook_results = RunHook(committing=False, upstream_branch=base_branch, | 933 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, |
937 rietveld_server=cl.GetRietveldServer(), tbr=False, | 934 tbr=False, may_prompt=True, |
938 may_prompt=True, verbose=options.verbose) | 935 verbose=options.verbose) |
939 if not options.reviewers and hook_results.reviewers: | 936 if not options.reviewers and hook_results.reviewers: |
940 options.reviewers = hook_results.reviewers | 937 options.reviewers = hook_results.reviewers |
941 | 938 |
942 | 939 |
943 # --no-ext-diff is broken in some versions of Git, so try to work around | 940 # --no-ext-diff is broken in some versions of Git, so try to work around |
944 # this by overriding the environment (but there is still a problem if the | 941 # this by overriding the environment (but there is still a problem if the |
945 # git config key "diff.external" is used). | 942 # git config key "diff.external" is used). |
946 env = os.environ.copy() | 943 env = os.environ.copy() |
947 if 'GIT_EXTERNAL_DIFF' in env: | 944 if 'GIT_EXTERNAL_DIFF' in env: |
948 del env['GIT_EXTERNAL_DIFF'] | 945 del env['GIT_EXTERNAL_DIFF'] |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1079 '--pretty=format:%H']) | 1076 '--pretty=format:%H']) |
1080 extra_commits = RunGit(['rev-list', '^' + svn_head, base_branch]) | 1077 extra_commits = RunGit(['rev-list', '^' + svn_head, base_branch]) |
1081 if extra_commits: | 1078 if extra_commits: |
1082 print ('This branch has %d additional commits not upstreamed yet.' | 1079 print ('This branch has %d additional commits not upstreamed yet.' |
1083 % len(extra_commits.splitlines())) | 1080 % len(extra_commits.splitlines())) |
1084 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' | 1081 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' |
1085 'before attempting to %s.' % (base_branch, cmd)) | 1082 'before attempting to %s.' % (base_branch, cmd)) |
1086 return 1 | 1083 return 1 |
1087 | 1084 |
1088 if not options.bypass_hooks and not options.force: | 1085 if not options.bypass_hooks and not options.force: |
1089 RunHook(committing=True, upstream_branch=base_branch, | 1086 cl.RunHook(committing=True, upstream_branch=base_branch, |
1090 rietveld_server=cl.GetRietveldServer(), tbr=options.tbr, | 1087 tbr=options.tbr, may_prompt=True, verbose=options.verbose) |
1091 may_prompt=True, verbose=options.verbose) | |
1092 | 1088 |
1093 if cmd == 'dcommit': | 1089 if cmd == 'dcommit': |
1094 # Check the tree status if the tree status URL is set. | 1090 # Check the tree status if the tree status URL is set. |
1095 status = GetTreeStatus() | 1091 status = GetTreeStatus() |
1096 if 'closed' == status: | 1092 if 'closed' == status: |
1097 print ('The tree is closed. Please wait for it to reopen. Use ' | 1093 print ('The tree is closed. Please wait for it to reopen. Use ' |
1098 '"git cl dcommit -f" to commit on a closed tree.') | 1094 '"git cl dcommit -f" to commit on a closed tree.') |
1099 return 1 | 1095 return 1 |
1100 elif 'unknown' == status: | 1096 elif 'unknown' == status: |
1101 print ('Unable to determine tree status. Please verify manually and ' | 1097 print ('Unable to determine tree status. Please verify manually and ' |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1451 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1447 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
1452 | 1448 |
1453 # Not a known command. Default to help. | 1449 # Not a known command. Default to help. |
1454 GenUsage(parser, 'help') | 1450 GenUsage(parser, 'help') |
1455 return CMDhelp(parser, argv) | 1451 return CMDhelp(parser, argv) |
1456 | 1452 |
1457 | 1453 |
1458 if __name__ == '__main__': | 1454 if __name__ == '__main__': |
1459 fix_encoding.fix_encoding() | 1455 fix_encoding.fix_encoding() |
1460 sys.exit(main(sys.argv[1:])) | 1456 sys.exit(main(sys.argv[1:])) |
OLD | NEW |