| 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 1375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1386 return presubmit_support.GitChange( | 1386 return presubmit_support.GitChange( |
| 1387 name, | 1387 name, |
| 1388 description, | 1388 description, |
| 1389 absroot, | 1389 absroot, |
| 1390 files, | 1390 files, |
| 1391 issue, | 1391 issue, |
| 1392 patchset, | 1392 patchset, |
| 1393 author, | 1393 author, |
| 1394 upstream=upstream_branch) | 1394 upstream=upstream_branch) |
| 1395 | 1395 |
| 1396 def UpdateDescription(self, description): | 1396 def UpdateDescription(self, description, force=False): |
| 1397 self.description = description | 1397 self.description = description |
| 1398 return self._codereview_impl.UpdateDescriptionRemote(description) | 1398 return self._codereview_impl.UpdateDescriptionRemote( |
| 1399 description, force=force) |
| 1399 | 1400 |
| 1400 def RunHook(self, committing, may_prompt, verbose, change): | 1401 def RunHook(self, committing, may_prompt, verbose, change): |
| 1401 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" | 1402 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" |
| 1402 try: | 1403 try: |
| 1403 return presubmit_support.DoPresubmitChecks(change, committing, | 1404 return presubmit_support.DoPresubmitChecks(change, committing, |
| 1404 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, | 1405 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, |
| 1405 default_presubmit=None, may_prompt=may_prompt, | 1406 default_presubmit=None, may_prompt=may_prompt, |
| 1406 rietveld_obj=self._codereview_impl.GetRieveldObjForPresubmit(), | 1407 rietveld_obj=self._codereview_impl.GetRieveldObjForPresubmit(), |
| 1407 gerrit_obj=self._codereview_impl.GetGerritObjForPresubmit()) | 1408 gerrit_obj=self._codereview_impl.GetGerritObjForPresubmit()) |
| 1408 except presubmit_support.PresubmitFailure as e: | 1409 except presubmit_support.PresubmitFailure as e: |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1596 | 1597 |
| 1597 def GetRieveldObjForPresubmit(self): | 1598 def GetRieveldObjForPresubmit(self): |
| 1598 # This is an unfortunate Rietveld-embeddedness in presubmit. | 1599 # This is an unfortunate Rietveld-embeddedness in presubmit. |
| 1599 # For non-Rietveld codereviews, this probably should return a dummy object. | 1600 # For non-Rietveld codereviews, this probably should return a dummy object. |
| 1600 raise NotImplementedError() | 1601 raise NotImplementedError() |
| 1601 | 1602 |
| 1602 def GetGerritObjForPresubmit(self): | 1603 def GetGerritObjForPresubmit(self): |
| 1603 # None is valid return value, otherwise presubmit_support.GerritAccessor. | 1604 # None is valid return value, otherwise presubmit_support.GerritAccessor. |
| 1604 return None | 1605 return None |
| 1605 | 1606 |
| 1606 def UpdateDescriptionRemote(self, description): | 1607 def UpdateDescriptionRemote(self, description, force=False): |
| 1607 """Update the description on codereview site.""" | 1608 """Update the description on codereview site.""" |
| 1608 raise NotImplementedError() | 1609 raise NotImplementedError() |
| 1609 | 1610 |
| 1610 def CloseIssue(self): | 1611 def CloseIssue(self): |
| 1611 """Closes the issue.""" | 1612 """Closes the issue.""" |
| 1612 raise NotImplementedError() | 1613 raise NotImplementedError() |
| 1613 | 1614 |
| 1614 def GetApprovingReviewers(self): | 1615 def GetApprovingReviewers(self): |
| 1615 """Returns a list of reviewers approving the change. | 1616 """Returns a list of reviewers approving the change. |
| 1616 | 1617 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1791 break | 1792 break |
| 1792 | 1793 |
| 1793 if not messages: | 1794 if not messages: |
| 1794 # No message was sent. | 1795 # No message was sent. |
| 1795 return 'unsent' | 1796 return 'unsent' |
| 1796 if messages[-1]['sender'] != props.get('owner_email'): | 1797 if messages[-1]['sender'] != props.get('owner_email'): |
| 1797 # Non-LGTM reply from non-owner and not CQ bot. | 1798 # Non-LGTM reply from non-owner and not CQ bot. |
| 1798 return 'reply' | 1799 return 'reply' |
| 1799 return 'waiting' | 1800 return 'waiting' |
| 1800 | 1801 |
| 1801 def UpdateDescriptionRemote(self, description): | 1802 def UpdateDescriptionRemote(self, description, force=False): |
| 1802 return self.RpcServer().update_description( | 1803 return self.RpcServer().update_description( |
| 1803 self.GetIssue(), self.description) | 1804 self.GetIssue(), self.description) |
| 1804 | 1805 |
| 1805 def CloseIssue(self): | 1806 def CloseIssue(self): |
| 1806 return self.RpcServer().close_issue(self.GetIssue()) | 1807 return self.RpcServer().close_issue(self.GetIssue()) |
| 1807 | 1808 |
| 1808 def SetFlag(self, flag, value): | 1809 def SetFlag(self, flag, value): |
| 1809 return self.SetFlags({flag: value}) | 1810 return self.SetFlags({flag: value}) |
| 1810 | 1811 |
| 1811 def SetFlags(self, flags): | 1812 def SetFlags(self, flags): |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2287 def GetMostRecentPatchset(self): | 2288 def GetMostRecentPatchset(self): |
| 2288 data = self._GetChangeDetail(['CURRENT_REVISION']) | 2289 data = self._GetChangeDetail(['CURRENT_REVISION']) |
| 2289 return data['revisions'][data['current_revision']]['_number'] | 2290 return data['revisions'][data['current_revision']]['_number'] |
| 2290 | 2291 |
| 2291 def FetchDescription(self): | 2292 def FetchDescription(self): |
| 2292 data = self._GetChangeDetail(['CURRENT_REVISION']) | 2293 data = self._GetChangeDetail(['CURRENT_REVISION']) |
| 2293 current_rev = data['current_revision'] | 2294 current_rev = data['current_revision'] |
| 2294 url = data['revisions'][current_rev]['fetch']['http']['url'] | 2295 url = data['revisions'][current_rev]['fetch']['http']['url'] |
| 2295 return gerrit_util.GetChangeDescriptionFromGitiles(url, current_rev) | 2296 return gerrit_util.GetChangeDescriptionFromGitiles(url, current_rev) |
| 2296 | 2297 |
| 2297 def UpdateDescriptionRemote(self, description): | 2298 def UpdateDescriptionRemote(self, description, force=False): |
| 2299 if gerrit_util.HasPendingChangeEdit(self._GetGerritHost(), self.GetIssue()): |
| 2300 if not force: |
| 2301 ask_for_data( |
| 2302 'The description cannot be modified while the issue has a pending ' |
| 2303 'unpublished edit. Either publish the edit in the Gerrit web UI ' |
| 2304 'or delete it.\n\n' |
| 2305 'Press Enter to delete the unpublished edit, Ctrl+C to abort.') |
| 2306 |
| 2307 gerrit_util.DeletePendingChangeEdit(self._GetGerritHost(), |
| 2308 self.GetIssue()) |
| 2298 gerrit_util.SetCommitMessage(self._GetGerritHost(), self.GetIssue(), | 2309 gerrit_util.SetCommitMessage(self._GetGerritHost(), self.GetIssue(), |
| 2299 description) | 2310 description) |
| 2300 | 2311 |
| 2301 def CloseIssue(self): | 2312 def CloseIssue(self): |
| 2302 gerrit_util.AbandonChange(self._GetGerritHost(), self.GetIssue(), msg='') | 2313 gerrit_util.AbandonChange(self._GetGerritHost(), self.GetIssue(), msg='') |
| 2303 | 2314 |
| 2304 def GetApprovingReviewers(self): | 2315 def GetApprovingReviewers(self): |
| 2305 """Returns a list of reviewers approving the change. | 2316 """Returns a list of reviewers approving the change. |
| 2306 | 2317 |
| 2307 Note: not necessarily committers. | 2318 Note: not necessarily committers. |
| (...skipping 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3600 | 3611 |
| 3601 | 3612 |
| 3602 @subcommand.usage('[codereview url or issue id]') | 3613 @subcommand.usage('[codereview url or issue id]') |
| 3603 def CMDdescription(parser, args): | 3614 def CMDdescription(parser, args): |
| 3604 """Brings up the editor for the current CL's description.""" | 3615 """Brings up the editor for the current CL's description.""" |
| 3605 parser.add_option('-d', '--display', action='store_true', | 3616 parser.add_option('-d', '--display', action='store_true', |
| 3606 help='Display the description instead of opening an editor') | 3617 help='Display the description instead of opening an editor') |
| 3607 parser.add_option('-n', '--new-description', | 3618 parser.add_option('-n', '--new-description', |
| 3608 help='New description to set for this issue (- for stdin, ' | 3619 help='New description to set for this issue (- for stdin, ' |
| 3609 '+ to load from local commit HEAD)') | 3620 '+ to load from local commit HEAD)') |
| 3621 parser.add_option('-f', '--force', action='store_true', |
| 3622 help='Delete any unpublished Gerrit edits for this issue ' |
| 3623 'without prompting') |
| 3610 | 3624 |
| 3611 _add_codereview_select_options(parser) | 3625 _add_codereview_select_options(parser) |
| 3612 auth.add_auth_options(parser) | 3626 auth.add_auth_options(parser) |
| 3613 options, args = parser.parse_args(args) | 3627 options, args = parser.parse_args(args) |
| 3614 _process_codereview_select_options(parser, options) | 3628 _process_codereview_select_options(parser, options) |
| 3615 | 3629 |
| 3616 target_issue = None | 3630 target_issue = None |
| 3617 if len(args) > 0: | 3631 if len(args) > 0: |
| 3618 target_issue = ParseIssueNumberArgument(args[0]) | 3632 target_issue = ParseIssueNumberArgument(args[0]) |
| 3619 if not target_issue.valid: | 3633 if not target_issue.valid: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3648 elif text == '+': | 3662 elif text == '+': |
| 3649 base_branch = cl.GetCommonAncestorWithUpstream() | 3663 base_branch = cl.GetCommonAncestorWithUpstream() |
| 3650 change = cl.GetChange(base_branch, None, local_description=True) | 3664 change = cl.GetChange(base_branch, None, local_description=True) |
| 3651 text = change.FullDescriptionText() | 3665 text = change.FullDescriptionText() |
| 3652 | 3666 |
| 3653 description.set_description(text) | 3667 description.set_description(text) |
| 3654 else: | 3668 else: |
| 3655 description.prompt() | 3669 description.prompt() |
| 3656 | 3670 |
| 3657 if cl.GetDescription() != description.description: | 3671 if cl.GetDescription() != description.description: |
| 3658 cl.UpdateDescription(description.description) | 3672 cl.UpdateDescription(description.description, force=options.force) |
| 3659 return 0 | 3673 return 0 |
| 3660 | 3674 |
| 3661 | 3675 |
| 3662 def CreateDescriptionFromLog(args): | 3676 def CreateDescriptionFromLog(args): |
| 3663 """Pulls out the commit log to use as a base for the CL description.""" | 3677 """Pulls out the commit log to use as a base for the CL description.""" |
| 3664 log_args = [] | 3678 log_args = [] |
| 3665 if len(args) == 1 and not args[0].endswith('.'): | 3679 if len(args) == 1 and not args[0].endswith('.'): |
| 3666 log_args = [args[0] + '..'] | 3680 log_args = [args[0] + '..'] |
| 3667 elif len(args) == 1 and args[0].endswith('...'): | 3681 elif len(args) == 1 and args[0].endswith('...'): |
| 3668 log_args = [args[0][:-1]] | 3682 log_args = [args[0][:-1]] |
| (...skipping 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5260 if __name__ == '__main__': | 5274 if __name__ == '__main__': |
| 5261 # These affect sys.stdout so do it outside of main() to simplify mocks in | 5275 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 5262 # unit testing. | 5276 # unit testing. |
| 5263 fix_encoding.fix_encoding() | 5277 fix_encoding.fix_encoding() |
| 5264 setup_color.init() | 5278 setup_color.init() |
| 5265 try: | 5279 try: |
| 5266 sys.exit(main(sys.argv[1:])) | 5280 sys.exit(main(sys.argv[1:])) |
| 5267 except KeyboardInterrupt: | 5281 except KeyboardInterrupt: |
| 5268 sys.stderr.write('interrupted\n') | 5282 sys.stderr.write('interrupted\n') |
| 5269 sys.exit(1) | 5283 sys.exit(1) |
| OLD | NEW |