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 |