| Index: git_cl.py
|
| diff --git a/git_cl.py b/git_cl.py
|
| index 41bbb9800ecf68e8a24e5e9b0f9ce055009f8074..f10c196b93a83db5a5d2015195419feced1f9f52 100755
|
| --- a/git_cl.py
|
| +++ b/git_cl.py
|
| @@ -1448,6 +1448,14 @@ class Changelist(object):
|
| def GetStatus(self):
|
| return self._codereview_impl.GetStatus()
|
|
|
| + def IsOpen(self):
|
| + return self._codereview_impl.IsOpen()
|
| +
|
| + def GetCQState(self):
|
| + state = self._codereview_impl.GetCQState()
|
| + assert state in _CQState.ALL_STATES
|
| + return state
|
| +
|
| def GetCodereviewServer(self):
|
| return self._codereview_impl.GetCodereviewServer()
|
|
|
| @@ -1483,6 +1491,14 @@ class _ChangelistCodereviewBase(object):
|
| """
|
| raise NotImplementedError()
|
|
|
| + def IsOpen(self):
|
| + """Returns True iff the issue is open."""
|
| + raise NotImplementedError()
|
| +
|
| + def GetCQState(self):
|
| + """Returns CQ state (see _CQState)."""
|
| + raise NotImplementedError()
|
| +
|
| def GetCodereviewServer(self):
|
| """Returns server URL without end slash, like "https://codereview.com"."""
|
| raise NotImplementedError()
|
| @@ -1681,11 +1697,9 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase):
|
| except urllib2.HTTPError:
|
| return 'error'
|
|
|
| - if props.get('closed'):
|
| - # Issue is closed.
|
| + if not self.IsOpen():
|
| return 'closed'
|
| - if props.get('commit') and not props.get('cq_dry_run', False):
|
| - # Issue is in the commit queue.
|
| + if self.GetCQState() == _CQState.COMMIT:
|
| return 'commit'
|
|
|
| try:
|
| @@ -1719,6 +1733,20 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase):
|
| return 'reply'
|
| return 'waiting'
|
|
|
| + def IsOpen(self, props=None):
|
| + if not props:
|
| + props = self.GetIssueProperties()
|
| + return not props.get('closed')
|
| +
|
| + def GetCQState(self, props=None):
|
| + if not props:
|
| + props = self.GetIssueProperties()
|
| + if props.get('commit') and not props.get('cq_dry_run'):
|
| + return _CQState.COMMIT
|
| + if props.get('cq_dry_run'):
|
| + return _CQState.DRY_RUN
|
| + return _CQState.NONE
|
| +
|
| def UpdateDescriptionRemote(self, description):
|
| return self.RpcServer().update_description(
|
| self.GetIssue(), self.description)
|
| @@ -2191,16 +2219,11 @@ class _GerritChangelistImpl(_ChangelistCodereviewBase):
|
| except httplib.HTTPException:
|
| return 'error'
|
|
|
| - if data['status'] in ('ABANDONED', 'MERGED'):
|
| + if not self.IsOpen(data=data):
|
| return 'closed'
|
|
|
| - cq_label = data['labels'].get('Commit-Queue', {})
|
| - if cq_label:
|
| - # Vote value is a stringified integer, which we expect from 0 to 2.
|
| - vote_value = cq_label.get('value', '0')
|
| - vote_text = cq_label.get('values', {}).get(vote_value, '')
|
| - if vote_text.lower() == 'commit':
|
| - return 'commit'
|
| + if self.GetCQState(data=data) == _CQState.COMMIT:
|
| + return 'commit'
|
|
|
| lgtm_label = data['labels'].get('Code-Review', {})
|
| if lgtm_label:
|
| @@ -2222,6 +2245,25 @@ class _GerritChangelistImpl(_ChangelistCodereviewBase):
|
|
|
| return 'waiting'
|
|
|
| + def IsOpen(self, data=None):
|
| + if not data:
|
| + data = self._GetChangeDetail(['DETAILED_LABELS', 'CURRENT_REVISION'])
|
| + return data['status'] not in ('ABANDONED', 'MERGED')
|
| +
|
| + def GetCQState(self, data=None):
|
| + if not data:
|
| + data = self._GetChangeDetail(['DETAILED_LABELS', 'CURRENT_REVISION'])
|
| + cq_label = data['labels'].get('Commit-Queue', {})
|
| + if cq_label:
|
| + # Vote value is a stringified integer, which we expect from 0 to 2.
|
| + vote_value = cq_label.get('value', '0')
|
| + vote_text = cq_label.get('values', {}).get(vote_value, '')
|
| + if vote_text.lower() == 'commit':
|
| + return _CQState.COMMIT
|
| + if vote_test.lower() == 'dry run':
|
| + return _CQState.DRY_RUN
|
| + return _CQState.NONE
|
| +
|
| def GetMostRecentPatchset(self):
|
| data = self._GetChangeDetail(['CURRENT_REVISION'])
|
| return data['revisions'][data['current_revision']]['_number']
|
| @@ -5059,6 +5101,34 @@ def CMDlol(parser, args):
|
| return 0
|
|
|
|
|
| +def CMDplumbing(parser, args):
|
| + """Returns info about the CL in machine-readable form."""
|
| + parser.add_option('--json', help='Path to output JSON file')
|
| +
|
| + auth.add_auth_options(parser)
|
| +
|
| + _add_codereview_select_options(parser)
|
| + options, args = parser.parse_args(args)
|
| + _process_codereview_select_options(parser, options)
|
| +
|
| + auth_config = auth.extract_auth_config_from_options(options)
|
| +
|
| + cl = Changelist(auth_config=auth_config, codereview=options.forced_codereview)
|
| +
|
| + result = {
|
| + 'open': cl.IsOpen(),
|
| + 'commit_queue': cl.GetCQState(),
|
| + }
|
| +
|
| + if options.json:
|
| + with open(options.json, 'w') as f:
|
| + json.dump(result, f)
|
| + else:
|
| + print(json.dumps(result, sort_keys=True, indent=4))
|
| +
|
| + return 0
|
| +
|
| +
|
| class OptionParser(optparse.OptionParser):
|
| """Creates the option parse and add --verbose support."""
|
| def __init__(self, *args, **kwargs):
|
|
|