[Concept,13/32] patman: Add patchwork list command

Message ID 20260226200106.1727176-14-sjg@u-boot.org
State New
Headers
Series patman: Add multi-upstream support |

Commit Message

Simon Glass Feb. 26, 2026, 8 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Add a 'patchwork list' (or 'pw list') command to show all configured
patchwork projects and which upstream each is associated with.

Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 tools/patman/cmdline.py      |  1 +
 tools/patman/control.py      |  2 ++
 tools/patman/cseries.py      | 13 +++++++++++++
 tools/patman/database.py     | 15 +++++++++++++++
 tools/patman/test_cseries.py | 26 ++++++++++++++++++++++++++
 5 files changed, 57 insertions(+)
  

Patch

diff --git a/tools/patman/cmdline.py b/tools/patman/cmdline.py
index 74571fd7220..f08287641dd 100644
--- a/tools/patman/cmdline.py
+++ b/tools/patman/cmdline.py
@@ -169,6 +169,7 @@  def add_patchwork_subparser(subparsers):
     uset.add_argument(
         '-u', '--upstream-name',
         help='Upstream to associate this project with')
+    patchwork_subparsers.add_parser('list')
     return patchwork
 
 
diff --git a/tools/patman/control.py b/tools/patman/control.py
index 191cfc134d3..bd9e0f8b9bd 100644
--- a/tools/patman/control.py
+++ b/tools/patman/control.py
@@ -289,6 +289,8 @@  def patchwork(args, test_db=None, pwork=None):
             if ups:
                 msg += f" upstream '{ups}'"
             print(msg)
+        elif args.subcmd == 'list':
+            cser.project_list()
         else:
             raise ValueError(f"Unknown patchwork subcommand '{args.subcmd}'")
     finally:
diff --git a/tools/patman/cseries.py b/tools/patman/cseries.py
index 56adcc5b4cd..fdf48a4eabd 100644
--- a/tools/patman/cseries.py
+++ b/tools/patman/cseries.py
@@ -683,6 +683,19 @@  class Cseries(cser_helper.CseriesHelper):
         """
         return self.db.patchwork_get(ups)
 
+    def project_list(self):
+        """List all patchwork project configurations"""
+        settings = self.db.patchwork_get_list()
+        if not settings:
+            print('No patchwork projects configured')
+            return
+        print(f"{'Project':20}  {'ID':>4}  {'Link name':15}  Upstream")
+        border = f"{'-' * 20}  {'-' * 4}  {'-' * 15}  {'-' * 15}"
+        print(border)
+        for name, proj_id, link_name, ups in settings:
+            print(f'{name:20}  {proj_id:4}  {link_name:15}  {ups or ""}')
+        print(border)
+
     def remove(self, name, dry_run=False):
         """Remove a series from the database
 
diff --git a/tools/patman/database.py b/tools/patman/database.py
index 22f21ce715f..396cf52aa48 100644
--- a/tools/patman/database.py
+++ b/tools/patman/database.py
@@ -884,6 +884,21 @@  class Database:  # pylint:disable=R0904
             'INSERT INTO patchwork (name, proj_id, link_name, upstream) '
             'VALUES (?, ?, ?, ?)', (name, proj_id, link_name, ups))
 
+    def patchwork_get_list(self):
+        """Get all patchwork project configurations
+
+        Returns:
+            list of tuple:
+                name (str): Project name, e.g. 'U-Boot'
+                proj_id (int): Patchworks project ID for this project
+                link_name (str): Patchwork's link-name for the project
+                upstream (str or None): Upstream name
+        """
+        res = self.execute(
+            'SELECT name, proj_id, link_name, upstream FROM patchwork '
+            'ORDER BY upstream')
+        return res.fetchall()
+
     def patchwork_get(self, ups=None):
         """Get the patchwork project details for an upstream
 
diff --git a/tools/patman/test_cseries.py b/tools/patman/test_cseries.py
index 0922c3e57f5..f21fda8d2fa 100644
--- a/tools/patman/test_cseries.py
+++ b/tools/patman/test_cseries.py
@@ -2502,6 +2502,32 @@  Tested-by: Mary Smith <msmith@wibble.com>   # yak
             f"Project 'U-Boot' patchwork-ID {self.PROJ_ID} link-name 'uboot'",
             out.getvalue().strip())
 
+    def test_patchwork_list(self):
+        """Test listing patchwork project configurations"""
+        cser = self.get_cser()
+
+        # No projects configured
+        with terminal.capture() as (out, _):
+            cser.project_list()
+        self.assertEqual('No patchwork projects configured',
+                         out.getvalue().strip())
+
+        # Add projects for two upstreams
+        cser.db.upstream_add('us', 'https://us.example.com')
+        cser.db.upstream_add('ci', 'https://ci.example.com')
+        cser.db.patchwork_update('U-Boot', 6, 'uboot', 'us')
+        cser.db.patchwork_update('Linux', 10, 'linux', 'ci')
+        cser.db.commit()
+
+        with terminal.capture() as (out, _):
+            cser.project_list()
+        lines = out.getvalue().splitlines()
+        self.assertEqual(5, len(lines))
+        self.assertIn('Linux', lines[2])
+        self.assertIn('ci', lines[2])
+        self.assertIn('U-Boot', lines[3])
+        self.assertIn('us', lines[3])
+
     def test_patchwork_upstream(self):
         """Test patchwork project with upstream association"""
         cser = self.get_cser()