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 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 """Set this branch's issue. If issue=0, clears the issue.""" | 503 """Set this branch's issue. If issue=0, clears the issue.""" |
504 if issue: | 504 if issue: |
505 RunGit(['config', self._IssueSetting(), str(issue)]) | 505 RunGit(['config', self._IssueSetting(), str(issue)]) |
506 if self.rietveld_server: | 506 if self.rietveld_server: |
507 RunGit(['config', self._RietveldServer(), self.rietveld_server]) | 507 RunGit(['config', self._RietveldServer(), self.rietveld_server]) |
508 else: | 508 else: |
509 RunGit(['config', '--unset', self._IssueSetting()]) | 509 RunGit(['config', '--unset', self._IssueSetting()]) |
510 self.SetPatchset(0) | 510 self.SetPatchset(0) |
511 self.has_issue = False | 511 self.has_issue = False |
512 | 512 |
513 def RunHook(self, committing, upstream_branch, tbr, may_prompt, verbose, | 513 def RunHook(self, committing, upstream_branch, may_prompt, verbose, author): |
514 author): | |
515 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" | 514 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" |
516 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() or '.' | 515 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() or '.' |
517 absroot = os.path.abspath(root) | 516 absroot = os.path.abspath(root) |
518 | 517 |
519 # We use the sha1 of HEAD as a name of this change. | 518 # We use the sha1 of HEAD as a name of this change. |
520 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() | 519 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() |
521 # Need to pass a relative path for msysgit. | 520 # Need to pass a relative path for msysgit. |
522 files = scm.GIT.CaptureStatus([root], upstream_branch) | 521 files = scm.GIT.CaptureStatus([root], upstream_branch) |
523 | 522 |
524 issue = ConvertToInteger(self.GetIssue()) | 523 issue = ConvertToInteger(self.GetIssue()) |
(...skipping 20 matching lines...) Expand all Loading... |
545 | 544 |
546 # Apply watchlists on upload. | 545 # Apply watchlists on upload. |
547 if not committing: | 546 if not committing: |
548 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | 547 watchlist = watchlists.Watchlists(change.RepositoryRoot()) |
549 files = [f.LocalPath() for f in change.AffectedFiles()] | 548 files = [f.LocalPath() for f in change.AffectedFiles()] |
550 self.SetWatchers(watchlist.GetWatchersForPaths(files)) | 549 self.SetWatchers(watchlist.GetWatchersForPaths(files)) |
551 | 550 |
552 try: | 551 try: |
553 output = presubmit_support.DoPresubmitChecks(change, committing, | 552 output = presubmit_support.DoPresubmitChecks(change, committing, |
554 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, | 553 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, |
555 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, | 554 default_presubmit=None, may_prompt=may_prompt, |
556 rietveld_obj=self.RpcServer()) | 555 rietveld_obj=self.RpcServer()) |
557 except presubmit_support.PresubmitFailure, e: | 556 except presubmit_support.PresubmitFailure, e: |
558 DieWithError( | 557 DieWithError( |
559 ('%s\nMaybe your depot_tools is out of date?\n' | 558 ('%s\nMaybe your depot_tools is out of date?\n' |
560 'If all fails, contact maruel@') % e) | 559 'If all fails, contact maruel@') % e) |
561 | 560 |
562 # TODO(dpranke): We should propagate the error out instead of calling | 561 # TODO(dpranke): We should propagate the error out instead of calling |
563 # exit(). | 562 # exit(). |
564 if not output.should_continue(): | 563 if not output.should_continue(): |
565 sys.exit(1) | 564 sys.exit(1) |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 return 1 | 889 return 1 |
891 | 890 |
892 cl = Changelist() | 891 cl = Changelist() |
893 if args: | 892 if args: |
894 base_branch = args[0] | 893 base_branch = args[0] |
895 else: | 894 else: |
896 # Default to diffing against the "upstream" branch. | 895 # Default to diffing against the "upstream" branch. |
897 base_branch = cl.GetUpstreamBranch() | 896 base_branch = cl.GetUpstreamBranch() |
898 | 897 |
899 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, | 898 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, |
900 tbr=False, may_prompt=False, verbose=options.verbose, | 899 may_prompt=False, verbose=options.verbose, |
901 author=None) | 900 author=None) |
902 return 0 | 901 return 0 |
903 | 902 |
904 | 903 |
905 @usage('[args to "git diff"]') | 904 @usage('[args to "git diff"]') |
906 def CMDupload(parser, args): | 905 def CMDupload(parser, args): |
907 """upload the current changelist to codereview""" | 906 """upload the current changelist to codereview""" |
908 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', | 907 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', |
909 help='bypass upload presubmit hook') | 908 help='bypass upload presubmit hook') |
910 parser.add_option('-f', action='store_true', dest='force', | 909 parser.add_option('-f', action='store_true', dest='force', |
(...skipping 25 matching lines...) Expand all Loading... |
936 cl = Changelist() | 935 cl = Changelist() |
937 if args: | 936 if args: |
938 base_branch = args[0] | 937 base_branch = args[0] |
939 else: | 938 else: |
940 # Default to diffing against the "upstream" branch. | 939 # Default to diffing against the "upstream" branch. |
941 base_branch = cl.GetUpstreamBranch() | 940 base_branch = cl.GetUpstreamBranch() |
942 args = [base_branch + "..."] | 941 args = [base_branch + "..."] |
943 | 942 |
944 if not options.bypass_hooks and not options.force: | 943 if not options.bypass_hooks and not options.force: |
945 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, | 944 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, |
946 tbr=False, may_prompt=True, | 945 may_prompt=True, |
947 verbose=options.verbose, | 946 verbose=options.verbose, |
948 author=None) | 947 author=None) |
949 if not options.reviewers and hook_results.reviewers: | 948 if not options.reviewers and hook_results.reviewers: |
950 options.reviewers = hook_results.reviewers | 949 options.reviewers = hook_results.reviewers |
951 | 950 |
952 | 951 |
953 # --no-ext-diff is broken in some versions of Git, so try to work around | 952 # --no-ext-diff is broken in some versions of Git, so try to work around |
954 # this by overriding the environment (but there is still a problem if the | 953 # this by overriding the environment (but there is still a problem if the |
955 # git config key "diff.external" is used). | 954 # git config key "diff.external" is used). |
956 env = os.environ.copy() | 955 env = os.environ.copy() |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', | 1050 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', |
1052 help='bypass upload presubmit hook') | 1051 help='bypass upload presubmit hook') |
1053 parser.add_option('-m', dest='message', | 1052 parser.add_option('-m', dest='message', |
1054 help="override review description") | 1053 help="override review description") |
1055 parser.add_option('-f', action='store_true', dest='force', | 1054 parser.add_option('-f', action='store_true', dest='force', |
1056 help="force yes to questions (don't prompt)") | 1055 help="force yes to questions (don't prompt)") |
1057 parser.add_option('-c', dest='contributor', | 1056 parser.add_option('-c', dest='contributor', |
1058 help="external contributor for patch (appended to " + | 1057 help="external contributor for patch (appended to " + |
1059 "description and used as author for git). Should be " + | 1058 "description and used as author for git). Should be " + |
1060 "formatted as 'First Last <email@example.com>'") | 1059 "formatted as 'First Last <email@example.com>'") |
1061 parser.add_option('--tbr', action='store_true', dest='tbr', | |
1062 help="short for 'to be reviewed', commit branch " + | |
1063 "even without uploading for review") | |
1064 (options, args) = parser.parse_args(args) | 1060 (options, args) = parser.parse_args(args) |
1065 cl = Changelist() | 1061 cl = Changelist() |
1066 | 1062 |
1067 if not args or cmd == 'push': | 1063 if not args or cmd == 'push': |
1068 # Default to merging against our best guess of the upstream branch. | 1064 # Default to merging against our best guess of the upstream branch. |
1069 args = [cl.GetUpstreamBranch()] | 1065 args = [cl.GetUpstreamBranch()] |
1070 | 1066 |
1071 base_branch = args[0] | 1067 base_branch = args[0] |
1072 | 1068 |
1073 # Make sure index is up-to-date before running diff-index. | 1069 # Make sure index is up-to-date before running diff-index. |
(...skipping 19 matching lines...) Expand all Loading... |
1093 extra_commits = RunGit(['rev-list', '^' + svn_head, base_branch]) | 1089 extra_commits = RunGit(['rev-list', '^' + svn_head, base_branch]) |
1094 if extra_commits: | 1090 if extra_commits: |
1095 print ('This branch has %d additional commits not upstreamed yet.' | 1091 print ('This branch has %d additional commits not upstreamed yet.' |
1096 % len(extra_commits.splitlines())) | 1092 % len(extra_commits.splitlines())) |
1097 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' | 1093 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' |
1098 'before attempting to %s.' % (base_branch, cmd)) | 1094 'before attempting to %s.' % (base_branch, cmd)) |
1099 return 1 | 1095 return 1 |
1100 | 1096 |
1101 if not options.bypass_hooks and not options.force: | 1097 if not options.bypass_hooks and not options.force: |
1102 cl.RunHook(committing=True, upstream_branch=base_branch, | 1098 cl.RunHook(committing=True, upstream_branch=base_branch, |
1103 tbr=options.tbr, may_prompt=True, verbose=options.verbose, | 1099 may_prompt=True, verbose=options.verbose, |
1104 author=options.contributor) | 1100 author=options.contributor) |
1105 | 1101 |
1106 if cmd == 'dcommit': | 1102 if cmd == 'dcommit': |
1107 # Check the tree status if the tree status URL is set. | 1103 # Check the tree status if the tree status URL is set. |
1108 status = GetTreeStatus() | 1104 status = GetTreeStatus() |
1109 if 'closed' == status: | 1105 if 'closed' == status: |
1110 print ('The tree is closed. Please wait for it to reopen. Use ' | 1106 print ('The tree is closed. Please wait for it to reopen. Use ' |
1111 '"git cl dcommit -f" to commit on a closed tree.') | 1107 '"git cl dcommit -f" to commit on a closed tree.') |
1112 return 1 | 1108 return 1 |
1113 elif 'unknown' == status: | 1109 elif 'unknown' == status: |
1114 print ('Unable to determine tree status. Please verify manually and ' | 1110 print ('Unable to determine tree status. Please verify manually and ' |
1115 'use "git cl dcommit -f" to commit on a closed tree.') | 1111 'use "git cl dcommit -f" to commit on a closed tree.') |
1116 | 1112 |
1117 description = options.message | 1113 description = options.message |
1118 if not options.tbr: | 1114 if not description and cl.GetIssue(): |
1119 # It is important to have these checks early. Not only for user | 1115 description = cl.GetDescription() |
1120 # convenience, but also because the cl object then caches the correct values | |
1121 # of these fields even as we're juggling branches for setting up the commit. | |
1122 if not cl.GetIssue(): | |
1123 print 'Current issue unknown -- has this branch been uploaded?' | |
1124 print 'Use --tbr to commit without review.' | |
1125 return 1 | |
1126 | 1116 |
1127 if not description: | 1117 if not description: |
1128 description = cl.GetDescription() | 1118 print 'No description set.' |
| 1119 print 'Visit %s/edit to set it.' % (cl.GetIssueURL()) |
| 1120 return 1 |
1129 | 1121 |
1130 if not description: | 1122 if cl.GetIssue(): |
1131 print 'No description set.' | |
1132 print 'Visit %s/edit to set it.' % (cl.GetIssueURL()) | |
1133 return 1 | |
1134 | |
1135 description += "\n\nReview URL: %s" % cl.GetIssueURL() | 1123 description += "\n\nReview URL: %s" % cl.GetIssueURL() |
1136 else: | |
1137 if not description: | |
1138 # Submitting TBR. See if there's already a description in Rietveld, else | |
1139 # create a template description. Eitherway, give the user a chance to edit | |
1140 # it to fill in the TBR= field. | |
1141 if cl.GetIssue(): | |
1142 description = cl.GetDescription() | |
1143 | |
1144 # TODO(dpranke): Update to use ChangeDescription object. | |
1145 if not description: | |
1146 description = """# Enter a description of the change. | |
1147 # This will be used as the change log for the commit. | |
1148 | |
1149 """ | |
1150 description += CreateDescriptionFromLog(args) | |
1151 | |
1152 description = UserEditedLog(description + '\nTBR=') | |
1153 | |
1154 if not description: | |
1155 print "Description empty; aborting." | |
1156 return 1 | |
1157 | 1124 |
1158 if options.contributor: | 1125 if options.contributor: |
1159 if not re.match('^.*\s<\S+@\S+>$', options.contributor): | 1126 if not re.match('^.*\s<\S+@\S+>$', options.contributor): |
1160 print "Please provide contibutor as 'First Last <email@example.com>'" | 1127 print "Please provide contibutor as 'First Last <email@example.com>'" |
1161 return 1 | 1128 return 1 |
1162 description += "\nPatch from %s." % options.contributor | 1129 description += "\nPatch from %s." % options.contributor |
1163 print 'Description:', repr(description) | 1130 print 'Description:', repr(description) |
1164 | 1131 |
1165 branches = [base_branch, cl.GetBranchRef()] | 1132 branches = [base_branch, cl.GetBranchRef()] |
1166 if not options.force: | 1133 if not options.force: |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1479 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1446 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
1480 | 1447 |
1481 # Not a known command. Default to help. | 1448 # Not a known command. Default to help. |
1482 GenUsage(parser, 'help') | 1449 GenUsage(parser, 'help') |
1483 return CMDhelp(parser, argv) | 1450 return CMDhelp(parser, argv) |
1484 | 1451 |
1485 | 1452 |
1486 if __name__ == '__main__': | 1453 if __name__ == '__main__': |
1487 fix_encoding.fix_encoding() | 1454 fix_encoding.fix_encoding() |
1488 sys.exit(main(sys.argv[1:])) | 1455 sys.exit(main(sys.argv[1:])) |
OLD | NEW |