Esempio n. 1
0
  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
Esempio n. 2
0
  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)
Esempio n. 3
0
 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)
Esempio n. 4
0
    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
        ]
Esempio n. 5
0
    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)
Esempio n. 8
0
    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
        ]