| 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 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 SetProperty(settings.GetTreeStatusUrl(error_ok=True), 'Tree status URL', | 632 SetProperty(settings.GetTreeStatusUrl(error_ok=True), 'Tree status URL', |
| 633 'tree-status-url', False) | 633 'tree-status-url', False) |
| 634 SetProperty(settings.GetViewVCUrl(), 'ViewVC URL', 'viewvc-url', True) | 634 SetProperty(settings.GetViewVCUrl(), 'ViewVC URL', 'viewvc-url', True) |
| 635 | 635 |
| 636 # TODO: configure a default branch to diff against, rather than this | 636 # TODO: configure a default branch to diff against, rather than this |
| 637 # svn-based hackery. | 637 # svn-based hackery. |
| 638 | 638 |
| 639 | 639 |
| 640 class ChangeDescription(object): | 640 class ChangeDescription(object): |
| 641 """Contains a parsed form of the change description.""" | 641 """Contains a parsed form of the change description.""" |
| 642 def __init__(self, subject, log_desc, reviewers): | 642 def __init__(self, log_desc, reviewers): |
| 643 self.subject = subject | |
| 644 self.log_desc = log_desc | 643 self.log_desc = log_desc |
| 645 self.reviewers = reviewers | 644 self.reviewers = reviewers |
| 646 self.description = self.log_desc | 645 self.description = self.log_desc |
| 647 | 646 |
| 648 def Update(self): | 647 def Prompt(self): |
| 649 initial_text = """# Enter a description of the change. | 648 content = """# Enter a description of the change. |
| 650 # This will displayed on the codereview site. | 649 # This will displayed on the codereview site. |
| 651 # The first line will also be used as the subject of the review. | 650 # The first line will also be used as the subject of the review. |
| 652 """ | 651 """ |
| 653 initial_text += self.description | 652 content += self.description |
| 654 if ('\nR=' not in self.description and | 653 if ('\nR=' not in self.description and |
| 655 '\nTBR=' not in self.description and | 654 '\nTBR=' not in self.description and |
| 656 self.reviewers): | 655 self.reviewers): |
| 657 initial_text += '\nR=' + self.reviewers | 656 content += '\nR=' + self.reviewers |
| 658 if '\nBUG=' not in self.description: | 657 if '\nBUG=' not in self.description: |
| 659 initial_text += '\nBUG=' | 658 content += '\nBUG=' |
| 660 if '\nTEST=' not in self.description: | 659 if '\nTEST=' not in self.description: |
| 661 initial_text += '\nTEST=' | 660 content += '\nTEST=' |
| 662 initial_text = initial_text.rstrip('\n') + '\n' | 661 content = content.rstrip('\n') + '\n' |
| 663 content = gclient_utils.RunEditor(initial_text, True) | 662 content = gclient_utils.RunEditor(content, True) |
| 664 if not content: | 663 if not content: |
| 665 DieWithError('Running editor failed') | 664 DieWithError('Running editor failed') |
| 666 content = re.compile(r'^#.*$', re.MULTILINE).sub('', content).strip() | 665 content = re.compile(r'^#.*$', re.MULTILINE).sub('', content).strip() |
| 667 if not content: | 666 if not content: |
| 668 DieWithError('No CL description, aborting') | 667 DieWithError('No CL description, aborting') |
| 669 self._ParseDescription(content) | 668 self.description = content.strip('\n') + '\n' |
| 670 | 669 |
| 671 def _ParseDescription(self, description): | 670 def ParseDescription(self): |
| 672 """Updates the list of reviewers and subject from the description.""" | 671 """Updates the list of reviewers.""" |
| 673 if not description: | |
| 674 self.description = description | |
| 675 return | |
| 676 | |
| 677 self.description = description.strip('\n') + '\n' | |
| 678 self.subject = description.split('\n', 1)[0] | |
| 679 # Retrieves all reviewer lines | 672 # Retrieves all reviewer lines |
| 680 regexp = re.compile(r'^\s*(TBR|R)=(.+)$', re.MULTILINE) | 673 regexp = re.compile(r'^\s*(TBR|R)=(.+)$', re.MULTILINE) |
| 681 self.reviewers = ','.join( | 674 reviewers = ','.join( |
| 682 i.group(2).strip() for i in regexp.finditer(self.description)) | 675 i.group(2).strip() for i in regexp.finditer(self.description)) |
| 676 if reviewers: |
| 677 self.reviewers = reviewers |
| 683 | 678 |
| 684 def IsEmpty(self): | 679 def IsEmpty(self): |
| 685 return not self.description | 680 return not self.description |
| 686 | 681 |
| 687 | 682 |
| 688 def FindCodereviewSettingsFile(filename='codereview.settings'): | 683 def FindCodereviewSettingsFile(filename='codereview.settings'): |
| 689 """Finds the given file starting in the cwd and going up. | 684 """Finds the given file starting in the cwd and going up. |
| 690 | 685 |
| 691 Only looks up to the top of the repository unless an | 686 Only looks up to the top of the repository unless an |
| 692 'inherit-review-settings-ok' file exists in the root of the repository. | 687 'inherit-review-settings-ok' file exists in the root of the repository. |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 env = os.environ.copy() | 913 env = os.environ.copy() |
| 919 if 'GIT_EXTERNAL_DIFF' in env: | 914 if 'GIT_EXTERNAL_DIFF' in env: |
| 920 del env['GIT_EXTERNAL_DIFF'] | 915 del env['GIT_EXTERNAL_DIFF'] |
| 921 subprocess2.call( | 916 subprocess2.call( |
| 922 ['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, env=env) | 917 ['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, env=env) |
| 923 | 918 |
| 924 upload_args = ['--assume_yes'] # Don't ask about untracked files. | 919 upload_args = ['--assume_yes'] # Don't ask about untracked files. |
| 925 upload_args.extend(['--server', cl.GetRietveldServer()]) | 920 upload_args.extend(['--server', cl.GetRietveldServer()]) |
| 926 if options.emulate_svn_auto_props: | 921 if options.emulate_svn_auto_props: |
| 927 upload_args.append('--emulate_svn_auto_props') | 922 upload_args.append('--emulate_svn_auto_props') |
| 928 if options.from_logs and not options.message: | |
| 929 print 'Must set message for subject line if using desc_from_logs' | |
| 930 return 1 | |
| 931 | 923 |
| 932 change_desc = None | 924 change_desc = None |
| 933 | 925 |
| 934 if cl.GetIssue(): | 926 if cl.GetIssue(): |
| 935 if options.message: | 927 if options.message: |
| 936 upload_args.extend(['--message', options.message]) | 928 upload_args.extend(['--message', options.message]) |
| 937 upload_args.extend(['--issue', cl.GetIssue()]) | 929 upload_args.extend(['--issue', cl.GetIssue()]) |
| 938 print ("This branch is associated with issue %s. " | 930 print ("This branch is associated with issue %s. " |
| 939 "Adding patch to that issue." % cl.GetIssue()) | 931 "Adding patch to that issue." % cl.GetIssue()) |
| 940 else: | 932 else: |
| 941 log_desc = CreateDescriptionFromLog(args) | 933 message = options.message or CreateDescriptionFromLog(args) |
| 942 change_desc = ChangeDescription(options.message, log_desc, | 934 change_desc = ChangeDescription(message, options.reviewers) |
| 943 options.reviewers) | 935 if not options.force: |
| 944 if not options.from_logs: | 936 change_desc.Prompt() |
| 945 change_desc.Update() | 937 change_desc.ParseDescription() |
| 946 | 938 |
| 947 if change_desc.IsEmpty(): | 939 if change_desc.IsEmpty(): |
| 948 print "Description is empty; aborting." | 940 print "Description is empty; aborting." |
| 949 return 1 | 941 return 1 |
| 950 | 942 |
| 951 upload_args.extend(['--message', change_desc.subject]) | 943 upload_args.extend(['--message', change_desc.description]) |
| 952 upload_args.extend(['--description', change_desc.description]) | |
| 953 if change_desc.reviewers: | 944 if change_desc.reviewers: |
| 954 upload_args.extend(['--reviewers', change_desc.reviewers]) | 945 upload_args.extend(['--reviewers', change_desc.reviewers]) |
| 955 if options.send_mail: | 946 if options.send_mail: |
| 956 if not change_desc.reviewers: | 947 if not change_desc.reviewers: |
| 957 DieWithError("Must specify reviewers to send email.") | 948 DieWithError("Must specify reviewers to send email.") |
| 958 upload_args.append('--send_mail') | 949 upload_args.append('--send_mail') |
| 959 cc = ','.join(filter(None, (cl.GetCCList(), options.cc))) | 950 cc = ','.join(filter(None, (cl.GetCCList(), options.cc))) |
| 960 if cc: | 951 if cc: |
| 961 upload_args.extend(['--cc', cc]) | 952 upload_args.extend(['--cc', cc]) |
| 962 | 953 |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1428 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1419 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 1429 | 1420 |
| 1430 # Not a known command. Default to help. | 1421 # Not a known command. Default to help. |
| 1431 GenUsage(parser, 'help') | 1422 GenUsage(parser, 'help') |
| 1432 return CMDhelp(parser, argv) | 1423 return CMDhelp(parser, argv) |
| 1433 | 1424 |
| 1434 | 1425 |
| 1435 if __name__ == '__main__': | 1426 if __name__ == '__main__': |
| 1436 fix_encoding.fix_encoding() | 1427 fix_encoding.fix_encoding() |
| 1437 sys.exit(main(sys.argv[1:])) | 1428 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |