Source code for estuary_updater.handlers.distgit

# SPDX-License-Identifier: GPL-3.0+

from __future__ import unicode_literals, absolute_import

import re

from estuary.models.distgit import DistGitRepo, DistGitCommit
from estuary.models.bugzilla import BugzillaBug
from estuary.models.user import User
from estuary.utils.general import timestamp_to_datetime

from estuary_updater.handlers.base import BaseHandler


[docs]class DistGitHandler(BaseHandler): """A handler for dist-git related messages."""
[docs] @staticmethod def can_handle(msg): """ Determine if this is a dist-git message. :param dict msg: a message to be analyzed :return: a bool based on if the handler can handle this kind of message :rtype: bool """ supported_topics = [ '/topic/VirtualTopic.eng.distgit.commit' ] return msg['topic'] in supported_topics
[docs] def handle(self, msg): """ Handle a dist-git message by sending it to the right handler method and update Neo4j. :param dict msg: a message to be processed """ if msg['topic'] == '/topic/VirtualTopic.eng.distgit.commit': self.commit_handler(msg) else: raise RuntimeError('This message is unable to be handled: {0}'.format(msg))
[docs] def commit_handler(self, msg): """ Handle a dist-git commit message and update Neo4j if necessary. :param dict msg: a message to be processed """ repo = DistGitRepo.get_or_create({ 'namespace': msg['headers']['namespace'], 'name': msg['headers']['repo'] })[0] # Get the username from the email if the email is a Red Hat email email = msg['headers']['email'].lower() if email.endswith('@redhat.com'): username = email.split('@redhat.com')[0] else: username = email author = User.create_or_update({ 'username': username, 'email': email })[0] commit_message = msg['body']['msg']['message'] commit = DistGitCommit.create_or_update({ 'hash_': msg['headers']['rev'], 'log_message': commit_message, 'author_date': timestamp_to_datetime(msg['body']['msg']['author_date']), 'commit_date': timestamp_to_datetime(msg['body']['msg']['commit_date']) })[0] bug_rel_mapping = self.parse_bugzilla_bugs(commit_message) for bug_id in bug_rel_mapping['resolves']: bug = BugzillaBug.get_or_create({ 'id_': bug_id })[0] commit.resolved_bugs.connect(bug) for bug_id in bug_rel_mapping['related']: bug = BugzillaBug.get_or_create({ 'id_': bug_id })[0] commit.related_bugs.connect(bug) for bug_id in bug_rel_mapping['reverted']: bug = BugzillaBug.get_or_create({ 'id_': bug_id })[0] commit.reverted_bugs.connect(bug) commit.conditional_connect(commit.author, author) repo.commits.connect(commit)
[docs] @staticmethod def parse_bugzilla_bugs(commit_message): """ Parse the Bugzilla bugs mentioned in a a dist-git commit message. :param str commit_message: the dist-git commit message :rtype: dict :return: a dictionary with the keys resolves, related, reverted with values as lists of Bugzilla IDs """ # Look for 'Resolves', 'Related', or 'Reverts' action Bugzilla bugs bugzilla_bug_pattern = re.compile( r'^(?:(reverted|resolves|related)\: *(.+))', re.IGNORECASE | re.MULTILINE) matches = re.findall(bugzilla_bug_pattern, commit_message) # Pull out the bug id numbers without their prefixes or whitespace bug_ids_pattern = re.compile(r'(?:(?:bug|bz|rhbz)\s*#?|#)\s*(\d+)', re.IGNORECASE) bug_rel_mapping = { 'resolves': [], 'related': [], 'reverted': [] } # Populate values of bug relationship type keys to their corresponding bug IDs for match in matches: rel_type = match[0].lower() bug_rel_mapping[rel_type] += list(re.findall(bug_ids_pattern, match[1])) return bug_rel_mapping