[Concept,15/32] patman: Group remotes by project in patchwork list

Message ID 20260226200106.1727176-16-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>

A project can have multiple remotes, so group them on a single line
rather than showing one row per remote. Sort by project name then
upstream in the patchwork table query.

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

 tools/patman/cseries.py      | 13 +++++++++++--
 tools/patman/database.py     |  2 +-
 tools/patman/test_cseries.py |  9 ++++++---
 3 files changed, 18 insertions(+), 6 deletions(-)
  

Patch

diff --git a/tools/patman/cseries.py b/tools/patman/cseries.py
index 3d24dd62fae..7237dd575cd 100644
--- a/tools/patman/cseries.py
+++ b/tools/patman/cseries.py
@@ -689,11 +689,20 @@  class Cseries(cser_helper.CseriesHelper):
         if not settings:
             print('No patchwork projects configured')
             return
-        print(f"{'Project':20}  {'ID':>4}  {'Link name':15}  Remote")
+        print(f"{'Project':20}  {'ID':>4}  {'Link name':15}  Remotes")
         border = f"{'-' * 20}  {'-' * 4}  {'-' * 15}  {'-' * 15}"
         print(border)
+
+        # Group remotes by project
+        projects = OrderedDict()
         for name, proj_id, link_name, ups in settings:
-            print(f'{name:20}  {proj_id:4}  {link_name:15}  {ups or ""}')
+            key = (name, proj_id, link_name)
+            projects.setdefault(key, [])
+            if ups:
+                projects[key].append(ups)
+        for (name, proj_id, link_name), remotes in projects.items():
+            rlist = ' '.join(sorted(remotes))
+            print(f'{name:20}  {proj_id:4}  {link_name:15}  {rlist}')
         print(border)
 
     def remove(self, name, dry_run=False):
diff --git a/tools/patman/database.py b/tools/patman/database.py
index 396cf52aa48..2f21e62605f 100644
--- a/tools/patman/database.py
+++ b/tools/patman/database.py
@@ -896,7 +896,7 @@  class Database:  # pylint:disable=R0904
         """
         res = self.execute(
             'SELECT name, proj_id, link_name, upstream FROM patchwork '
-            'ORDER BY upstream')
+            'ORDER BY name, upstream')
         return res.fetchall()
 
     def patchwork_get(self, ups=None):
diff --git a/tools/patman/test_cseries.py b/tools/patman/test_cseries.py
index b9be1680199..2a31815932c 100644
--- a/tools/patman/test_cseries.py
+++ b/tools/patman/test_cseries.py
@@ -2518,11 +2518,13 @@  Tested-by: Mary Smith <msmith@wibble.com>   # yak
         self.assertEqual('No patchwork projects configured',
                          out.getvalue().strip())
 
-        # Add projects for two upstreams
+        # Add two remotes for U-Boot and one for Linux
         cser.db.upstream_add('us', 'https://us.example.com')
         cser.db.upstream_add('ci', 'https://ci.example.com')
+        cser.db.upstream_add('linus', 'https://linus.example.com')
         cser.db.patchwork_update('U-Boot', 6, 'uboot', 'us')
-        cser.db.patchwork_update('Linux', 10, 'linux', 'ci')
+        cser.db.patchwork_update('U-Boot', 6, 'uboot', 'ci')
+        cser.db.patchwork_update('Linux', 10, 'linux', 'linus')
         cser.db.commit()
 
         with terminal.capture() as (out, _):
@@ -2530,8 +2532,9 @@  Tested-by: Mary Smith <msmith@wibble.com>   # yak
         lines = out.getvalue().splitlines()
         self.assertEqual(5, len(lines))
         self.assertIn('Linux', lines[2])
-        self.assertIn('ci', lines[2])
+        self.assertIn('linus', lines[2])
         self.assertIn('U-Boot', lines[3])
+        self.assertIn('ci', lines[3])
         self.assertIn('us', lines[3])
 
     def test_patchwork_upstream(self):