OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 logging | 10 import logging |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 SetProperty(settings.GetTreeStatusUrl(error_ok=True), 'Tree status URL', | 615 SetProperty(settings.GetTreeStatusUrl(error_ok=True), 'Tree status URL', |
616 'tree-status-url', False) | 616 'tree-status-url', False) |
617 SetProperty(settings.GetViewVCUrl(), 'ViewVC URL', 'viewvc-url', True) | 617 SetProperty(settings.GetViewVCUrl(), 'ViewVC URL', 'viewvc-url', True) |
618 | 618 |
619 # TODO: configure a default branch to diff against, rather than this | 619 # TODO: configure a default branch to diff against, rather than this |
620 # svn-based hackery. | 620 # svn-based hackery. |
621 | 621 |
622 | 622 |
623 class ChangeDescription(object): | 623 class ChangeDescription(object): |
624 """Contains a parsed form of the change description.""" | 624 """Contains a parsed form of the change description.""" |
625 def __init__(self, subject, log_desc, reviewers): | 625 def __init__(self, log_desc, reviewers): |
626 self.subject = subject | |
627 self.log_desc = log_desc | 626 self.log_desc = log_desc |
628 self.reviewers = reviewers | 627 self.reviewers = reviewers |
629 self.description = self.log_desc | 628 self.description = self.log_desc |
630 | 629 |
631 def Update(self): | 630 def Prompt(self): |
632 initial_text = """# Enter a description of the change. | 631 content = """# Enter a description of the change. |
633 # This will displayed on the codereview site. | 632 # This will displayed on the codereview site. |
634 # The first line will also be used as the subject of the review. | 633 # The first line will also be used as the subject of the review. |
635 """ | 634 """ |
636 initial_text += self.description | 635 content += self.description |
637 if ('\nR=' not in self.description and | 636 if ('\nR=' not in self.description and |
638 '\nTBR=' not in self.description and | 637 '\nTBR=' not in self.description and |
639 self.reviewers): | 638 self.reviewers): |
640 initial_text += '\nR=' + self.reviewers | 639 content += '\nR=' + self.reviewers |
641 if '\nBUG=' not in self.description: | 640 if '\nBUG=' not in self.description: |
642 initial_text += '\nBUG=' | 641 content += '\nBUG=' |
643 if '\nTEST=' not in self.description: | 642 if '\nTEST=' not in self.description: |
644 initial_text += '\nTEST=' | 643 content += '\nTEST=' |
645 initial_text = initial_text.rstrip('\n') + '\n' | 644 content = content.rstrip('\n') + '\n' |
646 content = gclient_utils.RunEditor(initial_text, True) | 645 content = gclient_utils.RunEditor(content, True) |
647 if not content: | 646 if not content: |
648 DieWithError('Running editor failed') | 647 DieWithError('Running editor failed') |
649 content = re.compile(r'^#.*$', re.MULTILINE).sub('', content).strip() | 648 content = re.compile(r'^#.*$', re.MULTILINE).sub('', content).strip() |
650 if not content: | 649 if not content.strip(): |
651 DieWithError('No CL description, aborting') | 650 DieWithError('No CL description, aborting') |
652 self.ParseDescription(content) | 651 self.description = content |
653 | 652 |
654 def ParseDescription(self, description): | 653 def ParseDescription(self): |
655 """Updates the list of reviewers and subject from the description.""" | 654 """Updates the list of reviewers and subject from the description.""" |
656 if not description: | 655 self.description = self.description.strip('\n') + '\n' |
657 self.description = description | |
658 return | |
659 | |
660 self.description = description.strip('\n') + '\n' | |
661 self.subject = description.split('\n', 1)[0] | |
662 # Retrieves all reviewer lines | 656 # Retrieves all reviewer lines |
663 regexp = re.compile(r'^\s*(TBR|R)=(.+)$', re.MULTILINE) | 657 regexp = re.compile(r'^\s*(TBR|R)=(.+)$', re.MULTILINE) |
664 self.reviewers = ','.join( | 658 reviewers = ','.join( |
665 i.group(2).strip() for i in regexp.finditer(self.description)) | 659 i.group(2).strip() for i in regexp.finditer(self.description)) |
| 660 if reviewers: |
| 661 self.reviewers = reviewers |
666 | 662 |
667 def IsEmpty(self): | 663 def IsEmpty(self): |
668 return not self.description | 664 return not self.description |
669 | 665 |
670 | 666 |
671 def FindCodereviewSettingsFile(filename='codereview.settings'): | 667 def FindCodereviewSettingsFile(filename='codereview.settings'): |
672 """Finds the given file starting in the cwd and going up. | 668 """Finds the given file starting in the cwd and going up. |
673 | 669 |
674 Only looks up to the top of the repository unless an | 670 Only looks up to the top of the repository unless an |
675 'inherit-review-settings-ok' file exists in the root of the repository. | 671 'inherit-review-settings-ok' file exists in the root of the repository. |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 | 853 |
858 def GerritUpload(options, args, cl): | 854 def GerritUpload(options, args, cl): |
859 """upload the current branch to gerrit.""" | 855 """upload the current branch to gerrit.""" |
860 # We assume the remote called "origin" is the one we want. | 856 # We assume the remote called "origin" is the one we want. |
861 # It is probably not worthwhile to support different workflows. | 857 # It is probably not worthwhile to support different workflows. |
862 remote = 'origin' | 858 remote = 'origin' |
863 branch = 'master' | 859 branch = 'master' |
864 if options.target_branch: | 860 if options.target_branch: |
865 branch = options.target_branch | 861 branch = options.target_branch |
866 | 862 |
867 log_desc = CreateDescriptionFromLog(args) | 863 log_desc = options.message or CreateDescriptionFromLog(args) |
868 if options.reviewers: | 864 if options.reviewers: |
869 log_desc += '\nR=' + options.reviewers | 865 log_desc += '\nR=' + options.reviewers |
870 change_desc = ChangeDescription(options.message, log_desc, | 866 change_desc = ChangeDescription(log_desc, options.reviewers) |
871 options.reviewers) | 867 change_desc.ParseDescription() |
872 change_desc.ParseDescription(log_desc) | |
873 if change_desc.IsEmpty(): | 868 if change_desc.IsEmpty(): |
874 print "Description is empty; aborting." | 869 print "Description is empty; aborting." |
875 return 1 | 870 return 1 |
876 | 871 |
877 receive_options = [] | 872 receive_options = [] |
878 cc = cl.GetCCList().split(',') | 873 cc = cl.GetCCList().split(',') |
879 if options.cc: | 874 if options.cc: |
880 cc += options.cc.split(',') | 875 cc += options.cc.split(',') |
881 cc = filter(None, cc) | 876 cc = filter(None, cc) |
882 if cc: | 877 if cc: |
(...skipping 12 matching lines...) Expand all Loading... |
895 # TODO(ukai): parse Change-Id: and set issue number? | 890 # TODO(ukai): parse Change-Id: and set issue number? |
896 return 0 | 891 return 0 |
897 | 892 |
898 | 893 |
899 def RietveldUpload(options, args, cl): | 894 def RietveldUpload(options, args, cl): |
900 """upload the patch to rietveld.""" | 895 """upload the patch to rietveld.""" |
901 upload_args = ['--assume_yes'] # Don't ask about untracked files. | 896 upload_args = ['--assume_yes'] # Don't ask about untracked files. |
902 upload_args.extend(['--server', cl.GetRietveldServer()]) | 897 upload_args.extend(['--server', cl.GetRietveldServer()]) |
903 if options.emulate_svn_auto_props: | 898 if options.emulate_svn_auto_props: |
904 upload_args.append('--emulate_svn_auto_props') | 899 upload_args.append('--emulate_svn_auto_props') |
905 if options.from_logs and not options.message: | |
906 print 'Must set message for subject line if using desc_from_logs' | |
907 return 1 | |
908 | 900 |
909 change_desc = None | 901 change_desc = None |
910 | 902 |
911 if cl.GetIssue(): | 903 if cl.GetIssue(): |
912 if options.message: | 904 if options.message: |
913 upload_args.extend(['--message', options.message]) | 905 upload_args.extend(['--message', options.message]) |
914 upload_args.extend(['--issue', cl.GetIssue()]) | 906 upload_args.extend(['--issue', cl.GetIssue()]) |
915 print ("This branch is associated with issue %s. " | 907 print ("This branch is associated with issue %s. " |
916 "Adding patch to that issue." % cl.GetIssue()) | 908 "Adding patch to that issue." % cl.GetIssue()) |
917 else: | 909 else: |
918 log_desc = CreateDescriptionFromLog(args) | 910 message = options.message or CreateDescriptionFromLog(args) |
919 change_desc = ChangeDescription(options.message, log_desc, | 911 change_desc = ChangeDescription(message, options.reviewers) |
920 options.reviewers) | 912 if not options.force: |
921 if not options.from_logs: | 913 change_desc.Prompt() |
922 change_desc.Update() | 914 change_desc.ParseDescription() |
923 | 915 |
924 if change_desc.IsEmpty(): | 916 if change_desc.IsEmpty(): |
925 print "Description is empty; aborting." | 917 print "Description is empty; aborting." |
926 return 1 | 918 return 1 |
927 | 919 |
928 upload_args.extend(['--message', change_desc.subject]) | 920 upload_args.extend(['--message', change_desc.description]) |
929 upload_args.extend(['--description', change_desc.description]) | |
930 if change_desc.reviewers: | 921 if change_desc.reviewers: |
931 upload_args.extend(['--reviewers', change_desc.reviewers]) | 922 upload_args.extend(['--reviewers', change_desc.reviewers]) |
932 if options.send_mail: | 923 if options.send_mail: |
933 if not change_desc.reviewers: | 924 if not change_desc.reviewers: |
934 DieWithError("Must specify reviewers to send email.") | 925 DieWithError("Must specify reviewers to send email.") |
935 upload_args.append('--send_mail') | 926 upload_args.append('--send_mail') |
936 cc = ','.join(filter(None, (cl.GetCCList(), options.cc))) | 927 cc = ','.join(filter(None, (cl.GetCCList(), options.cc))) |
937 if cc: | 928 if cc: |
938 upload_args.extend(['--cc', cc]) | 929 upload_args.extend(['--cc', cc]) |
939 | 930 |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1464 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
1474 | 1465 |
1475 # Not a known command. Default to help. | 1466 # Not a known command. Default to help. |
1476 GenUsage(parser, 'help') | 1467 GenUsage(parser, 'help') |
1477 return CMDhelp(parser, argv) | 1468 return CMDhelp(parser, argv) |
1478 | 1469 |
1479 | 1470 |
1480 if __name__ == '__main__': | 1471 if __name__ == '__main__': |
1481 fix_encoding.fix_encoding() | 1472 fix_encoding.fix_encoding() |
1482 sys.exit(main(sys.argv[1:])) | 1473 sys.exit(main(sys.argv[1:])) |
OLD | NEW |