toaster:Add layer dependencies recursively #8004
cover toaster:Add layer dependencies recursively #8004
This lets a layer that has 2nd level dependencies (depends on x that depends on y) have all the dependent layers added to your project, not just the 1st level deps.
-b
The following changes since commit af1e3160922a30b8a538959335a5f8945f2f3549:
toaster: Remove project name from latest project builds (2015-10-02 14:44:14 +0100)
are available in the git repository at:
git://git.yoctoproject.org/poky-contrib bavery/submit/ed/2015-10-02_layerdeps-8004
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=bavery/submit/ed/2015-10-02_layerdeps-8004
Ed Bartosh (5):
toaster: implement API to get full list of deps
toaster: use get_alldeps in layerdetails renderer
toaster: fix NameError
toaster: fix orm tests
toaster: test get_alldeps API
lib/toaster/orm/models.py | 21 +++++++++++++++- lib/toaster/orm/tests.py | 53 ++++++++++++++++++----------------------- lib/toaster/toastergui/views.py | 4 ++-- 3 files changed, 45 insertions(+), 33 deletions(-)
Signature · 1 line
1.9.1
PATCH 1/5 toaster: implement API to get full list of deps
From: Ed Bartosh <[email protected]>
Implemented Layer_Version.get_alldeps API to recursively get full list of dependencies for the layer. Dependencies that are already in the project are filtered out from the result. Result list of Layer_Version objects is sorted by layer name for UI to look consistent.
This API is going to be used to show amount and list of dependencies for the layer in the list of compatible layers for the project.
--- lib/toaster/orm/models.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
lib/toaster/orm/models.py +19 -0
@@ -1178,6 +1178,25 @@ class Layer_Version(models.Model): def get_detailspage_url(self, project_id): return reverse('layerdetails', args=(project_id, self.pk)) + def get_alldeps(self, project_id): + """Get full list of unique layer dependencies.""" + def gen_layerdeps(lver, project): + for ldep in lver.dependencies.all(): + yield ldep.depends_on + # get next level of deps recursively calling gen_layerdeps + for subdep in gen_layerdeps(ldep.depends_on, project): + yield subdep + + project = Project.objects.get(pk=project_id) + result = [] + projectlvers = [player.layercommit for player in project.projectlayer_set.all()] + for dep in gen_layerdeps(self, project): + # filter out duplicates and layers already belonging to the project + if dep not in result + projectlvers: + result.append(dep) + + return sorted(result, key=lambda x: x.layer.name) + def __unicode__(self): return "%d %s (VCS %s, Project %s)" % (self.pk, str(self.layer), self.get_vcs_reference(), self.build.project if self.build is not None else "No project")
Signature · 1 line
1.9.1
PATCH 2/5 toaster: use get_alldeps in layerdetails renderer
From: Ed Bartosh <[email protected]>
Used Layer_Version.get_alldeps api in layerdetails template renderer to get list of layer dependencies.
[YOCTO 8004]
--- lib/toaster/toastergui/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
lib/toaster/toastergui/views.py +2 -2
@@ -2760,8 +2760,8 @@ if True: context = { 'project' : project, 'layerversion' : layer_version, - 'layerdeps' : { "list": [ - [{"id": y.id, "name": y.layer.name} for y in x.depends_on.get_equivalents_wpriority(project)][0] for x in layer_version.dependencies.all()]}, + 'layerdeps' : {"list": [{"id": dep.id, "name": dep.layer.name} \ + for dep in layer_version.get_alldeps(project.id)]}, 'projectlayers': map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=project)) }
Signature · 1 line
1.9.1
PATCH 3/5 toaster: fix NameError
In reply to brian averyFrom: Ed Bartosh <[email protected]>
Fixed exception: NameError: global name 'DoesNotExist' is not defined
--- lib/toaster/orm/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/toaster/orm/models.py +1 -1
@@ -900,7 +900,7 @@ class LayerIndexLayerSource(LayerSource): oe_core_l.save() continue - except DoesNotExist: + except Layer.DoesNotExist: pass l, created = Layer.objects.get_or_create(layer_source = self, name = li['name'])
Signature · 1 line
1.9.1
PATCH 4/5 toaster: fix orm tests
In reply to brian averyFrom: Ed Bartosh <[email protected]>
Cleaned up and fixed orm tests. Removed test_build_layerversion as it's not needed due to changed compatible_layer_versions API.
--- lib/toaster/orm/tests.py | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-)
lib/toaster/orm/tests.py +4 -29
@@ -25,10 +25,9 @@ from django.test import TestCase, TransactionTestCase from orm.models import LocalLayerSource, LayerIndexLayerSource, ImportedLayerSource, LayerSource from orm.models import Branch -from orm.models import Project, Build, Layer, Layer_Version, Branch, ProjectLayer +from orm.models import Project, Layer, Layer_Version, Branch, ProjectLayer from orm.models import Release, ReleaseLayerSourcePriority, BitbakeVersion -from django.utils import timezone from django.db import IntegrityError import os
@@ -153,35 +152,11 @@ class LayerVersionEquivalenceTestCase(TestCase): equivqs = self.lver.get_equivalents_wpriority(self.project) self.assertEqual(list(equivqs), [lver2, self.lver]) - def test_build_layerversion(self): + def test_compatible_layer_versions(self): """ - Any layer version coming from the build should show up - before any layer version coming from upstream - """ - build = Build.objects.create(project=self.project, - started_on=timezone.now(), - completed_on=timezone.now()) - lvb = Layer_Version.objects.create(layer=self.layer, build=build, - commit="deadbeef") - - # a build layerversion must be in the equivalence - # list for the original layerversion - equivqs = self.lver.get_equivalents_wpriority(self.project) - self.assertTrue(len(equivqs) == 2) - self.assertTrue(equivqs[0] == self.lver) - self.assertTrue(equivqs[1] == lvb) - - # getting the build layerversion equivalent list must - # return the same list as the original layer - bequivqs = lvb.get_equivalents_wpriority(self.project) - - self.assertEqual(list(equivqs), list(bequivqs)) - - def test_compatible_layerversions(self): - """ - When we have a 2 layer versions, compatible_layerversions() + When we have a 2 layer versions, get_all_compatible_layerversions() should return a queryset with both. """ - compat_lv = self.project.compatible_layerversions() + compat_lv = self.project.get_all_compatible_layer_versions() self.assertEqual(list(compat_lv), [self.lver, self.lver2])
Signature · 1 line
1.9.1
PATCH 5/5 toaster: test get_alldeps API
In reply to brian averyFrom: Ed Bartosh <[email protected]>
Added test case to test Layer_Version.get_alldeps API.
--- lib/toaster/orm/tests.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
lib/toaster/orm/tests.py +19 -1
@@ -23,7 +23,7 @@ from django.test import TestCase, TransactionTestCase from orm.models import LocalLayerSource, LayerIndexLayerSource, ImportedLayerSource, LayerSource -from orm.models import Branch +from orm.models import Branch, LayerVersionDependency from orm.models import Project, Layer, Layer_Version, Branch, ProjectLayer from orm.models import Release, ReleaseLayerSourcePriority, BitbakeVersion
@@ -160,3 +160,21 @@ class LayerVersionEquivalenceTestCase(TestCase): compat_lv = self.project.get_all_compatible_layer_versions() self.assertEqual(list(compat_lv), [self.lver, self.lver2]) + def test_layerversion_get_alldeps(self): + """Test Layer_Version.get_alldeps API.""" + lvers = {} + for i in range(10): + name = "layer%d" % i + lvers[name] = Layer_Version.objects.create(layer=Layer.objects.create(name=name), + project=self.project) + if i: + LayerVersionDependency.objects.create(layer_version=lvers["layer%d" % (i - 1)], + depends_on=lvers[name]) + # Check dinamically added deps + self.assertEqual(lvers['layer0'].get_alldeps(self.project.id), + [lvers['layer%d' % n] for n in range(1, i+1)]) + + # Check chain of deps created in previous loop + for i in range(10): + self.assertEqual(lvers['layer%d' % i].get_alldeps(self.project.id), + [lvers['layer%d' % n] for n in range(i+1, 10)])
Signature · 1 line
1.9.1