| 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 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 if response.status < 500 or try_count >= 2: | 311 if response.status < 500 or try_count >= 2: |
| 312 raise httplib2.HttpLib2Error(content) | 312 raise httplib2.HttpLib2Error(content) |
| 313 | 313 |
| 314 # status >= 500 means transient failures. | 314 # status >= 500 means transient failures. |
| 315 logging.debug('Transient errors when %s. Will retry.', operation_name) | 315 logging.debug('Transient errors when %s. Will retry.', operation_name) |
| 316 time.sleep(0.5 + 1.5*try_count) | 316 time.sleep(0.5 + 1.5*try_count) |
| 317 try_count += 1 | 317 try_count += 1 |
| 318 assert False, 'unreachable' | 318 assert False, 'unreachable' |
| 319 | 319 |
| 320 | 320 |
| 321 def trigger_try_jobs(auth_config, changelist, options, masters, category): | 321 def _trigger_try_jobs(auth_config, changelist, masters, options, |
| 322 rietveld_url = settings.GetDefaultServerUrl() | 322 category='git_cl_try', patchset=None): |
| 323 rietveld_host = urlparse.urlparse(rietveld_url).hostname | 323 assert changelist.GetIssue(), 'CL must be uploaded first' |
| 324 authenticator = auth.get_authenticator_for_host(rietveld_host, auth_config) | 324 codereview_url = changelist.GetCodereviewServer() |
| 325 assert codereview_url, 'CL must be uploaded first' |
| 326 patchset = patchset or changelist.GetMostRecentPatchset() |
| 327 assert patchset, 'CL must be uploaded first' |
| 328 |
| 329 codereview_host = urlparse.urlparse(codereview_url).hostname |
| 330 authenticator = auth.get_authenticator_for_host(codereview_host, auth_config) |
| 325 http = authenticator.authorize(httplib2.Http()) | 331 http = authenticator.authorize(httplib2.Http()) |
| 326 http.force_exception_to_status_code = True | 332 http.force_exception_to_status_code = True |
| 327 issue_props = changelist.GetIssueProperties() | 333 |
| 328 issue = changelist.GetIssue() | 334 # TODO(tandrii): consider caching Gerrit CL details just like |
| 329 patchset = changelist.GetMostRecentPatchset() | 335 # _RietveldChangelistImpl does, then caching values in these two variables |
| 330 properties = _get_properties_from_options(options) | 336 # won't be necessary. |
| 337 owner_email = changelist.GetIssueOwner() |
| 338 project = changelist.GetIssueProject() |
| 331 | 339 |
| 332 buildbucket_put_url = ( | 340 buildbucket_put_url = ( |
| 333 'https://{hostname}/_ah/api/buildbucket/v1/builds/batch'.format( | 341 'https://{hostname}/_ah/api/buildbucket/v1/builds/batch'.format( |
| 334 hostname=options.buildbucket_host)) | 342 hostname=options.buildbucket_host)) |
| 335 buildset = 'patch/rietveld/{hostname}/{issue}/{patch}'.format( | 343 buildset = 'patch/{codereview}/{hostname}/{issue}/{patch}'.format( |
| 336 hostname=rietveld_host, | 344 codereview='gerrit' if changelist.IsGerrit() else 'rietveld', |
| 337 issue=issue, | 345 hostname=codereview_host, |
| 346 issue=changelist.GetIssue(), |
| 338 patch=patchset) | 347 patch=patchset) |
| 348 extra_properties = _get_properties_from_options(options) |
| 339 | 349 |
| 340 batch_req_body = {'builds': []} | 350 batch_req_body = {'builds': []} |
| 341 print_text = [] | 351 print_text = [] |
| 342 print_text.append('Tried jobs on:') | 352 print_text.append('Tried jobs on:') |
| 343 for master, builders_and_tests in sorted(masters.iteritems()): | 353 for master, builders_and_tests in sorted(masters.iteritems()): |
| 344 print_text.append('Master: %s' % master) | 354 print_text.append('Master: %s' % master) |
| 345 bucket = _prefix_master(master) | 355 bucket = _prefix_master(master) |
| 346 for builder, tests in sorted(builders_and_tests.iteritems()): | 356 for builder, tests in sorted(builders_and_tests.iteritems()): |
| 347 print_text.append(' %s: %s' % (builder, tests)) | 357 print_text.append(' %s: %s' % (builder, tests)) |
| 348 parameters = { | 358 parameters = { |
| 349 'builder_name': builder, | 359 'builder_name': builder, |
| 350 'changes': [{ | 360 'changes': [{ |
| 351 'author': {'email': issue_props['owner_email']}, | 361 'author': {'email': owner_email}, |
| 352 'revision': options.revision, | 362 'revision': options.revision, |
| 353 }], | 363 }], |
| 354 'properties': { | 364 'properties': { |
| 355 'category': category, | 365 'category': category, |
| 356 'issue': issue, | 366 'issue': changelist.GetIssue(), |
| 357 'master': master, | 367 'master': master, |
| 358 'patch_project': issue_props['project'], | 368 'patch_project': project, |
| 359 'patch_storage': 'rietveld', | 369 'patch_storage': 'rietveld', |
| 360 'patchset': patchset, | 370 'patchset': patchset, |
| 361 'reason': options.name, | 371 'reason': options.name, |
| 362 'rietveld': rietveld_url, | 372 'rietveld': codereview_url, |
| 363 }, | 373 }, |
| 364 } | 374 } |
| 365 if 'presubmit' in builder.lower(): | 375 if 'presubmit' in builder.lower(): |
| 366 parameters['properties']['dry_run'] = 'true' | 376 parameters['properties']['dry_run'] = 'true' |
| 367 if tests: | 377 if tests: |
| 368 parameters['properties']['testfilter'] = tests | 378 parameters['properties']['testfilter'] = tests |
| 369 if properties: | 379 if extra_properties: |
| 370 parameters['properties'].update(properties) | 380 parameters['properties'].update(extra_properties) |
| 371 if options.clobber: | 381 if options.clobber: |
| 372 parameters['properties']['clobber'] = True | 382 parameters['properties']['clobber'] = True |
| 373 batch_req_body['builds'].append( | 383 batch_req_body['builds'].append( |
| 374 { | 384 { |
| 375 'bucket': bucket, | 385 'bucket': bucket, |
| 376 'parameters_json': json.dumps(parameters), | 386 'parameters_json': json.dumps(parameters), |
| 377 'client_operation_id': str(uuid.uuid4()), | 387 'client_operation_id': str(uuid.uuid4()), |
| 378 'tags': ['builder:%s' % builder, | 388 'tags': ['builder:%s' % builder, |
| 379 'buildset:%s' % buildset, | 389 'buildset:%s' % buildset, |
| 380 'master:%s' % master, | 390 'master:%s' % master, |
| (...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 | 1551 |
| 1542 def SetCQState(self, new_state): | 1552 def SetCQState(self, new_state): |
| 1543 """Update the CQ state for latest patchset. | 1553 """Update the CQ state for latest patchset. |
| 1544 | 1554 |
| 1545 Issue must have been already uploaded and known. | 1555 Issue must have been already uploaded and known. |
| 1546 """ | 1556 """ |
| 1547 assert new_state in _CQState.ALL_STATES | 1557 assert new_state in _CQState.ALL_STATES |
| 1548 assert self.GetIssue() | 1558 assert self.GetIssue() |
| 1549 return self._codereview_impl.SetCQState(new_state) | 1559 return self._codereview_impl.SetCQState(new_state) |
| 1550 | 1560 |
| 1551 def CannotTriggerTryJobReason(self): | |
| 1552 """Returns reason (str) if unable trigger tryjobs on this CL or None.""" | |
| 1553 return self._codereview_impl.CannotTriggerTryJobReason() | |
| 1554 | |
| 1555 # Forward methods to codereview specific implementation. | 1561 # Forward methods to codereview specific implementation. |
| 1556 | 1562 |
| 1557 def CloseIssue(self): | 1563 def CloseIssue(self): |
| 1558 return self._codereview_impl.CloseIssue() | 1564 return self._codereview_impl.CloseIssue() |
| 1559 | 1565 |
| 1560 def GetStatus(self): | 1566 def GetStatus(self): |
| 1561 return self._codereview_impl.GetStatus() | 1567 return self._codereview_impl.GetStatus() |
| 1562 | 1568 |
| 1563 def GetCodereviewServer(self): | 1569 def GetCodereviewServer(self): |
| 1564 return self._codereview_impl.GetCodereviewServer() | 1570 return self._codereview_impl.GetCodereviewServer() |
| 1565 | 1571 |
| 1572 def GetIssueOwner(self): |
| 1573 """Get owner from codereview, which may differ from this checkout.""" |
| 1574 return self._codereview_impl.GetIssueOwner() |
| 1575 |
| 1576 def GetIssueProject(self): |
| 1577 """Get project from codereview, which may differ from what this |
| 1578 checkout's codereview.settings or gerrit project URL say. |
| 1579 """ |
| 1580 return self._codereview_impl.GetIssueProject() |
| 1581 |
| 1566 def GetApprovingReviewers(self): | 1582 def GetApprovingReviewers(self): |
| 1567 return self._codereview_impl.GetApprovingReviewers() | 1583 return self._codereview_impl.GetApprovingReviewers() |
| 1568 | 1584 |
| 1569 def GetMostRecentPatchset(self): | 1585 def GetMostRecentPatchset(self): |
| 1570 return self._codereview_impl.GetMostRecentPatchset() | 1586 return self._codereview_impl.GetMostRecentPatchset() |
| 1571 | 1587 |
| 1588 def CannotTriggerTryJobReason(self): |
| 1589 """Returns reason (str) if unable trigger tryjobs on this CL or None.""" |
| 1590 return self._codereview_impl.CannotTriggerTryJobReason() |
| 1591 |
| 1572 def __getattr__(self, attr): | 1592 def __getattr__(self, attr): |
| 1573 # This is because lots of untested code accesses Rietveld-specific stuff | 1593 # This is because lots of untested code accesses Rietveld-specific stuff |
| 1574 # directly, and it's hard to fix for sure. So, just let it work, and fix | 1594 # directly, and it's hard to fix for sure. So, just let it work, and fix |
| 1575 # on a case by case basis. | 1595 # on a case by case basis. |
| 1576 # Note that child method defines __getattr__ as well, and forwards it here, | 1596 # Note that child method defines __getattr__ as well, and forwards it here, |
| 1577 # because _RietveldChangelistImpl is not cleaned up yet, and given | 1597 # because _RietveldChangelistImpl is not cleaned up yet, and given |
| 1578 # deprecation of Rietveld, it should probably be just removed. | 1598 # deprecation of Rietveld, it should probably be just removed. |
| 1579 # Until that time, avoid infinite recursion by bypassing __getattr__ | 1599 # Until that time, avoid infinite recursion by bypassing __getattr__ |
| 1580 # of implementation class. | 1600 # of implementation class. |
| 1581 return self._codereview_impl.__getattribute__(attr) | 1601 return self._codereview_impl.__getattribute__(attr) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1691 """Update the CQ state for latest patchset. | 1711 """Update the CQ state for latest patchset. |
| 1692 | 1712 |
| 1693 Issue must have been already uploaded and known. | 1713 Issue must have been already uploaded and known. |
| 1694 """ | 1714 """ |
| 1695 raise NotImplementedError() | 1715 raise NotImplementedError() |
| 1696 | 1716 |
| 1697 def CannotTriggerTryJobReason(self): | 1717 def CannotTriggerTryJobReason(self): |
| 1698 """Returns reason (str) if unable trigger tryjobs on this CL or None.""" | 1718 """Returns reason (str) if unable trigger tryjobs on this CL or None.""" |
| 1699 raise NotImplementedError() | 1719 raise NotImplementedError() |
| 1700 | 1720 |
| 1721 def GetIssueOwner(self): |
| 1722 raise NotImplementedError() |
| 1723 |
| 1724 def GetIssueProject(self): |
| 1725 raise NotImplementedError() |
| 1726 |
| 1701 | 1727 |
| 1702 class _RietveldChangelistImpl(_ChangelistCodereviewBase): | 1728 class _RietveldChangelistImpl(_ChangelistCodereviewBase): |
| 1703 def __init__(self, changelist, auth_config=None, rietveld_server=None): | 1729 def __init__(self, changelist, auth_config=None, rietveld_server=None): |
| 1704 super(_RietveldChangelistImpl, self).__init__(changelist) | 1730 super(_RietveldChangelistImpl, self).__init__(changelist) |
| 1705 assert settings, 'must be initialized in _ChangelistCodereviewBase' | 1731 assert settings, 'must be initialized in _ChangelistCodereviewBase' |
| 1706 if not rietveld_server: | 1732 if not rietveld_server: |
| 1707 settings.GetDefaultServerUrl() | 1733 settings.GetDefaultServerUrl() |
| 1708 | 1734 |
| 1709 self._rietveld_server = rietveld_server | 1735 self._rietveld_server = rietveld_server |
| 1710 self._auth_config = auth_config | 1736 self._auth_config = auth_config |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1776 return 'Rietveld doesn\'t know about your issue %s' % self.GetIssue() | 1802 return 'Rietveld doesn\'t know about your issue %s' % self.GetIssue() |
| 1777 if props.get('closed'): | 1803 if props.get('closed'): |
| 1778 return 'CL %s is closed' % self.GetIssue() | 1804 return 'CL %s is closed' % self.GetIssue() |
| 1779 if props.get('private'): | 1805 if props.get('private'): |
| 1780 return 'CL %s is private' % self.GetIssue() | 1806 return 'CL %s is private' % self.GetIssue() |
| 1781 return None | 1807 return None |
| 1782 | 1808 |
| 1783 def GetApprovingReviewers(self): | 1809 def GetApprovingReviewers(self): |
| 1784 return get_approving_reviewers(self.GetIssueProperties()) | 1810 return get_approving_reviewers(self.GetIssueProperties()) |
| 1785 | 1811 |
| 1812 def GetIssueOwner(self): |
| 1813 return (self.GetIssueProperties() or {}).get('owner_email') |
| 1814 |
| 1815 def GetIssueProject(self): |
| 1816 return (self.GetIssueProperties() or {}).get('project') |
| 1817 |
| 1786 def AddComment(self, message): | 1818 def AddComment(self, message): |
| 1787 return self.RpcServer().add_comment(self.GetIssue(), message) | 1819 return self.RpcServer().add_comment(self.GetIssue(), message) |
| 1788 | 1820 |
| 1789 def GetStatus(self): | 1821 def GetStatus(self): |
| 1790 """Apply a rough heuristic to give a simple summary of an issue's review | 1822 """Apply a rough heuristic to give a simple summary of an issue's review |
| 1791 or CQ status, assuming adherence to a common workflow. | 1823 or CQ status, assuming adherence to a common workflow. |
| 1792 | 1824 |
| 1793 Returns None if no issue for this branch, or one of the following keywords: | 1825 Returns None if no issue for this branch, or one of the following keywords: |
| 1794 * 'error' - error from review tool (including deleted issues) | 1826 * 'error' - error from review tool (including deleted issues) |
| 1795 * 'unsent' - not sent for review | 1827 * 'unsent' - not sent for review |
| (...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2731 _CQState.DRY_RUN: 1, | 2763 _CQState.DRY_RUN: 1, |
| 2732 _CQState.COMMIT : 2, | 2764 _CQState.COMMIT : 2, |
| 2733 } | 2765 } |
| 2734 gerrit_util.SetReview(self._GetGerritHost(), self.GetIssue(), | 2766 gerrit_util.SetReview(self._GetGerritHost(), self.GetIssue(), |
| 2735 labels={'Commit-Queue': vote_map[new_state]}) | 2767 labels={'Commit-Queue': vote_map[new_state]}) |
| 2736 | 2768 |
| 2737 def CannotTriggerTryJobReason(self): | 2769 def CannotTriggerTryJobReason(self): |
| 2738 # TODO(tandrii): implement for Gerrit. | 2770 # TODO(tandrii): implement for Gerrit. |
| 2739 raise NotImplementedError() | 2771 raise NotImplementedError() |
| 2740 | 2772 |
| 2773 def GetIssueOwner(self): |
| 2774 # TODO(tandrii): implement for Gerrit. |
| 2775 raise NotImplementedError() |
| 2776 |
| 2777 def GetIssueProject(self): |
| 2778 # TODO(tandrii): implement for Gerrit. |
| 2779 raise NotImplementedError() |
| 2780 |
| 2741 | 2781 |
| 2742 _CODEREVIEW_IMPLEMENTATIONS = { | 2782 _CODEREVIEW_IMPLEMENTATIONS = { |
| 2743 'rietveld': _RietveldChangelistImpl, | 2783 'rietveld': _RietveldChangelistImpl, |
| 2744 'gerrit': _GerritChangelistImpl, | 2784 'gerrit': _GerritChangelistImpl, |
| 2745 } | 2785 } |
| 2746 | 2786 |
| 2747 | 2787 |
| 2748 def _add_codereview_issue_select_options(parser, extra=""): | 2788 def _add_codereview_issue_select_options(parser, extra=""): |
| 2749 _add_codereview_select_options(parser) | 2789 _add_codereview_select_options(parser) |
| 2750 | 2790 |
| (...skipping 1959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4710 | 4750 |
| 4711 cl = Changelist(auth_config=auth_config) | 4751 cl = Changelist(auth_config=auth_config) |
| 4712 if not cl.GetIssue(): | 4752 if not cl.GetIssue(): |
| 4713 parser.error('Need to upload first') | 4753 parser.error('Need to upload first') |
| 4714 | 4754 |
| 4715 if cl.IsGerrit(): | 4755 if cl.IsGerrit(): |
| 4716 parser.error( | 4756 parser.error( |
| 4717 'Not yet supported for Gerrit (http://crbug.com/599931).\n' | 4757 'Not yet supported for Gerrit (http://crbug.com/599931).\n' |
| 4718 'If your project has Commit Queue, dry run is a workaround:\n' | 4758 'If your project has Commit Queue, dry run is a workaround:\n' |
| 4719 ' git cl set-commit --dry-run') | 4759 ' git cl set-commit --dry-run') |
| 4720 # Code below assumes Rietveld issue. | |
| 4721 # TODO(tandrii): actually implement for Gerrit http://crbug.com/599931. | |
| 4722 | 4760 |
| 4723 error_message = cl.CannotTriggerTryJobReason() | 4761 error_message = cl.CannotTriggerTryJobReason() |
| 4724 if error_message: | 4762 if error_message: |
| 4725 parser.error('Can\'t trigger try jobs: %s') | 4763 parser.error('Can\'t trigger try jobs: %s') |
| 4726 | 4764 |
| 4727 if not options.name: | 4765 if not options.name: |
| 4728 options.name = cl.GetBranch() | 4766 options.name = cl.GetBranch() |
| 4729 | 4767 |
| 4730 if options.bot and not options.master: | 4768 if options.bot and not options.master: |
| 4731 options.master, err_msg = GetBuilderMaster(options.bot) | 4769 options.master, err_msg = GetBuilderMaster(options.bot) |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4806 'Consider specifying which bots to trigger manually ' | 4844 'Consider specifying which bots to trigger manually ' |
| 4807 'or asking your project owners for permissions ' | 4845 'or asking your project owners for permissions ' |
| 4808 'or contacting Chrome Infrastructure team at ' | 4846 'or contacting Chrome Infrastructure team at ' |
| 4809 'https://www.chromium.org/infra\n\n') | 4847 'https://www.chromium.org/infra\n\n') |
| 4810 # Still raise exception so that stack trace is printed. | 4848 # Still raise exception so that stack trace is printed. |
| 4811 raise | 4849 raise |
| 4812 | 4850 |
| 4813 for builders in masters.itervalues(): | 4851 for builders in masters.itervalues(): |
| 4814 if any('triggered' in b for b in builders): | 4852 if any('triggered' in b for b in builders): |
| 4815 print('ERROR You are trying to send a job to a triggered bot. This type ' | 4853 print('ERROR You are trying to send a job to a triggered bot. This type ' |
| 4816 'of bot requires an\ninitial job from a parent (usually a builder).' | 4854 'of bot requires an initial job from a parent (usually a builder). ' |
| 4817 ' Instead send your job to the parent.\n' | 4855 'Instead send your job to the parent.\n' |
| 4818 'Bot list: %s' % builders, file=sys.stderr) | 4856 'Bot list: %s' % builders, file=sys.stderr) |
| 4819 return 1 | 4857 return 1 |
| 4820 | 4858 |
| 4821 patchset = cl.GetMostRecentPatchset() | 4859 patchset = cl.GetMostRecentPatchset() |
| 4822 if patchset and patchset != cl.GetPatchset(): | 4860 if patchset != cl.GetPatchset(): |
| 4823 print( | 4861 print('Warning: Codereview server has newer patchsets (%s) than most ' |
| 4824 '\nWARNING Mismatch between local config and server. Did a previous ' | 4862 'recent upload from local checkout (%s). Did a previous upload ' |
| 4825 'upload fail?\ngit-cl try always uses latest patchset from rietveld. ' | 4863 'fail?\n' |
| 4826 'Continuing using\npatchset %s.\n' % patchset) | 4864 'By default, git cl try uses the latest patchset from ' |
| 4865 'codereview, continuing to use patchset %s.\n' % |
| 4866 (patchset, cl.GetPatchset(), patchset)) |
| 4827 try: | 4867 try: |
| 4828 trigger_try_jobs(auth_config, cl, options, masters, 'git_cl_try') | 4868 _trigger_try_jobs(auth_config, cl, masters, options, 'git_cl_try', |
| 4869 patchset) |
| 4829 except BuildbucketResponseException as ex: | 4870 except BuildbucketResponseException as ex: |
| 4830 print('ERROR: %s' % ex) | 4871 print('ERROR: %s' % ex) |
| 4831 return 1 | 4872 return 1 |
| 4832 except Exception as e: | |
| 4833 stacktrace = (''.join(traceback.format_stack()) + traceback.format_exc()) | |
| 4834 print('ERROR: Exception when trying to trigger try jobs: %s\n%s' % | |
| 4835 (e, stacktrace)) | |
| 4836 return 1 | |
| 4837 return 0 | 4873 return 0 |
| 4838 | 4874 |
| 4839 | 4875 |
| 4840 def CMDtry_results(parser, args): | 4876 def CMDtry_results(parser, args): |
| 4841 """Prints info about try jobs associated with current CL.""" | 4877 """Prints info about try jobs associated with current CL.""" |
| 4842 group = optparse.OptionGroup(parser, 'Try job results options') | 4878 group = optparse.OptionGroup(parser, 'Try job results options') |
| 4843 group.add_option( | 4879 group.add_option( |
| 4844 '-p', '--patchset', type=int, help='patchset number if not current.') | 4880 '-p', '--patchset', type=int, help='patchset number if not current.') |
| 4845 group.add_option( | 4881 group.add_option( |
| 4846 '--print-master', action='store_true', help='print master name as well.') | 4882 '--print-master', action='store_true', help='print master name as well.') |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4869 if not patchset: | 4905 if not patchset: |
| 4870 parser.error('Codereview doesn\'t know about issue %s. ' | 4906 parser.error('Codereview doesn\'t know about issue %s. ' |
| 4871 'No access to issue or wrong issue number?\n' | 4907 'No access to issue or wrong issue number?\n' |
| 4872 'Either upload first, or pass --patchset explicitely' % | 4908 'Either upload first, or pass --patchset explicitely' % |
| 4873 cl.GetIssue()) | 4909 cl.GetIssue()) |
| 4874 | 4910 |
| 4875 if patchset != cl.GetPatchset(): | 4911 if patchset != cl.GetPatchset(): |
| 4876 print('Warning: Codereview server has newer patchsets (%s) than most ' | 4912 print('Warning: Codereview server has newer patchsets (%s) than most ' |
| 4877 'recent upload from local checkout (%s). Did a previous upload ' | 4913 'recent upload from local checkout (%s). Did a previous upload ' |
| 4878 'fail?\n' | 4914 'fail?\n' |
| 4879 'By default, git cl try uses latest patchset from codereview, ' | 4915 'By default, git cl try-results uses the latest patchset from ' |
| 4880 'continuing to use patchset %s.\n' % | 4916 'codereview, continuing to use patchset %s.\n' % |
| 4881 (patchset, cl.GetPatchset(), patchset)) | 4917 (patchset, cl.GetPatchset(), patchset)) |
| 4882 try: | 4918 try: |
| 4883 jobs = fetch_try_jobs(auth_config, cl, options.buildbucket_host, patchset) | 4919 jobs = fetch_try_jobs(auth_config, cl, options.buildbucket_host, patchset) |
| 4884 except BuildbucketResponseException as ex: | 4920 except BuildbucketResponseException as ex: |
| 4885 print('Buildbucket error: %s' % ex) | 4921 print('Buildbucket error: %s' % ex) |
| 4886 return 1 | 4922 return 1 |
| 4887 if options.json: | 4923 if options.json: |
| 4888 write_try_results_json(options.json, jobs) | 4924 write_try_results_json(options.json, jobs) |
| 4889 else: | 4925 else: |
| 4890 print_try_jobs(options, jobs) | 4926 print_try_jobs(options, jobs) |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5329 if __name__ == '__main__': | 5365 if __name__ == '__main__': |
| 5330 # These affect sys.stdout so do it outside of main() to simplify mocks in | 5366 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 5331 # unit testing. | 5367 # unit testing. |
| 5332 fix_encoding.fix_encoding() | 5368 fix_encoding.fix_encoding() |
| 5333 setup_color.init() | 5369 setup_color.init() |
| 5334 try: | 5370 try: |
| 5335 sys.exit(main(sys.argv[1:])) | 5371 sys.exit(main(sys.argv[1:])) |
| 5336 except KeyboardInterrupt: | 5372 except KeyboardInterrupt: |
| 5337 sys.stderr.write('interrupted\n') | 5373 sys.stderr.write('interrupted\n') |
| 5338 sys.exit(1) | 5374 sys.exit(1) |
| OLD | NEW |