From: Michael Tremer Date: Wed, 14 Jun 2023 08:52:08 +0000 (+0000) Subject: sources: Refactor Commit class X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ffd6438e873802b26ac3ec42f6697dcab6a39c01;p=pbs.git sources: Refactor Commit class Signed-off-by: Michael Tremer --- diff --git a/src/buildservice/sources.py b/src/buildservice/sources.py index c7617589..3e25219f 100644 --- a/src/buildservice/sources.py +++ b/src/buildservice/sources.py @@ -436,7 +436,7 @@ class Commit(base.DataObject): table = "source_commits" def __str__(self): - return "%s - %s" % (self.revision[:8], self.subject) + return self.subject or self.revision # Revision @@ -478,112 +478,117 @@ class Commit(base.DataObject): @property def body(self): - return self.data.body.strip() + return self.data.body @lazy_property def message(self): """ - Returns the message without any Git tags + Returns the message without Git tags """ - # Compile regex - r = re.compile("^(%s):?" % "|".join(VALID_TAGS), re.IGNORECASE) + lines = [] - message = [] + # Remove any Git tags for line in self.body.splitlines(): - # Find lines that start with a known Git tag - if r.match(line): + m = re.match(r"^[A-Za-z\-]+:", line) + if m: continue - message.append(line) + lines.append(line) - # If all lines are empty lines, we send back an empty message - if all((l == "" for l in message)): - return + # Join the message back together again + message = "\n".join(lines) - # We will now break the message into paragraphs - paragraphs = re.split("\n\n+", "\n".join(message)) + # Remove excess whitespace + message = message.strip() - message = [] - for paragraph in paragraphs: - # Remove all line breaks that are not following a colon - # and where the next line does not start with a star. - paragraph = re.sub("(?<=\:)\n(?=[\*\s])", " ", paragraph) + return message - message.append(paragraph) + @lazy_property + def tags(self): + tags = {} - return "\n\n".join(message) + # For Fixes:, we only want to extract the bug ID + results = re.findall(r""" + # Lines must start with Fixes: + ^Fixes: - @property - def message_full(self): - message = self.subject + # Consume any extra whitespace + \s* - if self.message: - message += "\n\n%s" % self.message + # There might be a leading # for the ID + \#? - return message + # The ID + ([0-9]+) + """, self.body, re.IGNORECASE|re.MULTILINE|re.VERBOSE) - def get_tag(self, tag): - """ - Returns a list of the values of this Git tag - """ - if not tag in VALID_TAGS: - raise ValueError("Unknown tag: %s" % tag) - - # Compile regex - r = re.compile(r"^%s:? (.*)$" % tag, re.IGNORECASE) + if results: + tags["Fixes"] = results - values = [] - for line in self.body.splitlines(): - # Skip all empty lines - if not line: - continue + # Match anything else + results = re.findall(r""" + # The tag must start at the beginning of the line + # only containing letters and hyphens followed by colon + ^((?!Fixes)[A-Za-z\-]+): - # Check if line matches the regex - m = r.match(line) - if m: - values.append(m.group(1)) + # Consume any extra whitespace + \s* - return values + # Consume the rest of the line in a non-greedy fashion + (.*?) - @lazy_property - def contributors(self): - contributors = [ - self.data.author, - self.data.committer, - ] + # Ignore any trailing whitespace + \s* - for tag in ("Acked-by", "Cc", "Reported-by", "Reviewed-by", "Signed-off-by", "Suggested-by", "Tested-by"): - contributors += self.get_tag(tag) + # We must have read the entire line + $ + """, self.body, re.IGNORECASE|re.MULTILINE|re.VERBOSE) - # Get all user accounts that we know - users = self.backend.users.find_maintainers(contributors) + # Store all tags + for tag, value in results: + try: + tags[tag].append(value) + except KeyError: + tags[tag] = [value] - # Add all email addresses where a user could not be found - for contributor in contributors[:]: - for user in users: - if user.has_email_address(contributor): - try: - contributors.remove(contributor) - except: - pass + return tags - return sorted(contributors + users) + def get_watchers(self): + """ + Returns a list of all known users involved in this commit + which should be added as watchers to builds. + """ + tags = ( + "Acked-by", + "Cc", + "Reported-by", + "Reviewed-by", + "Signed-off-by", + "Suggested-by", + "Tested-by", + ) - @lazy_property - def testers(self): - users = [] + # Add the author + users = set(( + self.data.author, + )) - for tag in ("Acked-by", "Reviewed-by", "Signed-off-by", "Tested-by"): - users += self.get_tag(tag) + # Add users from tags + for tag in tags: + users.update(self.tags.get(tag, [])) - return self.backend.users.find_maintainers(users) + return self.backend.users._search_by_email(users) - @property - def fixed_bugs(self): + async def get_fixed_bugs(self): """ Returns a list of all fixed bugs """ - return self.get_tag("Fixes") + bug_ids = self.tags.get("Fixes") + + if not bug_ids: + return [] + + return await self.backend.bugzilla.get_bugs(bug_ids) # Builds diff --git a/src/buildservice/users.py b/src/buildservice/users.py index 8a8b34b3..c047da8f 100644 --- a/src/buildservice/users.py +++ b/src/buildservice/users.py @@ -363,6 +363,27 @@ class Users(base.Object): return self.get_by_name(uid) + def _search_by_email(self, mails, include_missing=True): + """ + Takes a list of email addresses and returns all users that could be found + """ + users = [] + + for mail in mails: + user = self.get_by_email(mail) + + # Include the search string if no user could be found + if not user and include_missing: + user = mail + + # Skip any duplicates + if user in users: + continue + + users.append(user) + + return users + def search(self, q, limit=None): # Do nothing in test mode if self.backend.test: