diff mbox series

[layerindex-web,2/4] update: copy a new layer branch's subdirectory from the newest branch

Message ID 20261019213510.4384-3-tim.orling@konsulko.com
State New
Headers show
Series Fixes for errors and warnings in layer updates | expand

Commit Message

Tim Orling Oct. 19, 2026, 9:35 p.m. UTC
When a layer is first found on a new branch, vcs_subdir was copied from
get_layerbranch(None), an arbitrary and usually the oldest layer branch.
meta-tq has since moved into a subdirectory, so its wrynose update
failed with "conf/layer.conf not found". Copy it from the newest
non-comparison branch instead.

AI-Generated: Claude Opus 5.5
Signed-off-by: Tim Orling <tim.orling@konsulko.com>
---
 layerindex/models.py             |  9 ++++++
 layerindex/update.py             |  2 +-
 layerindex/update_layer.py       |  2 +-
 tests/test_latest_layerbranch.py | 52 ++++++++++++++++++++++++++++++++
 4 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 tests/test_latest_layerbranch.py
diff mbox series

Patch

diff --git a/layerindex/models.py b/layerindex/models.py
index a72a72b..a9e9bdf 100644
--- a/layerindex/models.py
+++ b/layerindex/models.py
@@ -162,6 +162,15 @@  class LayerItem(models.Model):
             return res[0]
         return None
 
+    def get_latest_layerbranch(self):
+        """
+        Return the layer branch for the newest non-comparison branch (by
+        branch sort priority), e.g. to copy settings such as vcs_subdir from
+        when the layer is first seen on a new branch.
+        """
+        return self.layerbranch_set.filter(branch__comparison=False).order_by(
+            models.F('branch__sort_priority').asc(nulls_last=True), '-id').first()
+
     def active_maintainers(self):
         matches = None
         for layerbranch in self.layerbranch_set.all():
diff --git a/layerindex/update.py b/layerindex/update.py
index dd730ca..ca68e3e 100755
--- a/layerindex/update.py
+++ b/layerindex/update.py
@@ -389,7 +389,7 @@  def main():
                         layerbranch.branch = branchobj
                         layerbranch_source = layer.get_layerbranch(branchobj)
                         if not layerbranch_source:
-                            layerbranch_source = layer.get_layerbranch(None)
+                            layerbranch_source = layer.get_latest_layerbranch()
                         if layerbranch_source:
                             layerbranch.vcs_subdir = layerbranch_source.vcs_subdir
 
diff --git a/layerindex/update_layer.py b/layerindex/update_layer.py
index 441efc2..0f49371 100644
--- a/layerindex/update_layer.py
+++ b/layerindex/update_layer.py
@@ -380,7 +380,7 @@  def main():
                     layerbranch.actual_branch = options.actual_branch
                 layerbranch_source = layer.get_layerbranch(branch)
                 if not layerbranch_source:
-                    layerbranch_source = layer.get_layerbranch(None)
+                    layerbranch_source = layer.get_latest_layerbranch()
                 if layerbranch_source:
                     layerbranch.vcs_subdir = layerbranch_source.vcs_subdir
                 layerbranch.save()
diff --git a/tests/test_latest_layerbranch.py b/tests/test_latest_layerbranch.py
new file mode 100644
index 0000000..33e0844
--- /dev/null
+++ b/tests/test_latest_layerbranch.py
@@ -0,0 +1,52 @@ 
+# layerindex-web - tests for choosing the layer branch to copy settings from
+#
+# Licensed under the MIT license, see COPYING.MIT for details
+#
+# SPDX-License-Identifier: MIT
+
+import pytest
+from django.test import TestCase
+
+from layerindex.models import Branch, LayerBranch, LayerItem
+
+
+@pytest.mark.django_db
+class TestLatestLayerBranch(TestCase):
+    """When a layer is first seen on a new branch, the update script copies
+    vcs_subdir from an existing layer branch. It must use the newest branch:
+    meta-tq moved into a meta-tq/ subdirectory, and copying the empty
+    subdirectory of an old branch made the new branch's update fail with
+    "conf/layer.conf not found"."""
+
+    def setUp(self):
+        self.layer = LayerItem.objects.create(name='meta-tq', status='P', layer_type='B',
+                                              summary='test', description='test',
+                                              vcs_url='https://example.com/meta-tq.git')
+
+    def branch(self, name, sort_priority, comparison=False):
+        return Branch.objects.create(name=name, bitbake_branch=name, sort_priority=sort_priority,
+                                     comparison=comparison)
+
+    def layerbranch(self, branch, subdir):
+        return LayerBranch.objects.create(layer=self.layer, branch=branch, vcs_subdir=subdir)
+
+    def test_newest_branch_wins_over_oldest_record(self):
+        # Oldest branch first, so it is the first record (as for meta-tq)
+        self.layerbranch(self.branch('krogoth', 20), '')
+        self.layerbranch(self.branch('kirkstone', 5), 'meta-tq')
+        newest = self.layerbranch(self.branch('scarthgap', 3), 'meta-tq')
+        self.assertEqual(self.layer.get_latest_layerbranch(), newest)
+        self.assertEqual(self.layer.get_latest_layerbranch().vcs_subdir, 'meta-tq')
+
+    def test_comparison_and_unprioritised_branches_are_not_preferred(self):
+        self.layerbranch(self.branch('comparison', 1, comparison=True), 'other')
+        self.layerbranch(self.branch('unsorted', None), 'other')
+        newest = self.layerbranch(self.branch('scarthgap', 3), 'meta-tq')
+        self.assertEqual(self.layer.get_latest_layerbranch(), newest)
+
+    def test_only_unprioritised_branches(self):
+        lb = self.layerbranch(self.branch('unsorted', None), 'meta-tq')
+        self.assertEqual(self.layer.get_latest_layerbranch(), lb)
+
+    def test_no_layer_branches(self):
+        self.assertIsNone(self.layer.get_latest_layerbranch())