[Concept,08/32] patman: Add set-upstream command for series

Message ID 20260226200106.1727176-9-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 'series set-upstream' subcommand to allow setting or changing the
upstream for an existing series. This uses the existing
series_set_upstream() database method and follows the same pattern as
the rename command.

Usage: patman series -s <name> set-upstream -u <upstream>

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

 tools/patman/cmdline.py      |  4 ++++
 tools/patman/control.py      |  3 +++
 tools/patman/cseries.py      | 25 +++++++++++++++++++++++++
 tools/patman/test_cseries.py | 17 +++++++++++++++++
 4 files changed, 49 insertions(+)
  

Patch

diff --git a/tools/patman/cmdline.py b/tools/patman/cmdline.py
index f80323b7853..65b9dfab4bb 100644
--- a/tools/patman/cmdline.py
+++ b/tools/patman/cmdline.py
@@ -298,6 +298,10 @@  def add_series_subparser(subparsers):
     ren.add_argument('-N', '--new-name', help='New name for the series')
 
     series_subparsers.add_parser('rm')
+
+    sup = series_subparsers.add_parser('set-upstream')
+    sup.add_argument('upstream_name', nargs='?',
+                     help='Name of the upstream for this series')
     series_subparsers.add_parser('rm-version', aliases=ALIASES['rm-version'])
 
     scan = series_subparsers.add_parser('scan')
diff --git a/tools/patman/control.py b/tools/patman/control.py
index c6fede4305b..1a65dfc2cc6 100644
--- a/tools/patman/control.py
+++ b/tools/patman/control.py
@@ -191,6 +191,9 @@  def do_series(args, test_db=None, pwork=None, cser=None):
             cser.version_remove(args.series, args.version, dry_run=args.dry_run)
         elif args.subcmd == 'rename':
             cser.rename(args.series, args.new_name, dry_run=args.dry_run)
+        elif args.subcmd == 'set-upstream':
+            cser.set_upstream(args.series, args.upstream_name,
+                              dry_run=args.dry_run)
         elif args.subcmd == 'scan':
             cser.scan(args.series, mark=args.mark,
                       allow_unmarked=args.allow_unmarked, end=args.upstream,
diff --git a/tools/patman/cseries.py b/tools/patman/cseries.py
index 6c918185387..246610215ed 100644
--- a/tools/patman/cseries.py
+++ b/tools/patman/cseries.py
@@ -770,6 +770,31 @@  class Cseries(cser_helper.CseriesHelper):
         if dry_run:
             tout.info('Dry run completed')
 
+    def set_upstream(self, series, ups, dry_run=False):
+        """Set the upstream for a series
+
+        Args:
+            series (str): Name of series to use, or None to use current branch
+            ups (str): Name of the upstream to set
+            dry_run (bool): True to do a dry run
+        """
+        if not ups:
+            raise ValueError('Please specify the upstream name')
+        ser, _ = self._parse_series_and_version(series, None)
+        if not ser.idnum:
+            raise ValueError(f"Series '{ser.name}' not found in database")
+
+        self.db.series_set_upstream(ser.idnum, ups)
+
+        if not dry_run:
+            self.commit()
+        else:
+            self.rollback()
+
+        tout.notice(f"Set upstream for series '{ser.name}' to '{ups}'")
+        if dry_run:
+            tout.info('Dry run completed')
+
     def scan(self, branch_name, mark=False, allow_unmarked=False, end=None,
              dry_run=False):
         """Scan a branch and make updates to the database if it has changed
diff --git a/tools/patman/test_cseries.py b/tools/patman/test_cseries.py
index e529d9fe61b..c6b90d5223d 100644
--- a/tools/patman/test_cseries.py
+++ b/tools/patman/test_cseries.py
@@ -1909,6 +1909,23 @@  Tested-by: Mary Smith <msmith@wibble.com>   # yak
         slist = cser.db.series_get_dict()
         self.assertIsNone(slist['first'].upstream)
 
+    def test_series_set_upstream(self):
+        """Test setting upstream via the set-upstream command"""
+        cser = self.get_cser()
+        with terminal.capture():
+            cser.add('first', '', allow_unmarked=True)
+
+        self.db_close()
+        with terminal.capture() as (out, _):
+            self.run_args('series', '-s', 'first', 'set-upstream',
+                          'origin')
+        self.assertIn("Set upstream for series 'first' to 'origin'",
+                      out.getvalue())
+
+        self.db_open()
+        slist = cser.db.series_get_dict()
+        self.assertEqual('origin', slist['first'].upstream)
+
     def test_series_add_mark(self):
         """Test marking a cseries with Change-Id fields"""
         cser = self.get_cser()