From patchwork Thu Feb 26 20:00:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1961 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=1772136187; bh=6a3SKaawCR+gGsKOwax37g+u1x+54ddQenjvBstwLpw=; 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=fMyK4XzS2yio8u5r3fjyJoPNBk8Zh60TgEUcK0zJ7CXyaUGIT5b2IZJIBUkSuyJ2Q wRumiwnjHyjTH/tbgyMtyWiPZuVI7r2BpRctCY3CbhEE1GIRPrp5u868uf6feNGpfm aC2r5JnZbTptm2Kg4svaIXFvlo0cTEhMRQk4iXSZ+2q6IBxBRjJsvx+9ZFaMXUmAac mYhIMYFm06sRb2usa1Yv3i5mLUroqVv7ZMVWmQ3FqKDjNNwgdx7DIbfTM6gfK0sH9G 1Ra9b02Pv3ZqIUAGs4pYRw0Jm/hnLbUvDctRoVpssoKTnYpIocaKyd7XWbvQkMW4jf rZk6Z4pEp1MQQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 732D269D4A for ; Thu, 26 Feb 2026 13:03:07 -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 hTd5ml0cUkWK for ; Thu, 26 Feb 2026 13:03:07 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772136187; bh=6a3SKaawCR+gGsKOwax37g+u1x+54ddQenjvBstwLpw=; 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=fMyK4XzS2yio8u5r3fjyJoPNBk8Zh60TgEUcK0zJ7CXyaUGIT5b2IZJIBUkSuyJ2Q wRumiwnjHyjTH/tbgyMtyWiPZuVI7r2BpRctCY3CbhEE1GIRPrp5u868uf6feNGpfm aC2r5JnZbTptm2Kg4svaIXFvlo0cTEhMRQk4iXSZ+2q6IBxBRjJsvx+9ZFaMXUmAac mYhIMYFm06sRb2usa1Yv3i5mLUroqVv7ZMVWmQ3FqKDjNNwgdx7DIbfTM6gfK0sH9G 1Ra9b02Pv3ZqIUAGs4pYRw0Jm/hnLbUvDctRoVpssoKTnYpIocaKyd7XWbvQkMW4jf rZk6Z4pEp1MQQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 60B9269E35 for ; Thu, 26 Feb 2026 13:03:07 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772136185; bh=OfStY4rFi12SfZZEcVV6KSAfyVb8y8TskoHv7LhsZes=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cJDwmU5qtqSPv1l1b1kpuf0UAFYdTHeNqIbGBm+VpB4Ci4cBp6M0kk+ciFGsuTbIl FmtrbRVKEkL6vlqeKTz7z6fbsIuxf6QiL+tTYxIY4y9JAtwOy365x624Qn+JVUJRjL VvlGYUr0mocqg0SkypZGrV7dzpX/Vq+Y4Si8lPMQ6MVpME6n2VXp4SYX7Vk6NnXlrl kIPhT+SNHrnGI2dOmFET3d/BTnA7mRq/6EO+vZpTWTiEgYPTf1yb7jM7BnIDLfP/Ac 9XRfTPvW+K2UhcyEAbGQhVCXs4bDLlYpoZQypE7L0VJWoB30oKShMuiByzLekSS6I4 uV3Tr5Dq5x3WQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 6A1B269E35; Thu, 26 Feb 2026 13:03:05 -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 uSJUIwpyRrRL; Thu, 26 Feb 2026 13:03:05 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772136180; bh=91Yekz1qh1b9FKr4w45j3LTm2/9489uFMrES9egkHY4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K4N5oUtyz9UAiMa9CHs9Lj4tQNxiN+/PQILkg3tAer+OLFQiSvmG4SyqjsAv6/5bx rCixcLpIJOJXM9nxCB44BNXLS+OaJwBAAQxArLYil83wEyhgfJIJWphPwRn5dL5oAA C/BD+2IGFrVTmz8o4fKo1dTy7RK5OOCHWIDtJFGI3jEkbCaO7HTJ+cohbkOktgG2Si lrKWYnV0BiFAwV85OghmdULpu+wdcX2eas+SJeqfdz1iYAobkBADenYEufJGLuvV7m ioUMpXDQhX8U4irvid79+aXkKjNh47vyOYFv09uFLwJlIqngmkA2QxPLLF6SUmEQt5 5II+s+VIsv/6w== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 7129C69D4A; Thu, 26 Feb 2026 13:03:00 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Thu, 26 Feb 2026 13:00:30 -0700 Message-ID: <20260226200106.1727176-25-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: 4VASACJBDQNWDEFXRVFOJPC5WBVQX3CY X-Message-ID-Hash: 4VASACJBDQNWDEFXRVFOJPC5WBVQX3CY 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 24/32] patman: Add an 'upstream set' command to update settings 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 Add a 'set' subcommand for upstream that allows updating individual fields on an existing upstream without having to delete and re-add it. Supports -p/--patchwork-url, -I/--identity, -t/--series-to, -m/--no-maintainers, --maintainers, --no-tags and --tags. For example: patman upstream set us -I chromium -t concept -m Signed-off-by: Simon Glass --- tools/patman/cmdline.py | 25 ++++++++++++++++++ tools/patman/control.py | 19 ++++++++++++++ tools/patman/cseries.py | 14 ++++++++++ tools/patman/database.py | 34 ++++++++++++++++++++++++ tools/patman/test_cseries.py | 50 ++++++++++++++++++++++++++++++++++++ 5 files changed, 142 insertions(+) diff --git a/tools/patman/cmdline.py b/tools/patman/cmdline.py index 6141f106fde..5bf917e4712 100644 --- a/tools/patman/cmdline.py +++ b/tools/patman/cmdline.py @@ -411,6 +411,7 @@ def add_upstream_subparser(subparsers): upstream.defaults_cmds = [ ['add', 'us', 'http://fred', '-p', 'http://pw', 'U-Boot'], ['delete', 'us'], + ['set', 'us'], ] upstream_subparsers = upstream.add_subparsers(dest='subcmd') uadd = upstream_subparsers.add_parser('add') @@ -443,6 +444,30 @@ def add_upstream_subparser(subparsers): 'remote_name', help="Git remote name used for this upstream, e.g. 'us'") upstream_subparsers.add_parser('ls', aliases=['list']) + uset = upstream_subparsers.add_parser('set') + uset.add_argument('remote_name', + help="Git remote name used for this upstream, e.g. 'us'") + uset.add_argument( + '-p', '--patchwork-url', + help='URL of patchwork server for this upstream') + uset.add_argument( + '-I', '--identity', + help="Git sendemail identity to use, e.g. 'chromium'") + uset.add_argument( + '-t', '--series-to', + help="Patman alias for the To address, e.g. 'u-boot'") + uset.add_argument( + '-m', '--no-maintainers', action='store_true', default=None, + help='Skip get_maintainer.pl for this upstream') + uset.add_argument( + '--maintainers', action='store_true', default=None, + help='Enable get_maintainer.pl for this upstream') + uset.add_argument( + '--no-tags', action='store_true', default=None, + help='Skip subject-tag alias processing for this upstream') + uset.add_argument( + '--tags', action='store_true', default=None, + help='Enable subject-tag alias processing for this upstream') udef = upstream_subparsers.add_parser('default') udef.add_argument('-u', '--unset', action='store_true', help='Unset the default upstream') diff --git a/tools/patman/control.py b/tools/patman/control.py index 689fd732dec..cabd2138bb3 100644 --- a/tools/patman/control.py +++ b/tools/patman/control.py @@ -267,6 +267,25 @@ def upstream(args, test_db=None): print(result if result else 'unset') elif args.subcmd == 'delete': cser.upstream_delete(args.remote_name) + elif args.subcmd == 'set': + kwargs = {} + if args.patchwork_url is not None: + kwargs['patchwork_url'] = args.patchwork_url + if args.identity is not None: + kwargs['identity'] = args.identity + if args.series_to is not None: + kwargs['series_to'] = args.series_to + if args.no_maintainers: + kwargs['no_maintainers'] = True + elif args.maintainers: + kwargs['no_maintainers'] = False + if args.no_tags: + kwargs['no_tags'] = True + elif args.tags: + kwargs['no_tags'] = False + if not kwargs: + raise ValueError('No settings to update') + cser.upstream_set(args.remote_name, **kwargs) elif args.subcmd == 'ls': cser.upstream_list() else: diff --git a/tools/patman/cseries.py b/tools/patman/cseries.py index 36f0b432073..588e83298bd 100644 --- a/tools/patman/cseries.py +++ b/tools/patman/cseries.py @@ -1237,6 +1237,20 @@ class Cseries(cser_helper.CseriesHelper): line += ' no-tags' print(line) + def upstream_set(self, name, **kwargs): + """Update settings on an existing upstream + + See Database.upstream_set() for permitted kwargs. + + Args: + name (str): Name of the upstream remote to update + kwargs: Fields to update + """ + self.db.upstream_set(name, **kwargs) + self.commit() + parts = [f'{k}={v!r}' for k, v in kwargs.items()] + tout.notice(f"Updated upstream '{name}': {', '.join(parts)}") + def upstream_set_default(self, name): """Set the default upstream target diff --git a/tools/patman/database.py b/tools/patman/database.py index 19df3c3bc82..dcd39ea2c69 100644 --- a/tools/patman/database.py +++ b/tools/patman/database.py @@ -863,6 +863,40 @@ class Database: # pylint:disable=R0904 self.rollback() raise ValueError(f"No such upstream '{name}'") + def upstream_set(self, name, **kwargs): + """Update fields on an existing upstream + + Args: + name (str): Name of the upstream remote to update + kwargs: Fields to update, each being one of: + patchwork_url (str): URL of the patchwork server, e.g. + 'patchwork.ozlabs.org' + identity (str): Git sendemail identity to use when + sending, corresponding to a [sendemail ""] + section in .gitconfig + series_to (str): Mailing-list address to use as the + default To: for this upstream + no_maintainers (bool): True to skip + get_maintainer.pl when sending + no_tags (bool): True to skip processing of subject + tags (e.g. 'dm:') when sending + + Raises: + ValueError: Upstream does not exist or invalid field + """ + valid = {'patchwork_url', 'identity', 'series_to', + 'no_maintainers', 'no_tags'} + invalid = set(kwargs) - valid + if invalid: + raise ValueError(f"Invalid upstream field(s): {invalid}") + for field, value in kwargs.items(): + self.execute( + f'UPDATE upstream SET {field} = ? WHERE name = ?', + (value, name)) + if self.rowcount() != 1: + self.rollback() + raise ValueError(f"No such upstream '{name}'") + def upstream_get_patchwork_url(self, name): """Get the patchwork URL for an upstream diff --git a/tools/patman/test_cseries.py b/tools/patman/test_cseries.py index 8f56627958e..fcfe6610321 100644 --- a/tools/patman/test_cseries.py +++ b/tools/patman/test_cseries.py @@ -1813,6 +1813,56 @@ Tested-by: Mary Smith # yak 'us https://one', lines[0]) + def test_upstream_set(self): + """Test updating settings on an existing upstream""" + cser = self.get_cser() + + with terminal.capture(): + cser.upstream_add('us', 'https://one') + + # Set identity and series_to + with terminal.capture(): + cser.upstream_set('us', identity='chromium', series_to='concept') + settings = cser.db.upstream_get_send_settings('us') + self.assertEqual('chromium', settings[0]) + self.assertEqual('concept', settings[1]) + + # Set boolean flags + with terminal.capture(): + cser.upstream_set('us', no_maintainers=True, no_tags=True) + settings = cser.db.upstream_get_send_settings('us') + self.assertTrue(settings[2]) + self.assertTrue(settings[3]) + + # Clear boolean flags + with terminal.capture(): + cser.upstream_set('us', no_maintainers=False, no_tags=False) + settings = cser.db.upstream_get_send_settings('us') + self.assertFalse(settings[2]) + self.assertFalse(settings[3]) + + # Non-existent upstream + with self.assertRaises(ValueError) as exc: + cser.upstream_set('nonexistent', identity='x') + self.assertIn('nonexistent', str(exc.exception)) + + def test_upstream_set_cmdline(self): + """Test upstream set via the command line""" + with terminal.capture(): + self.run_args('upstream', 'add', 'us', 'https://one') + + with terminal.capture(): + self.run_args('upstream', 'set', 'us', '-I', 'chromium', + '-t', 'concept', '-m', '--no-tags') + + with terminal.capture() as (out, _): + self.run_args('upstream', 'list') + line = out.getvalue().strip() + self.assertIn('id:chromium', line) + self.assertIn('to:concept', line) + self.assertIn('no-maintainers', line) + self.assertIn('no-tags', line) + def test_upstream_default(self): """Operation of the default upstream""" cser = self.get_cser()