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 and Gerrit.""" | 8 """A git-command for integrating reviews on Rietveld and Gerrit.""" |
9 | 9 |
10 from __future__ import print_function | 10 from __future__ import print_function |
(...skipping 2498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2509 'single commit.') | 2509 'single commit.') |
2510 ask_for_data('About to upload; enter to confirm.') | 2510 ask_for_data('About to upload; enter to confirm.') |
2511 | 2511 |
2512 if options.reviewers or options.tbr_owners: | 2512 if options.reviewers or options.tbr_owners: |
2513 change_desc.update_reviewers(options.reviewers, options.tbr_owners, | 2513 change_desc.update_reviewers(options.reviewers, options.tbr_owners, |
2514 change) | 2514 change) |
2515 | 2515 |
2516 # Extra options that can be specified at push time. Doc: | 2516 # Extra options that can be specified at push time. Doc: |
2517 # https://gerrit-review.googlesource.com/Documentation/user-upload.html | 2517 # https://gerrit-review.googlesource.com/Documentation/user-upload.html |
2518 refspec_opts = [] | 2518 refspec_opts = [] |
| 2519 if change_desc.get_reviewers(tbr_only=True): |
| 2520 print('Adding self-LGTM (Code-Review +1) because of TBRs') |
| 2521 refspec_opts.append('l=Code-Review+1') |
| 2522 |
2519 if options.title: | 2523 if options.title: |
2520 if not re.match(r'^[\w ]+$', options.title): | 2524 if not re.match(r'^[\w ]+$', options.title): |
2521 options.title = re.sub(r'[^\w ]', '', options.title) | 2525 options.title = re.sub(r'[^\w ]', '', options.title) |
2522 print('WARNING: Patchset title may only contain alphanumeric chars ' | 2526 print('WARNING: Patchset title may only contain alphanumeric chars ' |
2523 'and spaces. Cleaned up title:\n%s' % options.title) | 2527 'and spaces. Cleaned up title:\n%s' % options.title) |
2524 if not options.force: | 2528 if not options.force: |
2525 ask_for_data('Press enter to continue, Ctrl+C to abort') | 2529 ask_for_data('Press enter to continue, Ctrl+C to abort') |
2526 # Per doc, spaces must be converted to underscores, and Gerrit will do the | 2530 # Per doc, spaces must be converted to underscores, and Gerrit will do the |
2527 # reverse on its side. | 2531 # reverse on its side. |
2528 refspec_opts.append('m=' + options.title.replace(' ', '_')) | 2532 refspec_opts.append('m=' + options.title.replace(' ', '_')) |
2529 | 2533 |
2530 if options.send_mail: | 2534 if options.send_mail: |
2531 if not change_desc.get_reviewers(): | 2535 if not change_desc.get_reviewers(): |
2532 DieWithError('Must specify reviewers to send email.') | 2536 DieWithError('Must specify reviewers to send email.') |
2533 refspec_opts.append('notify=ALL') | 2537 refspec_opts.append('notify=ALL') |
2534 else: | 2538 else: |
2535 refspec_opts.append('notify=NONE') | 2539 refspec_opts.append('notify=NONE') |
2536 | 2540 |
2537 cc = self.GetCCList().split(',') | 2541 cc = self.GetCCList().split(',') |
2538 if options.cc: | 2542 if options.cc: |
2539 cc.extend(options.cc) | 2543 cc.extend(options.cc) |
2540 cc = filter(None, cc) | 2544 cc = filter(None, cc) |
2541 if cc: | 2545 if cc: |
2542 refspec_opts.extend('cc=' + email.strip() for email in cc) | 2546 refspec_opts.extend('cc=' + email.strip() for email in cc) |
2543 | 2547 |
2544 if change_desc.get_reviewers(): | 2548 reviewers = change_desc.get_reviewers() |
2545 refspec_opts.extend('r=' + email.strip() | 2549 if reviewers: |
2546 for email in change_desc.get_reviewers()) | 2550 refspec_opts.extend('r=' + email.strip() for email in reviewers) |
2547 | 2551 |
2548 refspec_suffix = '' | 2552 refspec_suffix = '' |
2549 if refspec_opts: | 2553 if refspec_opts: |
2550 refspec_suffix = '%' + ','.join(refspec_opts) | 2554 refspec_suffix = '%' + ','.join(refspec_opts) |
2551 assert ' ' not in refspec_suffix, ( | 2555 assert ' ' not in refspec_suffix, ( |
2552 'spaces not allowed in refspec: "%s"' % refspec_suffix) | 2556 'spaces not allowed in refspec: "%s"' % refspec_suffix) |
2553 refspec = '%s:refs/for/%s%s' % (ref_to_push, branch, refspec_suffix) | 2557 refspec = '%s:refs/for/%s%s' % (ref_to_push, branch, refspec_suffix) |
2554 | 2558 |
2555 push_stdout = gclient_utils.CheckCallAndFilter( | 2559 push_stdout = gclient_utils.CheckCallAndFilter( |
2556 ['git', 'push', gerrit_remote, refspec], | 2560 ['git', 'push', gerrit_remote, refspec], |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2797 else: | 2801 else: |
2798 separator = [] # No need for separator if there are no gerrit_footers. | 2802 separator = [] # No need for separator if there are no gerrit_footers. |
2799 | 2803 |
2800 prev_line = top_lines[-1] if top_lines else '' | 2804 prev_line = top_lines[-1] if top_lines else '' |
2801 if (not presubmit_support.Change.TAG_LINE_RE.match(prev_line) or | 2805 if (not presubmit_support.Change.TAG_LINE_RE.match(prev_line) or |
2802 not presubmit_support.Change.TAG_LINE_RE.match(line)): | 2806 not presubmit_support.Change.TAG_LINE_RE.match(line)): |
2803 top_lines.append('') | 2807 top_lines.append('') |
2804 top_lines.append(line) | 2808 top_lines.append(line) |
2805 self._description_lines = top_lines + separator + gerrit_footers | 2809 self._description_lines = top_lines + separator + gerrit_footers |
2806 | 2810 |
2807 def get_reviewers(self): | 2811 def get_reviewers(self, tbr_only=False): |
2808 """Retrieves the list of reviewers.""" | 2812 """Retrieves the list of reviewers.""" |
2809 matches = [re.match(self.R_LINE, line) for line in self._description_lines] | 2813 matches = [re.match(self.R_LINE, line) for line in self._description_lines] |
2810 reviewers = [match.group(2).strip() for match in matches if match] | 2814 reviewers = [match.group(2).strip() |
| 2815 for match in matches |
| 2816 if match and (not tbr_only or match.group(1).upper() == 'TBR')] |
2811 return cleanup_list(reviewers) | 2817 return cleanup_list(reviewers) |
2812 | 2818 |
2813 | 2819 |
2814 def get_approving_reviewers(props): | 2820 def get_approving_reviewers(props): |
2815 """Retrieves the reviewers that approved a CL from the issue properties with | 2821 """Retrieves the reviewers that approved a CL from the issue properties with |
2816 messages. | 2822 messages. |
2817 | 2823 |
2818 Note that the list may contain reviewers that are not committer, thus are not | 2824 Note that the list may contain reviewers that are not committer, thus are not |
2819 considered by the CQ. | 2825 considered by the CQ. |
2820 """ | 2826 """ |
(...skipping 2294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5115 if __name__ == '__main__': | 5121 if __name__ == '__main__': |
5116 # These affect sys.stdout so do it outside of main() to simplify mocks in | 5122 # These affect sys.stdout so do it outside of main() to simplify mocks in |
5117 # unit testing. | 5123 # unit testing. |
5118 fix_encoding.fix_encoding() | 5124 fix_encoding.fix_encoding() |
5119 setup_color.init() | 5125 setup_color.init() |
5120 try: | 5126 try: |
5121 sys.exit(main(sys.argv[1:])) | 5127 sys.exit(main(sys.argv[1:])) |
5122 except KeyboardInterrupt: | 5128 except KeyboardInterrupt: |
5123 sys.stderr.write('interrupted\n') | 5129 sys.stderr.write('interrupted\n') |
5124 sys.exit(1) | 5130 sys.exit(1) |
OLD | NEW |