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 distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
(...skipping 2489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2500 gerrit_util.SetReview(self._GetGerritHost(), self.GetIssue(), | 2500 gerrit_util.SetReview(self._GetGerritHost(), self.GetIssue(), |
2501 labels={'Commit-Queue': vote_map[new_state]}) | 2501 labels={'Commit-Queue': vote_map[new_state]}) |
2502 | 2502 |
2503 | 2503 |
2504 _CODEREVIEW_IMPLEMENTATIONS = { | 2504 _CODEREVIEW_IMPLEMENTATIONS = { |
2505 'rietveld': _RietveldChangelistImpl, | 2505 'rietveld': _RietveldChangelistImpl, |
2506 'gerrit': _GerritChangelistImpl, | 2506 'gerrit': _GerritChangelistImpl, |
2507 } | 2507 } |
2508 | 2508 |
2509 | 2509 |
| 2510 def _add_codereview_select_options(parser): |
| 2511 """Appends --gerrit and --rietveld options to force specific codereview.""" |
| 2512 parser.codereview_group = optparse.OptionGroup( |
| 2513 parser, 'EXPERIMENTAL! Codereview override options') |
| 2514 parser.add_option_group(parser.codereview_group) |
| 2515 parser.codereview_group.add_option( |
| 2516 '--gerrit', action='store_true', |
| 2517 help='Force the use of Gerrit for codereview') |
| 2518 parser.codereview_group.add_option( |
| 2519 '--rietveld', action='store_true', |
| 2520 help='Force the use of Rietveld for codereview') |
| 2521 |
| 2522 |
| 2523 def _process_codereview_select_options(parser, options): |
| 2524 if options.gerrit and options.rietveld: |
| 2525 parser.error('Options --gerrit and --rietveld are mutually exclusive') |
| 2526 options.forced_codereview = None |
| 2527 if options.gerrit: |
| 2528 options.forced_codereview = 'gerrit' |
| 2529 elif options.rietveld: |
| 2530 options.forced_codereview = 'rietveld' |
| 2531 |
| 2532 |
2510 class ChangeDescription(object): | 2533 class ChangeDescription(object): |
2511 """Contains a parsed form of the change description.""" | 2534 """Contains a parsed form of the change description.""" |
2512 R_LINE = r'^[ \t]*(TBR|R)[ \t]*=[ \t]*(.*?)[ \t]*$' | 2535 R_LINE = r'^[ \t]*(TBR|R)[ \t]*=[ \t]*(.*?)[ \t]*$' |
2513 BUG_LINE = r'^[ \t]*(BUG)[ \t]*=[ \t]*(.*?)[ \t]*$' | 2536 BUG_LINE = r'^[ \t]*(BUG)[ \t]*=[ \t]*(.*?)[ \t]*$' |
2514 | 2537 |
2515 def __init__(self, description): | 2538 def __init__(self, description): |
2516 self._description_lines = (description or '').strip().splitlines() | 2539 self._description_lines = (description or '').strip().splitlines() |
2517 | 2540 |
2518 @property # www.logilab.org/ticket/89786 | 2541 @property # www.logilab.org/ticket/89786 |
2519 def description(self): # pylint: disable=E0202 | 2542 def description(self): # pylint: disable=E0202 |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3115 @subcommand.usage('[issue_number]') | 3138 @subcommand.usage('[issue_number]') |
3116 def CMDissue(parser, args): | 3139 def CMDissue(parser, args): |
3117 """Sets or displays the current code review issue number. | 3140 """Sets or displays the current code review issue number. |
3118 | 3141 |
3119 Pass issue number 0 to clear the current issue. | 3142 Pass issue number 0 to clear the current issue. |
3120 """ | 3143 """ |
3121 parser.add_option('-r', '--reverse', action='store_true', | 3144 parser.add_option('-r', '--reverse', action='store_true', |
3122 help='Lookup the branch(es) for the specified issues. If ' | 3145 help='Lookup the branch(es) for the specified issues. If ' |
3123 'no issues are specified, all branches with mapped ' | 3146 'no issues are specified, all branches with mapped ' |
3124 'issues will be listed.') | 3147 'issues will be listed.') |
| 3148 _add_codereview_select_options(parser) |
3125 options, args = parser.parse_args(args) | 3149 options, args = parser.parse_args(args) |
| 3150 _process_codereview_select_options(parser, options) |
3126 | 3151 |
3127 if options.reverse: | 3152 if options.reverse: |
3128 branches = RunGit(['for-each-ref', 'refs/heads', | 3153 branches = RunGit(['for-each-ref', 'refs/heads', |
3129 '--format=%(refname:short)']).splitlines() | 3154 '--format=%(refname:short)']).splitlines() |
3130 | 3155 |
3131 # Reverse issue lookup. | 3156 # Reverse issue lookup. |
3132 issue_branch_map = {} | 3157 issue_branch_map = {} |
3133 for branch in branches: | 3158 for branch in branches: |
3134 cl = Changelist(branchref=branch) | 3159 cl = Changelist(branchref=branch) |
3135 issue_branch_map.setdefault(cl.GetIssue(), []).append(branch) | 3160 issue_branch_map.setdefault(cl.GetIssue(), []).append(branch) |
3136 if not args: | 3161 if not args: |
3137 args = sorted(issue_branch_map.iterkeys()) | 3162 args = sorted(issue_branch_map.iterkeys()) |
3138 for issue in args: | 3163 for issue in args: |
3139 if not issue: | 3164 if not issue: |
3140 continue | 3165 continue |
3141 print 'Branch for issue number %s: %s' % ( | 3166 print 'Branch for issue number %s: %s' % ( |
3142 issue, ', '.join(issue_branch_map.get(int(issue)) or ('None',))) | 3167 issue, ', '.join(issue_branch_map.get(int(issue)) or ('None',))) |
3143 else: | 3168 else: |
3144 cl = Changelist() | 3169 cl = Changelist(codereview=options.forced_codereview) |
3145 if len(args) > 0: | 3170 if len(args) > 0: |
3146 try: | 3171 try: |
3147 issue = int(args[0]) | 3172 issue = int(args[0]) |
3148 except ValueError: | 3173 except ValueError: |
3149 DieWithError('Pass a number to set the issue or none to list it.\n' | 3174 DieWithError('Pass a number to set the issue or none to list it.\n' |
3150 'Maybe you want to run git cl status?') | 3175 'Maybe you want to run git cl status?') |
3151 cl.SetIssue(issue) | 3176 cl.SetIssue(issue) |
3152 print 'Issue number: %s (%s)' % (cl.GetIssue(), cl.GetIssueURL()) | 3177 print 'Issue number: %s (%s)' % (cl.GetIssue(), cl.GetIssueURL()) |
3153 return 0 | 3178 return 0 |
3154 | 3179 |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3478 action='store_true', | 3503 action='store_true', |
3479 help='Send the patchset to do a CQ dry run right after ' | 3504 help='Send the patchset to do a CQ dry run right after ' |
3480 'upload.') | 3505 'upload.') |
3481 parser.add_option('--dependencies', action='store_true', | 3506 parser.add_option('--dependencies', action='store_true', |
3482 help='Uploads CLs of all the local branches that depend on ' | 3507 help='Uploads CLs of all the local branches that depend on ' |
3483 'the current branch') | 3508 'the current branch') |
3484 | 3509 |
3485 orig_args = args | 3510 orig_args = args |
3486 add_git_similarity(parser) | 3511 add_git_similarity(parser) |
3487 auth.add_auth_options(parser) | 3512 auth.add_auth_options(parser) |
| 3513 _add_codereview_select_options(parser) |
3488 (options, args) = parser.parse_args(args) | 3514 (options, args) = parser.parse_args(args) |
| 3515 _process_codereview_select_options(parser, options) |
3489 auth_config = auth.extract_auth_config_from_options(options) | 3516 auth_config = auth.extract_auth_config_from_options(options) |
3490 | 3517 |
3491 if git_common.is_dirty_git_tree('upload'): | 3518 if git_common.is_dirty_git_tree('upload'): |
3492 return 1 | 3519 return 1 |
3493 | 3520 |
3494 options.reviewers = cleanup_list(options.reviewers) | 3521 options.reviewers = cleanup_list(options.reviewers) |
3495 options.cc = cleanup_list(options.cc) | 3522 options.cc = cleanup_list(options.cc) |
3496 | 3523 |
3497 # For sanity of test expectations, do this otherwise lazy-loading *now*. | 3524 # For sanity of test expectations, do this otherwise lazy-loading *now*. |
3498 settings.GetIsGerrit() | 3525 settings.GetIsGerrit() |
3499 | 3526 |
3500 cl = Changelist(auth_config=auth_config) | 3527 cl = Changelist(auth_config=auth_config, codereview=options.forced_codereview) |
3501 return cl.CMDUpload(options, args, orig_args) | 3528 return cl.CMDUpload(options, args, orig_args) |
3502 | 3529 |
3503 | 3530 |
3504 def IsSubmoduleMergeCommit(ref): | 3531 def IsSubmoduleMergeCommit(ref): |
3505 # When submodules are added to the repo, we expect there to be a single | 3532 # When submodules are added to the repo, we expect there to be a single |
3506 # non-git-svn merge commit at remote HEAD with a signature comment. | 3533 # non-git-svn merge commit at remote HEAD with a signature comment. |
3507 pattern = '^SVN changes up to revision [0-9]*$' | 3534 pattern = '^SVN changes up to revision [0-9]*$' |
3508 cmd = ['rev-list', '--merges', '--grep=%s' % pattern, '%s^!' % ref] | 3535 cmd = ['rev-list', '--merges', '--grep=%s' % pattern, '%s^!' % ref] |
3509 return RunGit(cmd) != '' | 3536 return RunGit(cmd) != '' |
3510 | 3537 |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3974 group.add_option('--reapply', action='store_true', dest='reapply', | 4001 group.add_option('--reapply', action='store_true', dest='reapply', |
3975 help='Reset the branch and reapply the issue.\n' | 4002 help='Reset the branch and reapply the issue.\n' |
3976 'CAUTION: This will undo any local changes in this ' | 4003 'CAUTION: This will undo any local changes in this ' |
3977 'branch') | 4004 'branch') |
3978 | 4005 |
3979 group.add_option('--pull', action='store_true', dest='pull', | 4006 group.add_option('--pull', action='store_true', dest='pull', |
3980 help='Performs a pull before reapplying.') | 4007 help='Performs a pull before reapplying.') |
3981 parser.add_option_group(group) | 4008 parser.add_option_group(group) |
3982 | 4009 |
3983 auth.add_auth_options(parser) | 4010 auth.add_auth_options(parser) |
| 4011 _add_codereview_select_options(parser) |
3984 (options, args) = parser.parse_args(args) | 4012 (options, args) = parser.parse_args(args) |
| 4013 _process_codereview_select_options(parser, options) |
3985 auth_config = auth.extract_auth_config_from_options(options) | 4014 auth_config = auth.extract_auth_config_from_options(options) |
3986 | 4015 |
3987 cl = Changelist(auth_config=auth_config) | 4016 cl = Changelist(auth_config=auth_config, codereview=options.forced_codereview) |
3988 | 4017 |
3989 issue_arg = None | 4018 issue_arg = None |
3990 if options.reapply : | 4019 if options.reapply : |
3991 if len(args) > 0: | 4020 if len(args) > 0: |
3992 parser.error('--reapply implies no additional arguments.') | 4021 parser.error('--reapply implies no additional arguments.') |
3993 | 4022 |
3994 issue_arg = cl.GetIssue() | 4023 issue_arg = cl.GetIssue() |
3995 upstream = cl.GetUpstreamBranch() | 4024 upstream = cl.GetUpstreamBranch() |
3996 if upstream == None: | 4025 if upstream == None: |
3997 parser.error('No upstream branch specified. Cannot reset branch') | 4026 parser.error('No upstream branch specified. Cannot reset branch') |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4778 if __name__ == '__main__': | 4807 if __name__ == '__main__': |
4779 # These affect sys.stdout so do it outside of main() to simplify mocks in | 4808 # These affect sys.stdout so do it outside of main() to simplify mocks in |
4780 # unit testing. | 4809 # unit testing. |
4781 fix_encoding.fix_encoding() | 4810 fix_encoding.fix_encoding() |
4782 setup_color.init() | 4811 setup_color.init() |
4783 try: | 4812 try: |
4784 sys.exit(main(sys.argv[1:])) | 4813 sys.exit(main(sys.argv[1:])) |
4785 except KeyboardInterrupt: | 4814 except KeyboardInterrupt: |
4786 sys.stderr.write('interrupted\n') | 4815 sys.stderr.write('interrupted\n') |
4787 sys.exit(1) | 4816 sys.exit(1) |
OLD | NEW |