Beispiel #1
0
 def GetClDetails(self, change_id):
     params = {'messages': 'true'}
     url = 'https://%s/api/%s' % (self._server_hostname, change_id)
     status_code, content = self.HTTP_CLIENT.Get(url, params=params)
     if status_code == 200:  # pragma: no branch
         return self._ParseClInfo(
             json.loads(content),
             cl_info.ClInfo(self._server_hostname, change_id))
     return None  # pragma: no cover
Beispiel #2
0
  def testClInfo(self):

    def hours(h):
      return datetime.timedelta(hours=h)

    cl = cl_info.ClInfo(self.server, self.change_id)
    # Adding two attempts with the same timestamp to cover the codepath that
    # checks that the timestamp is different.
    cl.AddCqAttempt(self.patchset_id, self.email, self.timestamp)
    cl.AddCqAttempt(self.patchset_id, self.email, self.timestamp)
    cl.AddCqAttempt(
        self.patchset_id,
        self.email,
        self.timestamp + datetime.timedelta(hours=1))

    commit_1 = cl_info.Commit(self.patchset_id, self.revision,
                              self.parent_revisions, self.timestamp + hours(1))
    cl.commits.append(commit_1)
    self.assertEqual(commit_1, cl.GetCommitInfoByRevision(self.revision))
    self.assertIsNone(cl.GetCommitInfoByRevision('randomrevision'))
    self.assertEqual(self.patchset_id,
                     cl.GetPatchsetIdByRevision(self.revision))

    cl.commits.append(
        cl_info.Commit('3000', 'ef1234', [], self.timestamp + hours(2)))
    self.assertEqual('3000', cl.GetPatchsetIdByRevision('ef1234'))
    self.assertIsNone(cl.GetPatchsetIdByRevision('deadc0de'))

    revert_cl_1 = cl_info.ClInfo(self.server, 'revert1')
    revert_cl_1.commits.append(
        cl_info.Commit('r1p1', '007c0de', [], self.timestamp + hours(3)))
    revert1 = cl_info.Revert(self.patchset_id, revert_cl_1, '*****@*****.**',
                             self.timestamp + hours(3))
    cl.reverts.append(revert1)
    self.assertEqual(
        '007c0de',
        cl.GetRevertCLsByRevision(self.revision)[0]
        .reverting_cl.commits[0].revision)
    self.assertEqual([], cl.GetRevertCLsByRevision('ef1234'))
    self.assertIsNone(cl.GetRevertCLsByRevision('deadc0de'))
Beispiel #3
0
 def GetClDetails(self,
                  change_id,
                  _unused_project=None,
                  _unused_branch=None,
                  _additional_fields=None):
     params = {'messages': 'true'}
     url = 'https://%s/api/%s' % (self._server_hostname, change_id)
     status_code, content, _response_headers = self.HTTP_CLIENT.Get(
         url, params=params)
     if status_code == 200:  # pragma: no branch
         return self._ParseClInfo(
             json.loads(content),
             cl_info.ClInfo(self._server_hostname, change_id))
     return None  # pragma: no cover
Beispiel #4
0
 def testRevertWithBareCl(self):
   cl = cl_info.ClInfo(self.server, self.change_id)
   revert = cl_info.Revert(self.patchset_id, cl, self.email, self.timestamp)
   self.assertEqual({
       'patchset_id': self.patchset_id,
       'reverting_user_email': self.email,
       'timestamp': self.formatted_ts,
       'reverting_cl': {
           'auto_revert_off': False,
           'cc': [],
           'change_id': '20002000',
           'closed': None,
           'commit_attempts': [],
           'commits': [],
           'description': None,
           'owner_email': None,
           'reverts': [],
           'reviewers': [],
           'server_hostname': 'codereview.chromium.org',
           'subject': None,
           'revert_of': None,
           'patchsets': {}
       }
   }, revert.serialize())
import webapp2

from common import constants
from handlers import check_reverted_cls
from infra_api_clients.codereview import cl_info
from infra_api_clients.codereview import codereview_util
from infra_api_clients.codereview.gerrit import Gerrit
from libs import time_util
from model import revert_cl_status
from model.base_suspected_cl import RevertCL
from model.wf_suspected_cl import WfSuspectedCL
from services import git
from waterfall.test import wf_testcase

_MOCKED_FINDIT_REVERTING_CL = cl_info.ClInfo('codereview.chromium.org', '456')
_MOCKED_FINDIT_REVERTING_CL.commits = [
    cl_info.Commit('1001', 'e5f6a7b8', [], datetime(2017, 3, 15, 1, 10))
]
_MOCKED_FINDIT_REVERTING_CL.commit_attempts = {
    '1001':
    cl_info.CommitAttempt('1001', '*****@*****.**',
                          datetime(2017, 3, 15, 0, 7)),
}
_MOCKED_FINDIT_REVERTED_CL_INFO = cl_info.ClInfo('codereview.chromium.org',
                                                 '123')
_MOCKED_FINDIT_REVERTED_CL_INFO.commits = [
    cl_info.Commit('1000', 'a1b2c3d4', [], 1)
]
_MOCKED_FINDIT_REVERTED_CL_INFO.reverts = [
    cl_info.Revert('1000', _MOCKED_FINDIT_REVERTING_CL,
Beispiel #6
0
  def _ParseClInfo(self, change_info, change_id):
    if not change_info:  # pragma: no cover
      return None
    result = cl_info.ClInfo(self._server_hostname, change_id)

    result.reviewers = [
        x['email']
        for x in change_info.get('reviewers', {}).get('REVIEWER', [])
    ]
    result.cc = [
        x['email'] for x in change_info.get('reviewers', {}).get('CC', [])
    ]
    result.closed = change_info['status'] == 'MERGED'
    result.owner_email = change_info['owner'].get('email')
    result.subject = change_info['subject']
    result.revert_of = change_info.get('revert_of')

    # If the status is merged, look at the commit details for the current
    # commit.
    if result.closed:  # pragma: no branch
      current_revision = change_info['current_revision']
      revision_info = change_info['revisions'][current_revision]
      patchset_id = revision_info['_number']
      commit_timestamp = time_util.DatetimeFromString(change_info['submitted'])
      revision_commit = revision_info['commit']
      parent_revisions = [c['commit'] for c in revision_commit['parents']
                         ] if revision_commit else []
      result.commits.append(
          cl_info.Commit(patchset_id, current_revision, parent_revisions,
                         commit_timestamp))

      # Detect manual commits.
      committer = revision_commit['committer']['email']
      if committer not in self.commit_bot_emails:
        result.AddCqAttempt(patchset_id, committer, commit_timestamp)

      result.description = revision_commit['message']

      # Checks for if the culprit owner has turned off auto revert.
      result.auto_revert_off = codereview.IsAutoRevertOff(result.description)

    # Saves information for each patch set.
    for revision, revision_info in change_info['revisions'].iteritems():
      patchset_id = revision_info['_number']
      commit_info = revision_info.get('commit') or {}
      parent_revisions = [c['commit'] for c in commit_info['parents']
                         ] if commit_info else []
      result.patchsets[revision] = cl_info.PatchSet(patchset_id, revision,
                                                    parent_revisions)

    # TO FIND COMMIT ATTEMPTS:
    # In messages look for "Patch Set 1: Commit-Queue+2"
    # or "Patch Set 4: Code-Review+1 Commit-Queue+2".
    cq_pattern = re.compile('^Patch Set \d+:( Code-Review..)? Commit-Queue\+2$')
    revert_tag = 'autogenerated:gerrit:revert'
    revert_pattern = re.compile(
        'Created a revert of this change as (?P<change_id>I[a-f\d]{40})')

    for message in change_info.get('messages', []):
      if cq_pattern.match(message['message'].splitlines()[0]):
        patchset_id = message['_revision_number']
        author = message['author']['email']
        timestamp = time_util.DatetimeFromString(message['date'])
        result.AddCqAttempt(patchset_id, author, timestamp)

      # TO FIND REVERT(S):
      if message.get('tag') == revert_tag:
        patchset_id = message['_revision_number']
        author = message['author']['email']
        timestamp = time_util.DatetimeFromString(message['date'])
        reverting_change_id = revert_pattern.match(
            message['message']).group('change_id')
        reverting_cl = self.GetClDetails(reverting_change_id)
        result.reverts.append(
            cl_info.Revert(patchset_id, reverting_cl, author, timestamp))
    return result