summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Wood <michael.g.wood@intel.com>2016-05-26 16:12:27 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-06-15 08:35:04 +0100
commitdd764003ea2cb9449f838146183f17873a902e48 (patch)
treea0824c31ae2049a1784d91a8e1d7fe8735e3c6b7
parent89433a35e6e21a978cef3e41e24d87024ed9a6ed (diff)
downloadpoky-dd764003ea2cb9449f838146183f17873a902e48.tar.gz
bitbake: toaster: Rework displaying package dependencies across Toaster
After porting the build table to a unified mechanism for showing dependencies in tables it highlighted that the dependencies selected to be shown were un-filtered. i.e. all dependencies from all contexts were shown. The context for a package's dependencies is based on the target that they were installed onto, or if not installed then a "None" target. Depending on where the template for the dependencies are show we need to switch this target which is why a filter and utility function on the model is added. Additionally to use the same templates in the build analysis we also need to optionally add links to the build data for the packages being displayed as dependencies. Customising a Custom image recipes may or may not have a target depending on whether they have been built or not, if not we do a best effort at getting the dependencies by using the last known target on that package to get the dependency information. [YOCTO #9676] (Bitbake rev: 31e7c26cc31a7c8c78c1464fa01581683bfd2965) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/toaster/orm/models.py61
-rw-r--r--bitbake/lib/toaster/toastergui/buildtables.py15
-rw-r--r--bitbake/lib/toaster/toastergui/tables.py15
-rw-r--r--bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html44
-rw-r--r--bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html46
-rw-r--r--bitbake/lib/toaster/toastergui/templatetags/projecttags.py8
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py4
7 files changed, 157 insertions, 36 deletions
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 25bc1dbe15..caad2afe81 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -862,31 +862,70 @@ class CustomImagePackage(Package):
862 related_name='appends_set') 862 related_name='appends_set')
863 863
864 864
865
866class Package_DependencyManager(models.Manager): 865class Package_DependencyManager(models.Manager):
867 use_for_related_fields = True 866 use_for_related_fields = True
867 TARGET_LATEST = "use-latest-target-for-target"
868 868
869 def get_queryset(self): 869 def get_queryset(self):
870 return super(Package_DependencyManager, self).get_queryset().exclude(package_id = F('depends_on__id')) 870 return super(Package_DependencyManager, self).get_queryset().exclude(package_id = F('depends_on__id'))
871 871
872 def get_total_source_deps_size(self): 872 def for_target_or_none(self, target):
873 """ Returns the total file size of all the packages that depend on 873 """ filter the dependencies to be displayed by the supplied target
874 thispackage. 874 if no dependences are found for the target then try None as the target
875 """ 875 which will return the dependences calculated without the context of a
876 return self.all().aggregate(Sum('depends_on__size')) 876 target e.g. non image recipes.
877 877
878 def get_total_revdeps_size(self): 878 returns: { size, packages }
879 """ Returns the total file size of all the packages that depend on
880 this package.
881 """ 879 """
882 return self.all().aggregate(Sum('package_id__size')) 880 package_dependencies = self.all_depends().order_by('depends_on__name')
883 881
882 if target is self.TARGET_LATEST:
883 installed_deps =\
884 package_dependencies.filter(~Q(target__target=None))
885 else:
886 installed_deps =\
887 package_dependencies.filter(Q(target__target=target))
888
889 packages_list = None
890 total_size = 0
891
892 # If we have installed depdencies for this package and target then use
893 # these to display
894 if installed_deps.count() > 0:
895 packages_list = installed_deps
896 total_size = installed_deps.aggregate(
897 Sum('depends_on__size'))['depends_on__size__sum']
898 else:
899 new_list = []
900 package_names = []
901
902 # Find dependencies for the package that we know about even if
903 # it's not installed on a target e.g. from a non-image recipe
904 for p in package_dependencies.filter(Q(target=None)):
905 if p.depends_on.name in package_names:
906 continue
907 else:
908 package_names.append(p.depends_on.name)
909 new_list.append(p.pk)
910 # while we're here we may as well total up the size to
911 # avoid iterating again
912 total_size += p.depends_on.size
913
914 # We want to return a queryset here for consistency so pick the
915 # deps from the new_list
916 packages_list = package_dependencies.filter(Q(pk__in=new_list))
917
918 return {'packages': packages_list,
919 'size': total_size}
884 920
885 def all_depends(self): 921 def all_depends(self):
886 """ Returns just the depends packages and not any other dep_type """ 922 """ Returns just the depends packages and not any other dep_type
923 Note that this is for any target
924 """
887 return self.filter(Q(dep_type=Package_Dependency.TYPE_RDEPENDS) | 925 return self.filter(Q(dep_type=Package_Dependency.TYPE_RDEPENDS) |
888 Q(dep_type=Package_Dependency.TYPE_TRDEPENDS)) 926 Q(dep_type=Package_Dependency.TYPE_TRDEPENDS))
889 927
928
890class Package_Dependency(models.Model): 929class Package_Dependency(models.Model):
891 TYPE_RDEPENDS = 0 930 TYPE_RDEPENDS = 0
892 TYPE_TRDEPENDS = 1 931 TYPE_TRDEPENDS = 1
diff --git a/bitbake/lib/toaster/toastergui/buildtables.py b/bitbake/lib/toaster/toastergui/buildtables.py
index 17de369305..e237e4ecb6 100644
--- a/bitbake/lib/toaster/toastergui/buildtables.py
+++ b/bitbake/lib/toaster/toastergui/buildtables.py
@@ -47,6 +47,7 @@ class BuiltPackagesTableBase(tables.PackagesTable):
47 def setup_queryset(self, *args, **kwargs): 47 def setup_queryset(self, *args, **kwargs):
48 build = Build.objects.get(pk=kwargs['build_id']) 48 build = Build.objects.get(pk=kwargs['build_id'])
49 self.static_context_extra['build'] = build 49 self.static_context_extra['build'] = build
50 self.static_context_extra['target_name'] = None
50 self.queryset = build.package_set.all().exclude(recipe=None) 51 self.queryset = build.package_set.all().exclude(recipe=None)
51 self.queryset = self.queryset.order_by(self.default_orderby) 52 self.queryset = self.queryset.order_by(self.default_orderby)
52 53
@@ -187,7 +188,15 @@ class InstalledPackagesTable(BuildTablesMixin, BuiltPackagesTableBase):
187 self.static_context_extra['build'] = build 188 self.static_context_extra['build'] = build
188 189
189 target = Target.objects.get(pk=kwargs['target_id']) 190 target = Target.objects.get(pk=kwargs['target_id'])
191 # We send these separately because in the case of image details table
192 # we don't have a target just the recipe name as the target
193 self.static_context_extra['target_name'] = target.target
194 self.static_context_extra['target_id'] = target.pk
195
196 self.static_context_extra['add_links'] = True
197
190 self.queryset = self.make_package_list(target) 198 self.queryset = self.make_package_list(target)
199 self.queryset = self.queryset.order_by(self.default_orderby)
191 200
192 def setup_columns(self, *args, **kwargs): 201 def setup_columns(self, *args, **kwargs):
193 super(InstalledPackagesTable, self).setup_columns(**kwargs) 202 super(InstalledPackagesTable, self).setup_columns(**kwargs)
@@ -195,11 +204,13 @@ class InstalledPackagesTable(BuildTablesMixin, BuiltPackagesTableBase):
195 static_data_name="installed_size", 204 static_data_name="installed_size",
196 static_data_template="{% load projecttags %}" 205 static_data_template="{% load projecttags %}"
197 "{{data.size|filtered_filesizeformat}}", 206 "{{data.size|filtered_filesizeformat}}",
198 orderable=True) 207 orderable=True,
208 hidden=True)
199 209
200 # Add the template to show installed name for installed packages 210 # Add the template to show installed name for installed packages
201 install_name_tmpl =\ 211 install_name_tmpl =\
202 ('{{data.name}} ' 212 ('<a href="{% url "package_included_detail" extra.build.pk'
213 ' extra.target_id data.pk %}">{{data.name}}</a>'
203 '{% if data.installed_name and data.installed_name !=' 214 '{% if data.installed_name and data.installed_name !='
204 ' data.name %}' 215 ' data.name %}'
205 '<span class="muted"> as {{data.installed_name}}</span>' 216 '<span class="muted"> as {{data.installed_name}}</span>'
diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py
index 902f62f708..79673f5dab 100644
--- a/bitbake/lib/toaster/toastergui/tables.py
+++ b/bitbake/lib/toaster/toastergui/tables.py
@@ -22,7 +22,7 @@
22from toastergui.widgets import ToasterTable 22from toastergui.widgets import ToasterTable
23from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project 23from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
24from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task 24from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task
25from orm.models import CustomImagePackage 25from orm.models import CustomImagePackage, Package_DependencyManager
26from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField 26from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField
27from django.conf.urls import url 27from django.conf.urls import url
28from django.core.urlresolvers import reverse, resolve 28from django.core.urlresolvers import reverse, resolve
@@ -695,6 +695,7 @@ class PackagesTable(ToasterTable):
695 695
696 def setup_queryset(self, *args, **kwargs): 696 def setup_queryset(self, *args, **kwargs):
697 recipe = Recipe.objects.get(pk=kwargs['recipe_id']) 697 recipe = Recipe.objects.get(pk=kwargs['recipe_id'])
698 self.static_context_extra['target_name'] = recipe.name
698 699
699 self.queryset = self.create_package_list(recipe, kwargs['pid']) 700 self.queryset = self.create_package_list(recipe, kwargs['pid'])
700 self.queryset = self.queryset.order_by('name') 701 self.queryset = self.queryset.order_by('name')
@@ -766,7 +767,19 @@ class SelectPackagesTable(PackagesTable):
766 767
767 self.queryset = self.queryset.order_by('name') 768 self.queryset = self.queryset.order_by('name')
768 769
770 # This target is the target used to work out which group of dependences
771 # to display, if we've built the custom image we use it otherwise we
772 # can use the based recipe instead
773 if prj.build_set.filter(target__target=self.cust_recipe.name).count()\
774 > 0:
775 self.static_context_extra['target_name'] = self.cust_recipe.name
776 else:
777 self.static_context_extra['target_name'] =\
778 Package_DependencyManager.TARGET_LATEST
779
769 self.static_context_extra['recipe_id'] = kwargs['custrecipeid'] 780 self.static_context_extra['recipe_id'] = kwargs['custrecipeid']
781
782
770 self.static_context_extra['current_packages'] = \ 783 self.static_context_extra['current_packages'] = \
771 current_packages.values_list('pk', flat=True) 784 current_packages.values_list('pk', flat=True)
772 785
diff --git a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
index 0a24e9217e..5be409ca44 100644
--- a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
+++ b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
@@ -1,14 +1,38 @@
1{# Popover that displays the dependences and sizes of a package 'data' used in the Packages table #} 1{# Popover that displays the dependences and sizes of a package 'data' used in the Packages table #}
2{% with data.package_dependencies_source.all_depends.count as dep_count %}
3{% load projecttags %} 2{% load projecttags %}
4{% if dep_count %} 3
5 <a data-content="<ul class='list-unstyled'> 4{% with package_deps=data.package_dependencies_source|for_target:extra.target_name %}
6 {% for dep in data.package_dependencies_source.all_depends %} 5{% with count_package=package_deps.packages|length %}
7 <li>{{dep.depends_on.name}} {% if dep.depends_on.size > 0 %}({{dep.depends_on.size|filtered_filesizeformat}}){% endif %}</li> 6
8 {% endfor %} 7{% if count_package > 0 %}
9 </ul>" class="btn btn-default" title=" 8 <a data-content='<ul class="unstyled">
10 <strong>{{data.name}}</strong> dependencies - <strong>{{data.package_dependencies_source.get_total_source_deps_size.depends_on__size__sum|filtered_filesizeformat}}</strong>"> 9 {% for dep in package_deps.packages %}
11 {{dep_count}} 10 <li>
12</a> 11 {% if extra.add_links %}
12 <a href="{% url 'package_included_detail' extra.build.pk extra.target_id dep.depends_on.pk %}">
13 {{dep.depends_on.name}}</a>
14 {% else %}
15 {{dep.depends_on.name}}
16 {% endif %}
17 {% if dep.depends_on.size > 0 %}
18 ({{dep.depends_on.size|filtered_filesizeformat}})
19 {% endif %}
20 </li>
21 {% endfor %}
22 </ul>' class="btn btn-default" title='
23 <strong>
24 {% if extra.add_links %}
25 <a href="{% url 'package_included_dependencies' extra.build.pk extra.target_id data.pk %}">
26 {{data.name}}</a>
27 {% else %}
28 {{data.name}}
29 {% endif %}
30 </strong>
31 dependencies -
32 <strong>{{package_deps.size|filtered_filesizeformat}}</strong>'>
33 {{count_package}}
34 </a>
13{% endif %} 35{% endif %}
36
37{% endwith %}
14{% endwith %} 38{% endwith %}
diff --git a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
index d470712121..65c2b29d0b 100644
--- a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
+++ b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
@@ -1,14 +1,38 @@
1{# Popover that displays the reverse dependencies and sizes of a package 'data' used in the Packages table #} 1{# Popover that displays the reverse dependences and sizes of a package 'data' used in the Packages table #}
2{% with data.package_dependencies_target.all_depends.count as dep_count %}
3{% load projecttags %} 2{% load projecttags %}
4{% if dep_count %} 3
5 <a data-content="<ul class='list-unstyled'> 4{% with package_deps=data.package_dependencies_target|for_target:extra.target_name %}
6 {% for dep in data.package_dependencies_target.all_depends|dictsort:'package.name' %} 5{% with count_package=package_deps.packages|length %}
7 <li>{{dep.package.name}} {% if dep.package.size > 0 %}({{dep.package.size|filtered_filesizeformat}}){% endif %}</li> 6
8 {% endfor %} 7{% if count_package > 0 %}
9 </ul>" class="btn btn-default" title=" 8 <a data-content='<ul class="unstyled">
10 <strong>{{data.name}}</strong> reverse dependencies - <strong>{{data.package_dependencies_target.get_total_revdeps_size.package_id__size__sum|filtered_filesizeformat}}</strong>"> 9 {% for dep in package_deps.packages|dictsort:"package.name" %}
11 {{dep_count}} 10 <li>
12</a> 11 {% if extra.add_links %}
12 <a href="{% url 'package_included_detail' extra.build.pk extra.target_id dep.package.pk %}">
13 {{dep.package.name}}</a>
14 {% else %}
15 {{dep.package.name}}
16 {% endif %}
17 {% if dep.package.size > 0 %}
18 ({{dep.package.size|filtered_filesizeformat}})
19 {% endif %}
20 </li>
21 {% endfor %}
22 </ul>' class="btn btn-default" title='
23 <strong>
24 {% if extra.add_links %}
25 <a href="{% url 'package_included_reverse_dependencies' extra.build.pk extra.target_id data.pk %}">
26 {{data.name}}</a>
27 {% else %}
28 {{data.name}}
29 {% endif %}
30 </strong>
31 dependencies -
32 <strong>{{package_deps.size|filtered_filesizeformat}}</strong>'>
33 {{count_package}}
34 </a>
13{% endif %} 35{% endif %}
36
37{% endwith %}
14{% endwith %} 38{% endwith %}
diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
index 1d680365ad..119311db93 100644
--- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
+++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
@@ -297,3 +297,11 @@ def cut_path_prefix(fullpath, prefixes):
297 if fullpath.startswith(prefix): 297 if fullpath.startswith(prefix):
298 return relpath(fullpath, prefix) 298 return relpath(fullpath, prefix)
299 return fullpath 299 return fullpath
300
301
302@register.filter
303def for_target(package_dependencies, target):
304 """ filter the dependencies to be displayed by the supplied target
305 if no dependences are found for the target then return the predicted
306 dependences"""
307 return package_dependencies.for_target_or_none(target)
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 88bc39a166..1f908ea209 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -2060,7 +2060,9 @@ if True:
2060 2060
2061 # Dependencies for package which aren't satisfied by the 2061 # Dependencies for package which aren't satisfied by the
2062 # current packages in the custom image recipe 2062 # current packages in the custom image recipe
2063 deps = package.package_dependencies_source.annotate( 2063 deps =\
2064 package.package_dependencies_source.for_target_or_none(
2065 recipe.name)['packages'].annotate(
2064 name=F('depends_on__name'), 2066 name=F('depends_on__name'),
2065 pk=F('depends_on__pk'), 2067 pk=F('depends_on__pk'),
2066 size=F('depends_on__size'), 2068 size=F('depends_on__size'),