@@ -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)
@@ -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')]
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(-)