[{"id":30721,"web_url":"https://patchwork.libcamera.org/comment/30721/","msgid":"<87ikw6w87q.fsf@redhat.com>","date":"2024-08-12T06:44:57","subject":"Re: [PATCH 1/3] utils: checkstyle.py: Rework commit message parsing","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Laurent,\n\nthank you for the improvement.\n\nLaurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n\n> When parsing commit messages, the Commit class tries to optimize the\n> process by invoking git-show once only, extracting both the commit\n> author, title and modified files in one go. As a result, the derived\n> Amendment class needs to implement the commit parsing separately, as the\n> modified files need to be extracted differently for amendments (and the\n> commit ID also needs to be retrieved differently). Furthermore, because\n> of the list of named files, extracting the trailers needs to invoke\n> git-show separately.\n>\n> Improve the situation by reworking the commit message parsing in three\n> steps. In the first step, use git-show to extract the commit ID, author,\n> title and body. In the second step, invoke git-interpret-trailers to\n> extract the trailers from the body that was previously extracted. The\n> third and final step extracts the list of modified files, using\n> different methods for regular commits and amendments.\n>\n> This allows sharing code for the first two steps between the Commit and\n> Amendment classes, making the code simpler. The Commit class still\n> invokes git three times, while the Amendment class runs it three times\n> instead of four, improving performance slightly.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Milan Zamazal <mzamazal@redhat.com>\n\n> ---\n>  utils/checkstyle.py | 60 +++++++++++++++++++++++++--------------------\n>  1 file changed, 33 insertions(+), 27 deletions(-)\n>\n> diff --git a/utils/checkstyle.py b/utils/checkstyle.py\n> index dae5d518920a..aa0731abdb5a 100755\n> --- a/utils/checkstyle.py\n> +++ b/utils/checkstyle.py\n> @@ -211,33 +211,42 @@ class CommitFile:\n>  \n>  class Commit:\n>      def __init__(self, commit):\n> -        self.commit = commit\n> +        self._commit = commit\n>          self._author = None\n>          self._trailers = []\n>          self._parse()\n>  \n> -    def _parse_trailers(self):\n> -        proc_show = subprocess.run(['git', 'show', '--format=%b',\n> -                                    '--no-patch', self.commit],\n> -                                   stdout=subprocess.PIPE)\n> +    def _parse_commit(self):\n> +        # Get and parse the commit message.\n> +        ret = subprocess.run(['git', 'show', '--format=%H%n%an <%ae>%n%s%n%b',\n> +                              '--no-patch', self.commit],\n> +                             stdout=subprocess.PIPE).stdout.decode('utf-8')\n> +        lines = ret.splitlines()\n> +\n> +        self._commit = lines[0]\n> +        self._author = lines[1]\n> +        self._title = lines[2]\n> +        self._body = lines[3:]\n> +\n> +        # Parse the trailers. Feed git-interpret-trailers with a full commit\n> +        # message that includes both the title and the body, as it otherwise\n> +        # fails to find trailers when the body contains trailers only.\n> +        message = self._title + '\\n\\n' + '\\n'.join(self._body)\n>          trailers = subprocess.run(['git', 'interpret-trailers', '--parse'],\n> -                                  input=proc_show.stdout,\n> +                                  input=message.encode('utf-8'),\n>                                    stdout=subprocess.PIPE).stdout.decode('utf-8')\n>  \n>          self._trailers = trailers.splitlines()\n>  \n>      def _parse(self):\n> -        # Get the commit title and list of files.\n> -        ret = subprocess.run(['git', 'show', '--format=%an <%ae>%n%s',\n> -                              '--name-status', self.commit],\n> +        self._parse_commit()\n> +\n> +        # Get the list of files. Use an empty format specifier to suppress the\n> +        # commit message completely.\n> +        ret = subprocess.run(['git', 'show', '--format=', '--name-status',\n> +                              self.commit],\n>                               stdout=subprocess.PIPE).stdout.decode('utf-8')\n> -        lines = ret.splitlines()\n> -\n> -        self._author = lines[0]\n> -        self._title = lines[1]\n> -        self._files = [CommitFile(f) for f in lines[2:] if f]\n> -\n> -        self._parse_trailers()\n> +        self._files = [CommitFile(f) for f in ret.splitlines()]\n>  \n>      def files(self, filter='AMR'):\n>          return [f.filename for f in self._files if f.status in filter]\n> @@ -246,6 +255,10 @@ class Commit:\n>      def author(self):\n>          return self._author\n>  \n> +    @property\n> +    def commit(self):\n> +        return self._commit\n> +\n>      @property\n>      def title(self):\n>          return self._title\n> @@ -284,21 +297,14 @@ class StagedChanges(Commit):\n>  \n>  class Amendment(Commit):\n>      def __init__(self):\n> -        Commit.__init__(self, '')\n> +        Commit.__init__(self, 'HEAD')\n>  \n>      def _parse(self):\n> -        # Create a title using HEAD commit and parse the trailers.\n> -        ret = subprocess.run(['git', 'show', '--format=%an <%ae>%n%H %s',\n> -                             '--no-patch'],\n> -                             stdout=subprocess.PIPE).stdout.decode('utf-8')\n> -        lines = ret.splitlines()\n> +        self._parse_commit()\n>  \n> -        self._author = lines[0]\n> -        self._title = 'Amendment of ' + lines[1]\n> +        self._title = f'Amendment of \"{self.title}\"'\n>  \n> -        self._parse_trailers()\n> -\n> -        # Extract the list of modified files\n> +        # Extract the list of modified files.\n>          ret = subprocess.run(['git', 'diff', '--staged', '--name-status', 'HEAD~'],\n>                               stdout=subprocess.PIPE).stdout.decode('utf-8')\n>          self._files = [CommitFile(f) for f in ret.splitlines()]\n>\n> base-commit: 62760bd2605a83e663b9003244ff42f8946f8955","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 83C48C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 12 Aug 2024 06:45:08 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2526B633B5;\n\tMon, 12 Aug 2024 08:45:07 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4BF776338D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 12 Aug 2024 08:45:04 +0200 (CEST)","from mail-ed1-f70.google.com (mail-ed1-f70.google.com\n\t[209.85.208.70]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-646-uGz8J0YPOxe4Mf-9-xI8vg-1; Mon, 12 Aug 2024 02:45:01 -0400","by mail-ed1-f70.google.com with SMTP id\n\t4fb4d7f45d1cf-5a74845546bso3423962a12.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 11 Aug 2024 23:45:00 -0700 (PDT)","from nuthatch (ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\t4fb4d7f45d1cf-5bd191a20fcsm2020481a12.36.2024.08.11.23.44.57\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSun, 11 Aug 2024 23:44:58 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"Pv8y7j+3\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1723445103;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=oOjPxRxEv+JJ+w1nH92Craf5xJD/6890Q2PsQhSiD0Y=;\n\tb=Pv8y7j+3Dpo+1ZEDEwvi17iASimSXdIEMY7jopd/o+6eWfQiCx2YsrmB//jGh1oCYPeVqH\n\t/LikRSJ1AAKKoOZ7dYS4gScSgXJp9mRA8K30m8dbPx6U8ORUFf8W33+KMHZWvUpfPRwiUY\n\tj4Ule5cfipVF/RhrDiEKMzYwcQagzUs=","X-MC-Unique":"uGz8J0YPOxe4Mf-9-xI8vg-1","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1723445099; x=1724049899;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=oOjPxRxEv+JJ+w1nH92Craf5xJD/6890Q2PsQhSiD0Y=;\n\tb=jVneZQ3bvV+6r8Q32P8KDDo+1n1J2z+WdvZS0KKSjYrYC0mc+LpAb0Yu7ipZttTpyz\n\t9PQzChdk3IsIxrxmL3uCVCrxRo9ZPUQ5O8g8eWFbR6Ze4JlJzz3YPhMicPyhpqQ0MhCE\n\t048Gn/0rQlxJOR0fIDIS4tzQGKGM7HZgWtJtRsVcD11Opp5eF77qLbnhaZphE9YrS5oq\n\tFxMmGVYQJog7MMgVwJecFVuNio3SHisj52GNX8jyXescHcqWL3bO9D0SOANAMZ+8pFeU\n\tF+z2X56QZPPJqj2+bdpL1Ru8gnHyNRu7xn4L15XqJwmc+D5RNX2AGO/wLjuGoLBLFQMV\n\tKwHQ==","X-Gm-Message-State":"AOJu0YyhpLeJhkaBg/gqnKWy9pgzs8pqVyH1Kw9DgK/z0DEFef7f/3Z3\n\tGtIPCZqFcEVJfXZjUFG8ffmj4MRMWqEG7ZNu5v3jadHb6DE2+Yjfv78Lnd2hGUxIVZtjF7Zym3I\n\tORgaXXUm5pkoPM0cc8hmGFYE2ekJ2o66D1hLfJfo+d8VlhOsnR4O5mg1oaT+niZUKg07SzWlu7y\n\tEg3HO8W5bb5bJVRTZLbvjif4oBYQoFfN2f280A4X5gTMRlRbRDV/0i2jM=","X-Received":["by 2002:a05:6402:2111:b0:5a1:f680:5470 with SMTP id\n\t4fb4d7f45d1cf-5bd0a570796mr6924103a12.13.1723445099442; \n\tSun, 11 Aug 2024 23:44:59 -0700 (PDT)","by 2002:a05:6402:2111:b0:5a1:f680:5470 with SMTP id\n\t4fb4d7f45d1cf-5bd0a570796mr6924078a12.13.1723445098831; \n\tSun, 11 Aug 2024 23:44:58 -0700 (PDT)"],"X-Google-Smtp-Source":"AGHT+IGXtMGlc7o/8ZDVZSqUQTt9d5uFsBojVxPWIZxfidISPjNopSN725LeCqcKrcJoZMWVxQTmpQ==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 1/3] utils: checkstyle.py: Rework commit message parsing","In-Reply-To":"<20240810005840.20841-1-laurent.pinchart@ideasonboard.com>\n\t(Laurent Pinchart's message of \"Sat, 10 Aug 2024 03:58:38 +0300\")","References":"<20240810005840.20841-1-laurent.pinchart@ideasonboard.com>","Date":"Mon, 12 Aug 2024 08:44:57 +0200","Message-ID":"<87ikw6w87q.fsf@redhat.com>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":30742,"web_url":"https://patchwork.libcamera.org/comment/30742/","msgid":"<2b0d7948-e475-4e0b-b214-712eb58b694c@ideasonboard.com>","date":"2024-08-12T12:42:03","subject":"Re: [PATCH 1/3] utils: checkstyle.py: Rework commit message parsing","submitter":{"id":156,"url":"https://patchwork.libcamera.org/api/people/156/","name":"Dan Scally","email":"dan.scally@ideasonboard.com"},"content":"Hi Laurent\n\nOn 10/08/2024 01:58, Laurent Pinchart wrote:\n> When parsing commit messages, the Commit class tries to optimize the\n> process by invoking git-show once only, extracting both the commit\n> author, title and modified files in one go. As a result, the derived\n> Amendment class needs to implement the commit parsing separately, as the\n> modified files need to be extracted differently for amendments (and the\n> commit ID also needs to be retrieved differently). Furthermore, because\n> of the list of named files, extracting the trailers needs to invoke\n> git-show separately.\n>\n> Improve the situation by reworking the commit message parsing in three\n> steps. In the first step, use git-show to extract the commit ID, author,\n> title and body. In the second step, invoke git-interpret-trailers to\n> extract the trailers from the body that was previously extracted. The\n> third and final step extracts the list of modified files, using\n> different methods for regular commits and amendments.\n>\n> This allows sharing code for the first two steps between the Commit and\n> Amendment classes, making the code simpler. The Commit class still\n> invokes git three times, while the Amendment class runs it three times\n> instead of four, improving performance slightly.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n\n\nReviewed-by: Daniel Scally <dan.scally@ideasonboard.com>\n\n>   utils/checkstyle.py | 60 +++++++++++++++++++++++++--------------------\n>   1 file changed, 33 insertions(+), 27 deletions(-)\n>\n> diff --git a/utils/checkstyle.py b/utils/checkstyle.py\n> index dae5d518920a..aa0731abdb5a 100755\n> --- a/utils/checkstyle.py\n> +++ b/utils/checkstyle.py\n> @@ -211,33 +211,42 @@ class CommitFile:\n>   \n>   class Commit:\n>       def __init__(self, commit):\n> -        self.commit = commit\n> +        self._commit = commit\n>           self._author = None\n>           self._trailers = []\n>           self._parse()\n>   \n> -    def _parse_trailers(self):\n> -        proc_show = subprocess.run(['git', 'show', '--format=%b',\n> -                                    '--no-patch', self.commit],\n> -                                   stdout=subprocess.PIPE)\n> +    def _parse_commit(self):\n> +        # Get and parse the commit message.\n> +        ret = subprocess.run(['git', 'show', '--format=%H%n%an <%ae>%n%s%n%b',\n> +                              '--no-patch', self.commit],\nI should read the whole commit when I get confused; it took me way too long to spot that this now \nreferences the property.\n> +                             stdout=subprocess.PIPE).stdout.decode('utf-8')\n> +        lines = ret.splitlines()\n> +\n> +        self._commit = lines[0]\n> +        self._author = lines[1]\n> +        self._title = lines[2]\n> +        self._body = lines[3:]\n> +\n> +        # Parse the trailers. Feed git-interpret-trailers with a full commit\n> +        # message that includes both the title and the body, as it otherwise\n> +        # fails to find trailers when the body contains trailers only.\n> +        message = self._title + '\\n\\n' + '\\n'.join(self._body)\n>           trailers = subprocess.run(['git', 'interpret-trailers', '--parse'],\n> -                                  input=proc_show.stdout,\n> +                                  input=message.encode('utf-8'),\n>                                     stdout=subprocess.PIPE).stdout.decode('utf-8')\n>   \n>           self._trailers = trailers.splitlines()\n>   \n>       def _parse(self):\n> -        # Get the commit title and list of files.\n> -        ret = subprocess.run(['git', 'show', '--format=%an <%ae>%n%s',\n> -                              '--name-status', self.commit],\n> +        self._parse_commit()\n> +\n> +        # Get the list of files. Use an empty format specifier to suppress the\n> +        # commit message completely.\n> +        ret = subprocess.run(['git', 'show', '--format=', '--name-status',\n> +                              self.commit],\n>                                stdout=subprocess.PIPE).stdout.decode('utf-8')\n> -        lines = ret.splitlines()\n> -\n> -        self._author = lines[0]\n> -        self._title = lines[1]\n> -        self._files = [CommitFile(f) for f in lines[2:] if f]\n> -\n> -        self._parse_trailers()\n> +        self._files = [CommitFile(f) for f in ret.splitlines()]\n>   \n>       def files(self, filter='AMR'):\n>           return [f.filename for f in self._files if f.status in filter]\n> @@ -246,6 +255,10 @@ class Commit:\n>       def author(self):\n>           return self._author\n>   \n> +    @property\n> +    def commit(self):\n> +        return self._commit\n> +\n>       @property\n>       def title(self):\n>           return self._title\n> @@ -284,21 +297,14 @@ class StagedChanges(Commit):\n>   \n>   class Amendment(Commit):\n>       def __init__(self):\n> -        Commit.__init__(self, '')\n> +        Commit.__init__(self, 'HEAD')\n>   \n>       def _parse(self):\n> -        # Create a title using HEAD commit and parse the trailers.\n> -        ret = subprocess.run(['git', 'show', '--format=%an <%ae>%n%H %s',\n> -                             '--no-patch'],\n> -                             stdout=subprocess.PIPE).stdout.decode('utf-8')\n> -        lines = ret.splitlines()\n> +        self._parse_commit()\n>   \n> -        self._author = lines[0]\n> -        self._title = 'Amendment of ' + lines[1]\n> +        self._title = f'Amendment of \"{self.title}\"'\n>   \n> -        self._parse_trailers()\n> -\n> -        # Extract the list of modified files\n> +        # Extract the list of modified files.\n>           ret = subprocess.run(['git', 'diff', '--staged', '--name-status', 'HEAD~'],\n>                                stdout=subprocess.PIPE).stdout.decode('utf-8')\n>           self._files = [CommitFile(f) for f in ret.splitlines()]\n>\n> base-commit: 62760bd2605a83e663b9003244ff42f8946f8955","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 ADB31BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 12 Aug 2024 12:42:08 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AEB4F633BA;\n\tMon, 12 Aug 2024 14:42:07 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 86E86633B3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 12 Aug 2024 14:42:06 +0200 (CEST)","from [192.168.0.43]\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 23B966B5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 12 Aug 2024 14:41:10 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"Of36Ht9N\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1723466470;\n\tbh=ZfphiyHlDsha4UDNNz7jOsW+zNJBuIRmW4bboPoFJ8U=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=Of36Ht9NP2wdVPUZxVqqaUp7+Mj/OYe7wuyGv8owTtbU157A5y+1ceprxEjYmCe8H\n\tfQDeaV3GGvzo5VCPR/H+WnOKMRkqI8cYR9ONIVpYGcWFQZF4KJPCc1KBxukhs6+lb5\n\t1BSYbekVhd6xmvN48hXBamTlydXbO9/zEDqGHbQg=","Message-ID":"<2b0d7948-e475-4e0b-b214-712eb58b694c@ideasonboard.com>","Date":"Mon, 12 Aug 2024 13:42:03 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 1/3] utils: checkstyle.py: Rework commit message parsing","To":"libcamera-devel@lists.libcamera.org","References":"<20240810005840.20841-1-laurent.pinchart@ideasonboard.com>","Content-Language":"en-US","From":"Dan Scally <dan.scally@ideasonboard.com>","Autocrypt":"addr=dan.scally@ideasonboard.com; keydata=\n\t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","In-Reply-To":"<20240810005840.20841-1-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]