diff mbox series

[layerindex-web,4/6] rrs/tools/common.py: check out the layer branch before parsing it

Message ID 20261115003506.53654-5-tim.orling@konsulko.com
State Under Review
Delegated to: Tim Orling
Headers show
Series Get the RRS update scripts working again | expand

Commit Message

Tim Orling Nov. 15, 2026, 12:35 a.m. UTC
load_recipes() let init_parser() check out BitBake and the core layer,
but not the layer itself or the layers it depends on, so
rrs_upstream_history.py and rrs_distros.py parsed whichever branch the
layer index updates had left them on, e.g. meta-openembedded at dunfell
while working on master. Check out the layer branch and its
dependencies' unless nocheckout is set.

[YOCTO #16502]

AI-Generated: Claude Opus 5.5
Signed-off-by: Tim Orling <tim.orling@konsulko.com>
---
 rrs/tools/common.py            | 13 +++++++++-
 tests/test_rrs_load_recipes.py | 45 ++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/rrs/tools/common.py b/rrs/tools/common.py
index ccdbe62..f97d4e1 100644
--- a/rrs/tools/common.py
+++ b/rrs/tools/common.py
@@ -92,7 +92,7 @@  def get_recipe_files(layerdir):
 
 def load_recipes(layerbranch, bitbakepath, fetchdir, settings, logger,
         recipe_files=None, nocheckout=False):
-    from layerindex import recipeparse
+    from layerindex import recipeparse, utils
 
     try:
         (tinfoil, tempdir) = recipeparse.init_parser(settings,
@@ -110,6 +110,17 @@  def load_recipes(layerbranch, bitbakepath, fetchdir, settings, logger,
     repodir = os.path.join(fetchdir, urldir)
     layerdir = os.path.join(repodir, str(layerbranch.vcs_subdir))
 
+    if not nocheckout:
+        # The repositories are left on whichever branch was updated last;
+        # check out this branch of the layer and of the layers it depends on
+        # (init_parser() has done BitBake and the core layer)
+        utils.checkout_layer_branch(layerbranch, repodir, logger=logger)
+        for dep in layerbranch.dependencies_set.all():
+            deplayerbranch = dep.dependency.get_layerbranch(layerbranch.branch.name)
+            if deplayerbranch:
+                utils.checkout_layer_branch(deplayerbranch,
+                        os.path.join(fetchdir, dep.dependency.get_fetch_dir()), logger=logger)
+
     d = recipeparse.setup_layer(tinfoil.config_data, fetchdir, layerdir,
             layer, layerbranch, logger)
 
diff --git a/tests/test_rrs_load_recipes.py b/tests/test_rrs_load_recipes.py
index 97f3d26..8322350 100644
--- a/tests/test_rrs_load_recipes.py
+++ b/tests/test_rrs_load_recipes.py
@@ -33,3 +33,48 @@  def test_load_recipes_checks_out_bitbake_before_importing_it(monkeypatch):
     with pytest.raises(Stop):
         common.load_recipes(types.SimpleNamespace(branch=None), '/nonexistent', '/nonexistent',
                             types.SimpleNamespace(), None)
+
+
+@pytest.mark.django_db
+@pytest.mark.parametrize('nocheckout', [False, True])
+def test_load_recipes_checks_out_the_layer_branch(monkeypatch, nocheckout):
+    # [YOCTO #16502] parse the branch being worked on, not whichever branch
+    # the repositories were left on
+    import common
+    monkeypatch.syspath_prepend(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'layerindex'))
+    from layerindex import recipeparse, utils
+    from layerindex.models import Branch, LayerBranch, LayerDependency, LayerItem
+
+    master, _ = Branch.objects.get_or_create(name='master', defaults={'bitbake_branch': 'master'})
+    layers = {}
+    for name in ('meta-oe', 'meta-python'):
+        layer = LayerItem.objects.create(name=name, status='P', layer_type='A', summary=name,
+                                         description=name, vcs_url='git://example.com/%s.git' % name)
+        layers[name] = LayerBranch.objects.create(layer=layer, branch=master, actual_branch='main')
+    LayerDependency.objects.create(layerbranch=layers['meta-oe'], dependency=layers['meta-python'].layer)
+
+    class Stop(Exception):
+        pass
+
+    def fake_setup_layer(*args, **kwargs):
+        raise Stop()
+
+    # load_recipes() imports bb.fetch once init_parser() has checked out BitBake
+    bb = types.ModuleType('bb')
+    bb.fetch = types.ModuleType('bb.fetch')
+    bb.fetch.FetchError = Exception
+    monkeypatch.setitem(sys.modules, 'bb', bb)
+    monkeypatch.setitem(sys.modules, 'bb.fetch', bb.fetch)
+
+    checkouts = []
+    monkeypatch.setattr(recipeparse, 'init_parser', lambda *args, **kwargs: (types.SimpleNamespace(config_data=None), '/tmp'))
+    monkeypatch.setattr(recipeparse, 'setup_layer', fake_setup_layer)
+    monkeypatch.setattr(utils, 'checkout_repo', lambda repodir, ref, logger=None: checkouts.append((os.path.basename(repodir), ref)))
+    with pytest.raises(Stop):
+        common.load_recipes(layers['meta-oe'], '/bitbake', '/fetch', types.SimpleNamespace(), None,
+                            recipe_files=[], nocheckout=nocheckout)
+    if nocheckout:
+        assert checkouts == []
+    else:
+        assert checkouts == [('git___example_com_meta-oe_git', 'origin/main'),
+                             ('git___example_com_meta-python_git', 'origin/main')]