blob: 6df000d1026d91a5cf4ed68510d2f37fe81438ff [file] [log] [blame]
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module containing helper class and methods for interacting with Gerrit."""
import constants
import json
import logging
from chromite.buildbot import patch as cros_patch
from chromite.lib import cros_build_lib
class GerritHelper():
"""Helper class to manage interaction with Gerrit server."""
def __init__(self, internal):
"""Initializes variables for interaction with a gerrit server."""
if internal:
ssh_port = constants.GERRIT_INT_PORT
ssh_host = constants.GERRIT_INT_HOST
else:
ssh_port = constants.GERRIT_PORT
ssh_host = constants.GERRIT_HOST
self.internal = internal
self.ssh_prefix = ['ssh', '-p', ssh_port, ssh_host]
def GetGerritQueryCommand(self, query_list):
"""Returns array corresponding to Gerrit Query command.
Query is useful for getting information about changelists. Returns results
in json format for easy dictionary parsing. Pass in |query| as the query
args.
"""
assert isinstance(query_list, list), 'Query command must be list.'
return self.ssh_prefix + ['gerrit', 'query', '--format=json'] + query_list
def GetGerritSqlCommand(self, command_list):
"""Returns array corresponding to Gerrit Review command.
Review can be used to modify a changelist. Specifically it can change
scores, abandon, restore or submit it. Pass in |command|.
"""
assert isinstance(command_list, list), 'Sql command must be list.'
return self.ssh_prefix + ['gerrit', 'gsql'] + command_list
def GetGerritReviewCommand(self, command_list):
"""Returns array corresponding to Gerrit Review command.
Review can be used to modify a changelist. Specifically it can change
scores, abandon, restore or submit it. Pass in |command|.
"""
assert isinstance(command_list, list), 'Review command must be list.'
return self.ssh_prefix + ['gerrit', 'review'] + command_list
def GrabChangesReadyForCommit(self):
"""Returns the list of changes to try.
This methods returns a a list of GerritPatch's to try.
"""
query_string = ('status:open AND CodeReview=+2 AND Verified=+1 '
'AND CommitReady=+1 '
'AND NOT CodeReview=-2 AND NOT Verified=-1')
ready_for_commit = ['--current-patch-set', '"%s"' % query_string]
query_cmd = self.GetGerritQueryCommand(ready_for_commit)
raw_results = cros_build_lib.RunCommand(query_cmd,
redirect_stdout=True)
# Each line returned is a json dict.
changes_to_commit = []
for raw_result in raw_results.output.splitlines():
result_dict = json.loads(raw_result)
if not 'id' in result_dict:
logging.debug('No change number found in %s', result_dict)
continue
changes_to_commit.append(cros_patch.GerritPatch(result_dict,
self.internal))
# Change to commit are ordered in descending order by last update.
# To be fair it makes sense to do apply changes eldest to newest.
changes_to_commit.reverse()
return changes_to_commit
def GrabPatchFromGerrit(self, project, change, commit):
"""Returns the GerritChange described by the arguments.
Args:
project: Name of the Gerrit project for the change.
change: The change ID for the change.
commit: The specific commit hash for the patch from the review.
"""
grab_change = (
['--current-patch-set',
'"project:%(project)s AND change:%(change)s AND commit:%(commit)s"' %
{'project': project, 'change': change, 'commit': commit}
])
query_cmd = self.GetGerritQueryCommand(grab_change)
raw_results = cros_build_lib.RunCommand(query_cmd,
redirect_stdout=True)
# First line returned is the json.
raw_result = raw_results.output.splitlines()[0]
result_dict = json.loads(raw_result)
assert result_dict.get('id'), 'Code Review json missing change-id!'
return cros_patch.GerritPatch(result_dict, self.internal)
def IsChangeCommitted(self, changeid):
"""Checks to see whether a change is already committed."""
rev_cmd = self.GetGerritQueryCommand(['change:%s' % changeid])
raw_results = cros_build_lib.RunCommand(rev_cmd, redirect_stdout=True)
result_dict = json.loads(raw_results.output.splitlines()[0])
return result_dict.get('status') not in ['NEW', 'ABANDONED', None]