def _GetGerritPatch(self, query): """Query the configured helpers looking for a given change. Args: project: The gerrit project to query. query: A cros_patch.PatchQuery object. Returns: A GerritPatch object. """ helper = self._LookupHelper(query) query_text = query.ToGerritQueryText() change = helper.QuerySingleRecord( query_text, must_match=not git.IsSHA1(query_text)) if not change: return # If the query was a gerrit number based query, check the projects/change-id # to see if we already have it locally, but couldn't map it since we didn't # know the gerrit number at the time of the initial injection. existing = self._lookup_cache[change] if cros_patch.ParseGerritNumber(query_text) and existing is not None: keys = change.LookupAliases() self._lookup_cache.InjectCustomKeys(keys, existing) return existing self.InjectLookupCache([change]) if change.IsAlreadyMerged(): self.InjectCommittedPatches([change]) return change
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 ]