{"id":18045,"url":"https://patchwork.libcamera.org/api/patches/18045/?format=json","web_url":"https://patchwork.libcamera.org/patch/18045/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20221221220005.1374-1-laurent.pinchart@ideasonboard.com>","date":"2022-12-21T22:00:05","name":"[libcamera-devel] utils: checkstyle.py: Add commit title checker","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"b6453352aea83a8a041434b6830ccfd90492a226","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/18045/mbox/","series":[{"id":3684,"url":"https://patchwork.libcamera.org/api/series/3684/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=3684","date":"2022-12-21T22:00:05","name":"[libcamera-devel] utils: checkstyle.py: Add commit title checker","version":1,"mbox":"https://patchwork.libcamera.org/series/3684/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/18045/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/18045/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CA54FC3213\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Dec 2022 22:00:12 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0DB56633B2;\n\tWed, 21 Dec 2022 23:00:12 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CF5A161F15\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Dec 2022 23:00:10 +0100 (CET)","from pendragon.ideasonboard.com (213-243-189-158.bb.dnainternet.fi\n\t[213.243.189.158])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 3373BFB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Dec 2022 23:00:10 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1671660012;\n\tbh=0d8Jj3e2ZI94UvyNzHB16Edn84EzgD5w5qGh25RYVTs=;\n\th=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post:\n\tList-Help:List-Subscribe:From:Reply-To:From;\n\tb=VPP9j8Z5gvkWh7Z1sjZqkSi8pAOUb2DPgiWGN/j/4ABiDNChRAAKmBm/LrSwq/D8n\n\tr+lMTYqFu7kV8Se7drz+B0RyJRBtkQxqHUfxAKPn5ROEq7PkRo8d5mgxK1ZeSYoEss\n\t/Wd1Nioc8e0BSRsJWmXC3NDkGNGty0LDwi8xpGfA6jmt6W1+22P2sExlmbd9eFa92S\n\tBBVaZ+PvsR1GOS6yIzotn9K464E1Wc8V95Lgc2mLhfj5/ZBHAlr/vC5T1yBkm/oDpS\n\tcyzX+raeWIOeqKgUj3C8fkXP5gHZ9vGwoXiETkbFp3WwOVOUIjLCy9jfjfzb0qHJTi\n\t+vEFytE1Uc8kQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1671660010;\n\tbh=0d8Jj3e2ZI94UvyNzHB16Edn84EzgD5w5qGh25RYVTs=;\n\th=From:To:Subject:Date:From;\n\tb=vo5lpAWrvx2Shr28b++YTLWwEMPjjIZNiCEB6xL98cbrmFUHBkX7y6ke6fJL1QTYQ\n\tJqjp5sklsGz99ks9yC1mS1H0rj4thRuIVVgD4tzqzE7rdMsbnT/PyVJSCUFE2aQzeN\n\tr6OO8OYP0F7jyjl58/wUormoDjOONxNLDDVn1CcQ="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"vo5lpAWr\"; dkim-atps=neutral","To":"libcamera-devel@lists.libcamera.org","Date":"Thu, 22 Dec 2022 00:00:05 +0200","Message-Id":"<20221221220005.1374-1-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.38.2","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH] utils: checkstyle.py: Add commit title\n\tchecker","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Add a commit checker to ensure that commit titles start with a prefix.\nThe commit issue message lists prefix candidates retrieved from the git\nlog.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n utils/checkstyle.py | 63 +++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 63 insertions(+)\n\n\nbase-commit: f66a5c447b65bce774a1bc2d01034f437bf764b5","diff":"diff --git a/utils/checkstyle.py b/utils/checkstyle.py\nindex a11d95cc5808..c40b79dd46fc 100755\n--- a/utils/checkstyle.py\n+++ b/utils/checkstyle.py\n@@ -352,6 +352,69 @@ class HeaderAddChecker(CommitChecker):\n         return issues\n \n \n+class TitleChecker(CommitChecker):\n+    prefix_regex = re.compile(r'[0-9a-f]+ (([a-zA-Z0-9_.-]+: )+)')\n+    release_regex = re.compile(r'libcamera v[0-9]+\\.[0-9]+\\.[0-9]+')\n+\n+    @classmethod\n+    def check(cls, commit, top_level):\n+        issues = []\n+\n+        title = commit.title\n+        if not TitleChecker.release_regex.fullmatch(title):\n+            prefix_pos = title.find(': ')\n+            if prefix_pos == -1 or prefix_pos == len(title) - 2:\n+                # Find prefix candidates by searching the git history\n+                msgs = subprocess.run(['git', 'log', '--no-decorate', '--oneline', '-n100', '--'] + commit.files(),\n+                                      stdout=subprocess.PIPE).stdout.decode('utf-8')\n+                prefixes = {}\n+                prefixes_count = 0\n+                for msg in msgs.splitlines():\n+                    prefix = TitleChecker.prefix_regex.match(msg)\n+                    if not prefix:\n+                        continue\n+\n+                    prefix = prefix.group(1)\n+                    if prefix in prefixes:\n+                        prefixes[prefix] += 1\n+                    else:\n+                        prefixes[prefix] = 1\n+\n+                    prefixes_count += 1\n+\n+                if prefixes:\n+                    # Sort the candidates by number of occurrences and pick the\n+                    # best ones. When multiple prefixes are possible without a\n+                    # clear winner, we want to display the most common options\n+                    # to the user, but without the most unlikely options to\n+                    # avoid too long messages. As a heuristic, select enough\n+                    # candidates to cover at least 2/3 of the possible\n+                    # prefixes, but never more than 4 candidates.\n+                    prefixes = list(prefixes.items())\n+                    prefixes.sort(key=lambda x: x[1], reverse=True)\n+\n+                    candidates = []\n+                    candidates_count = 0\n+                    for prefix in prefixes:\n+                        candidates.append(f\"`{prefix[0]}'\")\n+                        candidates_count += prefix[1]\n+                        if candidates_count >= prefixes_count * 2 / 3 or \\\n+                           len(candidates) == 4:\n+                            break\n+\n+                    candidates = candidates[:-2] + [' and '.join(candidates[-2:])]\n+                    candidates = ', '.join(candidates)\n+\n+                    issue = CommitIssue('Commit title is missing prefix, '\n+                                        'possible candidates are ' + candidates)\n+                else:\n+                    issue = CommitIssue('Commit title is missing prefix')\n+\n+                issues.append(issue)\n+\n+        return issues\n+\n+\n # ------------------------------------------------------------------------------\n # Style Checkers\n #\n","prefixes":["libcamera-devel"]}