blob: 4f81bc5b35fc53755ae6f2f73ef5b91d97ad7325 [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
import os
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, branch):
"""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 FilterProjectsNotInSourceTree(self, changes, buildroot):
"""Returns new filtered set of relevant changes to this source checkout.
There may be many miscellaneous reviews in other Gerrit repos that are not
part of the checked out manifest. This method returns a filtered list of
changes with such reviews removed.
Args:
changes: List of GerritPatch objects.
buildroot: Buildroot containing manifest to filter against.
Returns filtered list of GerritPatch objects.
"""
manifest_path = os.path.join(buildroot, '.repo', 'manifests/full.xml')
handler = cros_build_lib.ManifestHandler.ParseManifest(manifest_path)
projects = handler.projects
changes_to_return = []
for change in changes:
project = projects.get(change.project)
if project:
branch = project.get('revision') or handler.default.get('revision')
patch_branch = 'refs/heads/%s' % change.tracking_branch
if branch == patch_branch:
changes_to_return.append(change)
continue
logging.info('Filtered change %s', change)
return changes_to_return
def IsRevisionCommitted(self, project, revision):
"""Checks to see whether a revision is committed."""
rev_cmd = self.GetGerritQueryCommand(['project:%s' % project,
'commit:%s' % revision])
raw_results = cros_build_lib.RunCommand(rev_cmd, redirect_stdout=True)
result_dict = json.loads(raw_results.output.splitlines()[0])
return result_dict['status'] not in ['NEW', 'ABANDONED']