From patchwork Thu Mar 5 14:54:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1970 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=1772722520; bh=L3s61dGwgGnS/fv25M917FYEMS2/BXEyj7PcNwwnHeQ=; 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=cMausGOqf+Bq9SehxS7ntBC0P4bU2dX1b0FxVlAPEN1KIhf23Fi0iFbinnNeuwD0u pDbHn2ikrAjoIHpGzsR1QTFe+iyKSi/svd+1NStCCaRaQ+2IADcb+2G7cRtYbAsk5H FbEMC2uO//bQK7YRrCTdEwkpCaJ3WSWlfm8A5SpS2B37RoQMxq2MtlhlUIRDmzQJAN CCbMbVWoC7e9/73+prApXHORkNz/mp0MnODEKxW4S73SNeC+VAH26FwYMqESaBrnws Vf4qHh+kt421NuLdKc1UY2TFt54BQuXxm9SwACZ3Q/mKtWH0y9liKXIuym7ukD/s4i XCGWXovb+yf6Q== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id E4B3269F25 for ; Thu, 5 Mar 2026 07:55:20 -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 1ij4fW_rJQmF for ; Thu, 5 Mar 2026 07:55:20 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772722520; bh=L3s61dGwgGnS/fv25M917FYEMS2/BXEyj7PcNwwnHeQ=; 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=cMausGOqf+Bq9SehxS7ntBC0P4bU2dX1b0FxVlAPEN1KIhf23Fi0iFbinnNeuwD0u pDbHn2ikrAjoIHpGzsR1QTFe+iyKSi/svd+1NStCCaRaQ+2IADcb+2G7cRtYbAsk5H FbEMC2uO//bQK7YRrCTdEwkpCaJ3WSWlfm8A5SpS2B37RoQMxq2MtlhlUIRDmzQJAN CCbMbVWoC7e9/73+prApXHORkNz/mp0MnODEKxW4S73SNeC+VAH26FwYMqESaBrnws Vf4qHh+kt421NuLdKc1UY2TFt54BQuXxm9SwACZ3Q/mKtWH0y9liKXIuym7ukD/s4i XCGWXovb+yf6Q== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id D458069F0F for ; Thu, 5 Mar 2026 07:55:20 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772722518; bh=1jcoGqhbNffVEPP5eJWLNGoS8Ig1w+igjnRhsEjRVrk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=isiHnTxUiGJBXN3Eas8LvbwC+LcRlKizz2pS7o0T95EtG0j7s8FPgDCcxyuN0nyOr XOnkCkErZ7B+Y415c/J8AdwkhKa5Wn57Zj3Hd/j17rr18dSKMasn+59DxBQK1O6dSZ I4N/gXSPWAjQto+TWwafxd5/C/vXGW+x1LGXqyJd/FROcqUAvqXArxm0mbIlfzsT7K rwCU3XNgYUyxYiuKzb1nbxSGCH6SrHx6b2SUNWo8UZc95to3QIx7Ef3uFbDRCWQV43 +OsV0TtOmP1/CNfePr0K7IZOxxH6dyvAu4k2NoE39cryQisIXw3urUzgN47NZWWK9Q 4RLYlF0ab0k+w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 1E51469EC0; Thu, 5 Mar 2026 07:55:18 -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 ZuUkGXTzIvz9; Thu, 5 Mar 2026 07:55:18 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1772722512; bh=7wj4B68c7RAYm57/yQJZVOQa3nS8TmY2zVM2Z7T1708=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k8MTgcR1gWpWnCMVhSGg8D03lFUWL9vRYXmyXcXDcySIAsntlSMCBmKwMenUK+B1y 4eAUwI/OYP3k6BsiDBIll60TPtlWoMV62rKeJct2WclVoALrtAivkDgqyFaNlHJY6P kRs2fsNl5Gy0Xj1wyIauQ5+cLDnVV2ZbAnG++hwEJXjjIcqU8dFq4h5wkVYkzQmBXj me19/+Pn5Zp48pS4f9OLRSq3i/PUgBlHeeknBf9VqZnoO8wIiFH3pwAAuJ2ezgnu0r w9pMzfiGP1ziF4vgtT/S8m7VwbOEfgY2weQArVJTlVaGs7Ghxu6Bf5xP8VrjGy212e tEgxjdt66BCpA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 8244B69D92; Thu, 5 Mar 2026 07:55:12 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Thu, 5 Mar 2026 07:54:44 -0700 Message-ID: <20260305145452.909661-2-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260305145452.909661-1-sjg@u-boot.org> References: <20260305145452.909661-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 2OVDCJBBJXG3Q5IXH4ARRZCEAXQBFIJO X-Message-ID-Hash: 2OVDCJBBJXG3Q5IXH4ARRZCEAXQBFIJO 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 1/4] pickman: Fix ambiguous checkout in subtree update 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 When multiple remotes have a branch with the same name (e.g. ci/master, me/master, us/master), a bare 'git checkout master' fails because git cannot determine which remote to track. Fall back to 'git checkout -b /' when the bare checkout fails, creating a local branch from the specific remote. This mirrors the existing pattern used for MR branch creation. Signed-off-by: Simon Glass --- tools/pickman/control.py | 13 +++++++---- tools/pickman/ftest.py | 50 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/tools/pickman/control.py b/tools/pickman/control.py index a42927f991d..815ac574093 100644 --- a/tools/pickman/control.py +++ b/tools/pickman/control.py @@ -1524,7 +1524,7 @@ def _subtree_run_update(name, tag): int: 0 on success, 1 on failure """ try: - result = command.run( + result = command.run_one( './tools/update-subtree.sh', 'pull', name, tag, capture=True, raise_on_error=False) if result.stdout: @@ -1595,9 +1595,14 @@ def apply_subtree_update(dbs, source, name, tag, merge_hash, args): # pylint: d try: run_git(['checkout', target]) - except Exception: # pylint: disable=broad-except - tout.error(f'Could not checkout {target}') - return 1 + except command.CommandExc: + # Bare name may be ambiguous when multiple remotes have it + try: + run_git(['checkout', '-b', target, + f'{args.remote}/{target}']) + except command.CommandExc: + tout.error(f'Could not checkout {target}') + return 1 ret = _subtree_run_update(name, tag) if ret: diff --git a/tools/pickman/ftest.py b/tools/pickman/ftest.py index 5a4d0c433dc..766cc714ed7 100644 --- a/tools/pickman/ftest.py +++ b/tools/pickman/ftest.py @@ -4022,7 +4022,7 @@ class TestApplySubtreeUpdate(unittest.TestCase): with mock.patch.object(control, 'run_git', side_effect=run_git_handler): with mock.patch.object( - control.command, 'run', + control.command, 'run_one', return_value=mock_result): ret = control.apply_subtree_update( dbs, 'us/next', 'dts', 'v6.15-dts', @@ -4070,7 +4070,7 @@ class TestApplySubtreeUpdate(unittest.TestCase): with mock.patch.object(control, 'run_git', side_effect=run_git_handler): with mock.patch.object( - control.command, 'run', + control.command, 'run_one', return_value=mock_result): with mock.patch.object( control.gitlab_api, 'push_branch', @@ -4112,6 +4112,48 @@ class TestApplySubtreeUpdate(unittest.TestCase): self.assertEqual(dbs.source_get('us/next'), 'base') dbs.close() + def test_apply_checkout_fallback(self): + """Test apply_subtree_update falls back to -b when checkout fails.""" + with terminal.capture(): + dbs = database.Database(self.db_path) + dbs.start() + dbs.source_set('us/next', 'base') + dbs.commit() + + args = argparse.Namespace(push=False, remote='ci', + target='master') + + checkout_calls = [] + + def run_git_handler(git_args): + if 'rev-parse' in git_args: + return 'first_parent\nsquash_hash' + if 'checkout' in git_args: + checkout_calls.append(list(git_args)) + if '-b' not in git_args: + raise command.CommandExc( + 'ambiguous checkout', None) + return '' + if 'log' in git_args: + return 'subject|author' + return '' + + with mock.patch.object(control, 'run_git', + side_effect=run_git_handler): + with mock.patch.object(control, '_subtree_run_update', + return_value=0): + ret = control.apply_subtree_update( + dbs, 'us/next', 'dts', 'v6.15-dts', + 'merge_hash', args) + + self.assertEqual(ret, 0) + # Should have tried bare checkout, then fallback + self.assertEqual(len(checkout_calls), 2) + self.assertEqual(checkout_calls[0], ['checkout', 'master']) + self.assertEqual(checkout_calls[1], + ['checkout', '-b', 'master', 'ci/master']) + dbs.close() + def test_apply_no_second_parent(self): """Test apply_subtree_update returns 1 when merge has no 2nd parent.""" with terminal.capture(): @@ -4154,7 +4196,7 @@ class TestApplySubtreeUpdate(unittest.TestCase): with mock.patch.object(control, 'run_git', side_effect=run_git_handler): with mock.patch.object( - control.command, 'run', + control.command, 'run_one', side_effect=Exception('script failed')): ret = control.apply_subtree_update( dbs, 'us/next', 'dts', 'v6.15-dts', @@ -4193,7 +4235,7 @@ class TestApplySubtreeUpdate(unittest.TestCase): with mock.patch.object(control, 'run_git', side_effect=run_git_handler): with mock.patch.object( - control.command, 'run', + control.command, 'run_one', return_value=mock_result): ret = control.apply_subtree_update( dbs, 'us/next', 'dts', 'v6.15-dts',