]> git.ipfire.org Git - pbs.git/commitdiff
sources: Refactor Commit class
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 14 Jun 2023 08:52:08 +0000 (08:52 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 14 Jun 2023 08:52:08 +0000 (08:52 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/sources.py
src/buildservice/users.py

index c76175891804e91748407173e2a5027b2a05e271..3e25219fe7569355c550e4b30e0ee19244ca06e1 100644 (file)
@@ -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
 
index 8a8b34b31de0eb8351a20252c87873b6b529a7f3..c047da8f3ffc220639a715ab7af5c6dd16e219ba 100644 (file)
@@ -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: