def MockPatch(self, change_id=None, patch_number=None, is_merged=False, project='chromiumos/chromite', remote=site_config.params.EXTERNAL_REMOTE, tracking_branch='refs/heads/master', is_draft=False, approvals=()): """Helper function to create mock GerritPatch objects.""" if change_id is None: change_id = self._patch_counter() gerrit_number = str(change_id) change_id = hex(change_id)[2:].rstrip('L').lower() change_id = 'I%s' % change_id.rjust(40, '0') sha1 = hex(_GetNumber())[2:].rstrip('L').lower().rjust(40, '0') patch_number = (patch_number if patch_number is not None else _GetNumber()) fake_url = 'http://foo/bar' if not approvals: approvals = [{'type': 'VRIF', 'value': '1', 'grantedOn': 1391733002}, {'type': 'CRVW', 'value': '2', 'grantedOn': 1391733002}, {'type': 'COMR', 'value': '1', 'grantedOn': 1391733002}] current_patch_set = { 'number': patch_number, 'revision': sha1, 'draft': is_draft, 'approvals': approvals, } patch_dict = { 'currentPatchSet': current_patch_set, 'id': change_id, 'number': gerrit_number, 'project': project, 'branch': tracking_branch, 'owner': {'email': '*****@*****.**'}, 'remote': remote, 'status': 'MERGED' if is_merged else 'NEW', 'url': '%s/%s' % (fake_url, change_id), } patch = cros_patch.GerritPatch(patch_dict, remote, fake_url) patch.pass_count = 0 patch.fail_count = 1 patch.total_fail_count = 3 return patch
def QueryMultipleCurrentPatchset(self, changes): """Query the gerrit server for multiple changes. Args: changes: A sequence of gerrit change numbers. Returns: A list of cros_patch.GerritPatch. """ if not changes: return url_prefix = gob_util.GetGerritFetchUrl(self.host) results = self.GetMultipleChangeDetail(changes) for change, change_detail in zip(changes, results): if not change_detail: raise GerritException('Change %s not found on server %s.' % (change, self.host)) patch_dict = cros_patch.GerritPatch.ConvertQueryResults( change_detail, self.host) yield change, cros_patch.GerritPatch(patch_dict, self.remote, url_prefix)
def QueryMultipleCurrentPatchset(self, changes): if not changes: return url_prefix = gob_util.GetGerritFetchUrl(self.host) o_params = [ 'CURRENT_COMMIT', 'CURRENT_REVISION', 'DETAILED_ACCOUNTS', 'DETAILED_LABELS', ] moar = gob_util.MultiQueryChanges(self.host, {}, changes, limit=self._GERRIT_MAX_QUERY_RETURN, o_params=o_params) results = list(moar) while moar and '_more_changes' in moar[-1]: query_kwds = {'resume_sortkey': moar[-1]['_sortkey']} moar = gob_util.MultiQueryChanges( self.host, query_kwds, changes, limit=self._GERRIT_MAX_QUERY_RETURN, o_params=o_params) results.extend(moar) for change in changes: change_results = [ x for x in results if (str(x.get('_number')) == change or x.get('change_id') == change) ] if not change_results: raise GerritException('Change %s not found on server %s.' % (change, self.host)) elif len(change_results) > 1: logging.warning(json.dumps(change_results, indent=2)) raise GerritException( 'Query for change %s returned multiple results.' % change) patch_dict = cros_patch.GerritPatch.ConvertQueryResults( change_results[0], self.host) yield change, cros_patch.GerritPatch(patch_dict, self.remote, url_prefix)
def Query(self, change=None, sort=None, current_patch=True, options=(), dryrun=False, raw=False, _resume_sortkey=None, **query_kwds): if options: raise GerritException( '"options" argument unsupported on gerrit-on-borg.') url_prefix = gob_util.GetGerritFetchUrl(self.host) o_params = ['DETAILED_ACCOUNTS'] if current_patch: o_params.extend( ['CURRENT_COMMIT', 'CURRENT_REVISION', 'DETAILED_LABELS']) if change and change.isdigit() and not query_kwds: if dryrun: logging.info( 'Would have run gob_util.GetChangeDetail(%s, %s, %s)', self.host, change, o_params) return [] patch_dict = cros_patch.GerritPatch.ConvertQueryResults( gob_util.GetChangeDetail(self.host, change, o_params=o_params), self.host) if raw: return [patch_dict] return [ cros_patch.GerritPatch(patch_dict, self.remote, url_prefix) ] if change and query_kwds.get('change'): raise GerritException( 'Bad query params: provided a change-id-like query,' ' and a "change" search parameter') if _resume_sortkey: query_kwds['resume_sortkey'] = _resume_sortkey if dryrun: logging.info( 'Would have run gob_util.QueryChanges(%s, %s, ' 'first_param=%s, limit=%d)', self.host, repr(query_kwds), change, self._GERRIT_MAX_QUERY_RETURN) return [] moar = gob_util.QueryChanges(self.host, query_kwds, first_param=change, limit=self._GERRIT_MAX_QUERY_RETURN, o_params=o_params) result = list(moar) while moar and moar[-1].get('_more_changes'): query_kwds['resume_sortkey'] = result[-1].get['_sortkey'] moar = gob_util.QueryChanges(self.host, query_kwds, first_param=change, limit=self._GERRIT_MAX_QUERY_RETURN) result.extend(moar) result = [ cros_patch.GerritPatch.ConvertQueryResults(x, self.host) for x in result ] if sort: result = sorted(result, key=operator.itemgetter(sort)) if raw: return result return [ cros_patch.GerritPatch(x, self.remote, url_prefix) for x in result ]
def Query(self, query, sort=None, current_patch=True, options=(), dryrun=False, raw=False, _resume_sortkey=None): """Freeform querying of a gerrit server. Args: query: gerrit query to run: see the official docs for valid parameters: http://gerrit.googlecode.com/svn/documentation/2.1.7/cmd-query.html sort: if given, the key in the resultant json to sort on current_patch: If True, append --current-patch-set to options. If this is set to False, return the raw dictionary. If False, raw is forced to True. options: Any additional commandline options to pass to the gerrit query. Returns: A sequence of JSON dictionaries from the gerrit server. This includes patch dependencies in the 'dependsOn' and 'neededBy' fields. Raises: RunCommandException if the invocation fails, or GerritException if there is something wrong with the query parameters given """ cmd = self.ssh_prefix + [ 'gerrit', 'query', '--format=JSON', '--dependencies', '--commit-message' ] cmd.extend(options) if current_patch: cmd.append('--current-patch-set') else: raw = True # Note we intentionally cap the query to 500; gerrit does so # already, but we force it so that if gerrit were to change # its return limit, this wouldn't break. overrides = ['limit:%i' % self._GERRIT_MAX_QUERY_RETURN] if _resume_sortkey: overrides += ['resume_sortkey:%s' % _resume_sortkey] cmd.extend(['--', query] + overrides) if dryrun: logging.info('Would have run %s', ' '.join(cmd)) return [] result = cros_build_lib.RunCommand(cmd, redirect_stdout=True, print_cmd=self.print_cmd) result = self.InterpretJSONResults(query, result.output) if len(result) == self._GERRIT_MAX_QUERY_RETURN: # Gerrit cuts us off at 500; thus go recursive via the sortKey to # get the rest of the results. result += self.Query(query, _resume_sortkey=result[-1]['sortKey'], current_patch=current_patch, options=options, dryrun=dryrun, raw=True) if sort: result = sorted(result, key=operator.itemgetter(sort)) if not raw: return [ cros_patch.GerritPatch(x, self.remote, self.ssh_url) for x in result ] return result
def _GetCrosPatch(patch_info): return cros_patch.GerritPatch(patch_info, constants.EXTERNAL_REMOTE, constants.GERRIT_SSH_URL)
def _GetCrosInternalPatch(patch_info): return cros_patch.GerritPatch(patch_info, constants.INTERNAL_REMOTE, constants.GERRIT_INT_SSH_URL)
def Query(self, change=None, sort=None, current_patch=True, options=(), dryrun=False, raw=False, start=None, bypass_cache=True, **kwargs): """Free-form query for gerrit changes. Args: change: ChangeId, git commit hash, or gerrit number for a change. sort: A functor to extract a sort key from a cros_patch.GerritChange object, for sorting results.. If this is None, results will not be sorted. current_patch: If True, ask the gerrit server for extra information about the latest uploaded patch. options: Deprecated. dryrun: If True, don't query the gerrit server; return an empty list. raw: If True, return a list of python dict's representing the query results. Otherwise, return a list of cros_patch.GerritPatch. start: Offset in the result set to start at. bypass_cache: Query each change to make sure data is up to date. kwargs: A dict of query parameters, as described here: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-changes Returns: A list of python dicts or cros_patch.GerritChange. """ query_kwds = kwargs if options: raise GerritException( '"options" argument unsupported on gerrit-on-borg.') url_prefix = gob_util.GetGerritFetchUrl(self.host) # All possible params are documented at # pylint: disable=C0301 # https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-changes o_params = ['DETAILED_ACCOUNTS', 'ALL_REVISIONS', 'DETAILED_LABELS'] if current_patch: o_params.extend(['CURRENT_COMMIT', 'CURRENT_REVISION']) if change and cros_patch.ParseGerritNumber(change) and not query_kwds: if dryrun: logging.info('Would have run gob_util.GetChangeDetail(%s, %s)', self.host, change) return [] change = self.GetChangeDetail(change) if change is None: return [] patch_dict = cros_patch.GerritPatch.ConvertQueryResults( change, self.host) if raw: return [patch_dict] return [ cros_patch.GerritPatch(patch_dict, self.remote, url_prefix) ] # TODO: We should allow querying using a cros_patch.PatchQuery # object directly. if change and cros_patch.ParseSHA1(change): # Use commit:sha1 for accurate query results (crbug.com/358381). kwargs['commit'] = change change = None elif change and cros_patch.ParseChangeID(change): # Use change:change-id for accurate query results (crbug.com/357876). kwargs['change'] = change change = None elif change and cros_patch.ParseFullChangeID(change): change = cros_patch.ParseFullChangeID(change) kwargs['change'] = change.change_id kwargs['project'] = change.project kwargs['branch'] = change.branch change = None if change and query_kwds.get('change'): raise GerritException( 'Bad query params: provided a change-id-like query,' ' and a "change" search parameter') if dryrun: logging.info( 'Would have run gob_util.QueryChanges(%s, %s, ' 'first_param=%s, limit=%d)', self.host, repr(query_kwds), change, self._GERRIT_MAX_QUERY_RETURN) return [] start = 0 moar = gob_util.QueryChanges(self.host, query_kwds, first_param=change, start=start, limit=self._GERRIT_MAX_QUERY_RETURN, o_params=o_params) result = list(moar) while moar and self.MORE_CHANGES in moar[-1]: start += len(moar) moar = gob_util.QueryChanges(self.host, query_kwds, first_param=change, start=start, limit=self._GERRIT_MAX_QUERY_RETURN, o_params=o_params) result.extend(moar) # NOTE: Query results are served from the gerrit cache, which may be stale. # To make sure the patch information is accurate, re-request each query # result directly, circumventing the cache. For reference: # https://code.google.com/p/chromium/issues/detail?id=302072 if bypass_cache: result = self.GetMultipleChangeDetail( [x['_number'] for x in result]) result = [ cros_patch.GerritPatch.ConvertQueryResults(x, self.host) for x in result ] if sort: result = sorted(result, key=operator.itemgetter(sort)) if raw: return result return [ cros_patch.GerritPatch(x, self.remote, url_prefix) for x in result ]