From patchwork Thu Feb 26 20:00:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1941 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772136111; bh=mvrmAw685owT2ktsLCJMYdY5FfNVmymO+0O7h42MW1U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=IYNq2Tba+LkhyXxbk8s3mHXEi+7xM9c/51fscpyCnPP6nkIjbG6FzH5bp+yIYLXBn sF8zLZ8VlIqKpSOZglM3UQoP/+M681UO9gg8oNZog7dGXOYZofleqvcCDJ9mVYBtcq tQ5Teo9Xwy9Uju6N9FmmZcya+uwWICbl7ysiIzJkSADg18T3T6w2JU5gCMAvdHmMFh a87KY1lT/wTXDnM4SuFzk46v1AdkWX9JxgQ8LVtA3TYqrEP3fvVPFdU6ar9xMGu0ea BRPKBLc9NuoYojAO2VetaG8MXRwAQ/OmYCF/dPBdTRSOGc2xL9kLAzB7mKu9Nj4Gb2 v4vOlN4ZTcKbg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 1EB6369E36 for ; Thu, 26 Feb 2026 13:01:51 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id HBhDAxaUDi5g for ; Thu, 26 Feb 2026 13:01:51 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772136111; bh=mvrmAw685owT2ktsLCJMYdY5FfNVmymO+0O7h42MW1U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=IYNq2Tba+LkhyXxbk8s3mHXEi+7xM9c/51fscpyCnPP6nkIjbG6FzH5bp+yIYLXBn sF8zLZ8VlIqKpSOZglM3UQoP/+M681UO9gg8oNZog7dGXOYZofleqvcCDJ9mVYBtcq tQ5Teo9Xwy9Uju6N9FmmZcya+uwWICbl7ysiIzJkSADg18T3T6w2JU5gCMAvdHmMFh a87KY1lT/wTXDnM4SuFzk46v1AdkWX9JxgQ8LVtA3TYqrEP3fvVPFdU6ar9xMGu0ea BRPKBLc9NuoYojAO2VetaG8MXRwAQ/OmYCF/dPBdTRSOGc2xL9kLAzB7mKu9Nj4Gb2 v4vOlN4ZTcKbg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0D55B69D79 for ; Thu, 26 Feb 2026 13:01:51 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772136108; bh=R6OwqiPQ7kXoVGVQ1NrSrO/xvHKmL6hQF38F6v5mIFk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FIuSVwJrBPMQlIegMVJ/Y9cg614Z+iKKvCyhgysJI5MXcMBvANueFv/SePgUkCFYY hJpSMlCDX4n9UGRHQ+i5uajXSpgPq1evWEw8bBslZgg2M/F4nASqKixQqso+QZAZ4p dNSKi9pGCyarPCUAa3dfpu3DEdMT0Af3XojVZuir5kw8vK+eIpQOW4ONqa62gH2+oY jdZHPYpcpscfcVuDs+vq93MoDPDYThNuc2AV+J1kmlBYzM2JOrlIph0sfhggHW25pX E/8zpOpqWLvKfywG1vgN4vqRrPaDKKEWeewqLXSkk1HCQh3yoezt9uxXOisT7xjTop 0MxD6Palu4uCg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A1F7369D79; Thu, 26 Feb 2026 13:01:48 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id lzuqjq9Jj3Lg; Thu, 26 Feb 2026 13:01:48 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772136104; bh=BhnNPAxRAPGrD7HtK3pVBsEc8lEQW1Y+Py66j2IrVpQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=U9r/gcBEzcaArvuEGrs7sBOIJgjosnigc+Vh597wfWNEP7Xb9SbNA0i+szudlVVUf a180pG9oxz2/yLuiwxx7GySwM4A2hvBnIMkCnzmWBduZ+Gy6YYi9TabRtxpb34rCd7 YfYb1zkBj3qe7/80+2IpcBkX2KJfzUNjElZFEOQDBjPjyNLK2jyIkrq3KNntP/RHm5 pwWD1CShX5nYcmQOqkiMbOGSMugon+pR3nANmf1xg6AKWrbA0D12D1PSf2dbXvnzP4 9SHfUWUd+icv6nD823TE0ZeUMkdeZEZS7k9KQjdE3AwYVvR7BK7ES/sbAA1PTOEvUW m7zZJC349nr0g== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 8769969D4A; Thu, 26 Feb 2026 13:01:44 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Thu, 26 Feb 2026 13:00:10 -0700 Message-ID: <20260226200106.1727176-5-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260226200106.1727176-1-sjg@u-boot.org> References: <20260226200106.1727176-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: RL3FHNWFTWJAKSPE3FOE3A7PGDXUTKQE X-Message-ID-Hash: RL3FHNWFTWJAKSPE3FOE3A7PGDXUTKQE X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 04/32] patman: Add an upstream column to the series table List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Series are not currently associated with a particular upstream. Add an 'upstream' column to the series table (schema v5) so each series can record which upstream it targets. This stores the upstream name as a string reference to the upstream table's name column. Add series_set_upstream() for updating an existing series, and extend series_add(), series_get_info() and _get_series_list() to handle the new column. Update Series.from_fields() to require the upstream parameter. Signed-off-by: Simon Glass --- tools/patman/cser_helper.py | 9 +++++---- tools/patman/database.py | 31 +++++++++++++++++++++++-------- tools/patman/series.py | 3 ++- tools/patman/test_cseries.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/tools/patman/cser_helper.py b/tools/patman/cser_helper.py index 4289593b64b..1441904686c 100644 --- a/tools/patman/cser_helper.py +++ b/tools/patman/cser_helper.py @@ -246,6 +246,7 @@ class CseriesHelper: Return: tuple: str: Series name str: Series description + str or None: Upstream name Raises: ValueError: Series is not found @@ -400,9 +401,9 @@ class CseriesHelper: idnum = self.db.series_find_by_name(name, include_archived) if not idnum: return None - name, desc = self.db.series_get_info(idnum) + name, desc, ups = self.db.series_get_info(idnum) - return Series.from_fields(idnum, name, desc) + return Series.from_fields(idnum, name, desc, ups) def _get_branch_name(self, name, version): """Get the branch name for a particular version @@ -1441,7 +1442,7 @@ class CseriesHelper: int: Number of version which need a 'scan' """ max_vers = self._series_max_version(ser.idnum) - name, desc = self._get_series_info(ser.idnum) + name, desc, ups = self._get_series_info(ser.idnum) coloured = self.col.build(self.col.BLACK, desc, bright=False, back=self.col.YELLOW) versions = self._get_version_list(ser.idnum) @@ -1487,7 +1488,7 @@ class CseriesHelper: all series """ max_vers = self._series_max_version(ser.idnum) - name, desc = self._get_series_info(ser.idnum) + name, desc, ups = self._get_series_info(ser.idnum) stats, pwc = self._series_get_version_stats(ser.idnum, max_vers) states = {x.state for x in pwc.values()} state = 'accepted' diff --git a/tools/patman/database.py b/tools/patman/database.py index 2861ca69fa0..e3df4257f8c 100644 --- a/tools/patman/database.py +++ b/tools/patman/database.py @@ -295,10 +295,11 @@ class Database: # pylint:disable=R0904 list of Series """ res = self.execute( - 'SELECT id, name, desc FROM series ' + + 'SELECT id, name, desc, upstream FROM series ' + ('WHERE archived = 0' if not include_archived else '')) - return [Series.from_fields(idnum=idnum, name=name, desc=desc) - for idnum, name, desc in res.fetchall()] + return [Series.from_fields(idnum=idnum, name=name, desc=desc, + ups=ups) + for idnum, name, desc, ups in res.fetchall()] # series functions @@ -349,12 +350,14 @@ class Database: # pylint:disable=R0904 Return: tuple: str: Series name str: Series description + str or None: Upstream name Raises: ValueError: Series is not found """ - res = self.execute('SELECT name, desc FROM series WHERE id = ?', - (idnum,)) + res = self.execute( + 'SELECT name, desc, upstream FROM series WHERE id = ?', + (idnum,)) recs = res.fetchall() if len(recs) != 1: raise ValueError(f'No series found (id {idnum} len {len(recs)})') @@ -417,7 +420,7 @@ class Database: # pylint:disable=R0904 'GROUP BY series_id') return res.fetchall() - def series_add(self, name, desc): + def series_add(self, name, desc, ups=None): """Add a new series record The new record is set to not archived @@ -425,13 +428,14 @@ class Database: # pylint:disable=R0904 Args: name (str): Series name desc (str): Series description + ups (str or None): Name of the upstream for this series Return: int: ID num of the new series record """ self.execute( - 'INSERT INTO series (name, desc, archived) ' - f"VALUES ('{name}', '{desc}', 0)") + 'INSERT INTO series (name, desc, archived, upstream) ' + 'VALUES (?, ?, 0, ?)', (name, desc, ups)) return self.lastrowid() def series_remove(self, idnum): @@ -481,6 +485,17 @@ class Database: # pylint:disable=R0904 self.execute( 'UPDATE series SET name = ? WHERE id = ?', (name, series_idnum)) + def series_set_upstream(self, series_idnum, ups): + """Update upstream for a series + + Args: + series_idnum (int): ID num of the series + ups (str or None): Name of the upstream, or None to clear + """ + self.execute( + 'UPDATE series SET upstream = ? WHERE id = ?', + (ups, series_idnum)) + # ser_ver functions def ser_ver_get_link(self, series_idnum, version): diff --git a/tools/patman/series.py b/tools/patman/series.py index 517fd4304f5..9985533ee52 100644 --- a/tools/patman/series.py +++ b/tools/patman/series.py @@ -72,11 +72,12 @@ class Series(dict): return self[name] @staticmethod - def from_fields(idnum, name, desc): + def from_fields(idnum, name, desc, ups): ser = Series() ser.idnum = idnum ser.name = name ser.desc = desc + ser.upstream = ups return ser def AddTag(self, commit, line, name, value): diff --git a/tools/patman/test_cseries.py b/tools/patman/test_cseries.py index 5719d9b6ddc..fc29e9a7bef 100644 --- a/tools/patman/test_cseries.py +++ b/tools/patman/test_cseries.py @@ -1879,6 +1879,36 @@ Tested-by: Mary Smith # yak self.run_args('upstream', 'list') self.assertFalse(out.getvalue().strip()) + def test_series_upstream(self): + """Test upstream field in the series table""" + cser = self.get_cser() + + # Add a series without upstream + cser.db.series_add('first', 'my desc') + cser.db.commit() + slist = cser.db.series_get_dict() + self.assertIsNone(slist['first'].upstream) + + # Add a series with upstream + cser.db.series_add('second', 'desc2', ups='us') + cser.db.commit() + slist = cser.db.series_get_dict() + self.assertIsNone(slist['first'].upstream) + self.assertEqual('us', slist['second'].upstream) + + # Update upstream on existing series + idnum = cser.db.series_find_by_name('first') + cser.db.series_set_upstream(idnum, 'ci') + cser.db.commit() + slist = cser.db.series_get_dict() + self.assertEqual('ci', slist['first'].upstream) + + # Clear upstream + cser.db.series_set_upstream(idnum, None) + cser.db.commit() + slist = cser.db.series_get_dict() + self.assertIsNone(slist['first'].upstream) + def test_series_add_mark(self): """Test marking a cseries with Change-Id fields""" cser = self.get_cser()