diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 3abee016c4..113631def0 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -145,6 +145,7 @@ class Task_Dependency(models.Model):
class Package(models.Model):
+ search_allowed_fields = ['name', 'installed_name', 'section', 'summary']
build = models.ForeignKey('Build')
recipe = models.ForeignKey('Recipe', null=True)
name = models.CharField(max_length=100)
@@ -160,23 +161,39 @@ class Package(models.Model):
class Package_Dependency(models.Model):
TYPE_RDEPENDS = 0
- TYPE_RPROVIDES = 1
+ TYPE_TRDEPENDS = 1
TYPE_RRECOMMENDS = 2
- TYPE_RSUGGESTS = 3
- TYPE_RREPLACES = 4
- TYPE_RCONFLICTS = 5
- TYPE_TRDEPENDS = 6
- TYPE_TRECOMMENDS = 7
+ TYPE_TRECOMMENDS = 3
+ TYPE_RSUGGESTS = 4
+ TYPE_RPROVIDES = 5
+ TYPE_RREPLACES = 6
+ TYPE_RCONFLICTS = 7
+ ' TODO: bpackage should be changed to remove the DEPENDS_TYPE access '
DEPENDS_TYPE = (
- (TYPE_RDEPENDS, "rdepends"),
- (TYPE_RPROVIDES, "rprovides"),
- (TYPE_RRECOMMENDS, "rrecommends"),
- (TYPE_RSUGGESTS, "rsuggests"),
- (TYPE_RREPLACES, "rreplaces"),
- (TYPE_RCONFLICTS, "rconflicts"),
- (TYPE_TRDEPENDS, "trdepends"),
- (TYPE_TRECOMMENDS, "trecommends"),
+ (TYPE_RDEPENDS, "depends"),
+ (TYPE_TRDEPENDS, "depends"),
+ (TYPE_TRECOMMENDS, "recommends"),
+ (TYPE_RRECOMMENDS, "recommends"),
+ (TYPE_RSUGGESTS, "suggests"),
+ (TYPE_RPROVIDES, "provides"),
+ (TYPE_RREPLACES, "replaces"),
+ (TYPE_RCONFLICTS, "conflicts"),
)
+ ''' Indexed by dep_type, in view order, key for short name and help
+ description which when viewed will be printf'd with the
+ package name.
+ '''
+ DEPENDS_DICT = {
+ TYPE_RDEPENDS : ("depends", "%s is required to run %s"),
+ TYPE_TRDEPENDS : ("depends", "%s is required to run %s"),
+ TYPE_TRECOMMENDS : ("recommends", "%s extends the usability of %s"),
+ TYPE_RRECOMMENDS : ("recommends", "%s extends the usability of %s"),
+ TYPE_RSUGGESTS : ("suggests", "%s is suggested for installation with %s"),
+ TYPE_RPROVIDES : ("provides", "%s is provided by %s"),
+ TYPE_RREPLACES : ("replaces", "%s is replaced by %s"),
+ TYPE_RCONFLICTS : ("conflicts", "%s conflicts with %s, which will not be installed if this package is not first removed"),
+ }
+
package = models.ForeignKey(Package, related_name='package_dependencies_source')
depends_on = models.ForeignKey(Package, related_name='package_dependencies_target') # soft dependency
dep_type = models.IntegerField(choices=DEPENDS_TYPE)
@@ -184,7 +201,7 @@ class Package_Dependency(models.Model):
class Target_Installed_Package(models.Model):
target = models.ForeignKey(Target)
- package = models.ForeignKey(Package)
+ package = models.ForeignKey(Package, related_name='buildtargetlist_package')
class Package_File(models.Model):
package = models.ForeignKey(Package, related_name='buildfilelist_package')
diff --git a/bitbake/lib/toaster/toastergui/templates/bpackage.html b/bitbake/lib/toaster/toastergui/templates/bpackage.html
index 3329ddae51..b78ae4644f 100644
--- a/bitbake/lib/toaster/toastergui/templates/bpackage.html
+++ b/bitbake/lib/toaster/toastergui/templates/bpackage.html
@@ -26,7 +26,7 @@
{% for package in objects %}
- | {{package.name}} ({{package.filelist_bpackage.count}} files) |
+ {{package.name}} ({{package.filelist_bpackage.count}} files) |
{{package.version}}-{{package.revision}} |
{%if package.recipe%}{{package.recipe.name}}{{package.package_name}}{%endif%} |
diff --git a/bitbake/lib/toaster/toastergui/templates/package_built_dependencies.html b/bitbake/lib/toaster/toastergui/templates/package_built_dependencies.html
new file mode 100644
index 0000000000..c67f60e20b
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/package_built_dependencies.html
@@ -0,0 +1,112 @@
+{% extends "package_detail_base.html" %}
+{% load projecttags %}
+
+{% block tabcontent %}
+ {% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec %}
+
+
+
+ {% ifequal runtime_deps|length 0 %}
+
+ {{fullPackageSpec}} has no runtime dependencies.
+
+ {% else %}
+
+ {{fullPackageSpec}} is not included in any image. These are its projected runtime dependencies if you were to include it in future builds.
+
+
+
+
+ | Package |
+ Version |
+ Size |
+
+
+ {% for runtime_dep in runtime_deps %}
+
+ {% ifequal runtime_dep.version '' %}
+
+ | {{runtime_dep.name}} |
+ {{runtime_dep.version}} |
+ |
+
+
+ {% else %}
+
+ |
+
+ {{runtime_dep.name}}
+
+ |
+ {{runtime_dep.version}} |
+ {{runtime_dep.size|filtered_filesizeformat}} |
+
+ {% endifequal %}
+
+ {% endfor %}
+
+ {% endifequal %}
+ {% ifnotequal other_deps|length 0 %}
+
Other runtime relationships
+
+
+
+ | Package |
+ Version |
+ Size |
+
+
+
+ Relationship type
+ |
+
+
+
+ {% for other_dep in other_deps %}
+
+ {% ifequal other_dep.version '' %}
+
+ | {{other_dep.name}} |
+ {{other_dep.version}} |
+ |
+
+ {{other_dep.dep_type_display}}
+
+ |
+
+ {% else %}
+
+ |
+
+ {{other_dep.name}}
+
+ |
+ {{other_dep.version}} |
+ {{other_dep.size|filtered_filesizeformat}} |
+
+ {{other_dep.dep_type_display}}
+
+ |
+
+
+ {% endifequal %}
+ {% endfor %}
+
+ {% endifnotequal %}
+
+
+ {% endwith %}
+{% endblock tabcontent %}
diff --git a/bitbake/lib/toaster/toastergui/templates/package_built_detail.html b/bitbake/lib/toaster/toastergui/templates/package_built_detail.html
new file mode 100644
index 0000000000..fe856a3cb6
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/package_built_detail.html
@@ -0,0 +1,71 @@
+{% extends "package_detail_base.html" %}
+{% load projecttags %}
+
+{% block tabcontent %}
+ {% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec packageFileCount=package.buildfilelist_package.count %}
+
+ {% if package.buildtargetlist_package.count == 0 %}
+ {# Not included case #}
+
+
+
+
+ {% if packageFileCount > 0 %}
+
+ {{fullPackageSpec}} is not included in any image. These are the files that would be added to an image root file system if you were to include it in future builds.
+
+
+
+
+ | File |
+ Size |
+
+
+ {% for file in package.buildfilelist_package.all|dictsort:"path" %}
+
+
+ | {{file.path}} |
+ {{file.size|filtered_filesizeformat}} |
+
+
+ {% endfor %}
+
+
+ {% else %}
+
+ {{fullPackageSpec}} does not generate any files.
+
+ {% endif %}
+
+
+
+ {% else %}
+ {# Included case #}
+
+ {% endif %}
+
+ {% endwith %}
+{% endblock tabcontent %}
diff --git a/bitbake/lib/toaster/toastergui/templates/package_detail_base.html b/bitbake/lib/toaster/toastergui/templates/package_detail_base.html
new file mode 100644
index 0000000000..a7aaab6de7
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/package_detail_base.html
@@ -0,0 +1,125 @@
+{% extends "basebuilddetailpage.html" %}
+{% load projecttags %}
+
+{% block localbreadcrumb %}
+{% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec %}
+ {% if target %}
+ {{target.target}}
+ {% else %}
+ Packages
+ {% endif %}
+ {{fullPackageSpec}}
+{% endwith %}
+{% endblock localbreadcrumb %}
+
+{% block pagedetailinfomain %}
+{% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec %}
+
+
+
+
+
+ {% block twocolumns %}
+
+ {% block tabcontent %}
+ {% endblock tabcontent %}
+
+
+
+
Package information
+
+
+
+ -
+ Size
+
+
+ -
+ {% comment %}
+ if recipe is absent, filesize is not 0
+ {% endcomment %}
+ {% if package.recipe_id > 0 %}
+ {{package.size|filtered_filesizeformat}}
+ {% if target.file_size %}
+ ({{package.size|multiply:100|divide:target.file_size}}% of included package size)
+ {% endif %}
+
+ {% endif %}
+
+
+ -
+ License
+
+
+ - {{package.license}}
+
+ {% comment %}
+ # Removed per review on 1/18/2014 until license data population
+ # problemse are resolved.
+ -
+ License files
+
+
+
+ {% endcomment %}
+
+ -
+ Recipe
+
+
+ -
+ {% if package.recipe_id > 0 %}
+ {{package.recipe.name}}
+ {% else %}
+ {{package.recipe.name}}
+ {% endif %}
+
+
+ -
+ Recipe version
+
+
+ - {{package.recipe.version}}
+
+ -
+ Layer
+
+
+ -
+ {{package.recipe.layer_version.layer.name}}
+ {% if package.recipe.layer_version.layer.name|format_none_and_zero != "" %}
+ {% comment %}
+ # Removed per team meeting of 1/29/2014 until
+ # decision on index search algorithm
+
+
+ {% endcomment %}
+
+ {% endif %}
+
+
+ -
+ Layer branch
+
+
+ - {{package.recipe.layer_version.branch}}
+ -
+ Layer commit
+
+
+
+ - {{package.recipe.layer_version.commit}}
+ -
+ Layer directory
+
+
+ {{package.recipe.layer_version.layer.local_path}}
+
+
+ {% endblock twocolumns %}
+{% endwith %}
+{% endblock pagedetailinfomain %}
diff --git a/bitbake/lib/toaster/toastergui/templates/package_included_dependencies.html b/bitbake/lib/toaster/toastergui/templates/package_included_dependencies.html
new file mode 100644
index 0000000000..c8c2dddf29
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/package_included_dependencies.html
@@ -0,0 +1,93 @@
+{% extends "package_detail_base.html" %}
+{% load projecttags %}
+
+{% block title %}
+ {% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec %}
+ {{fullPackageSpec}} ({{target.target}})
+ {% endwith %}
+{% endblock title %}
+
+{% block tabcontent %}
+ {% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec packageFileCount=package.buildfilelist_package.count %}
+ {% include "package_included_tabs.html" with active_tab="dependencies" %}
+
+
+ {% ifnotequal runtime_deps|length 0 %}
+
+
+
+ | Package |
+ Version |
+ Size |
+
+
+ {% for runtime_dep in runtime_deps %}
+
+
+ |
+
+ {{runtime_dep.name}}
+
+ |
+ {{runtime_dep.version}} |
+ {{runtime_dep.size|filtered_filesizeformat}} |
+
+
+ {% endfor %}
+
+ {% else %}
+
+ {{fullPackageSpec}} has no runtime dependencies.
+
+ {% endifnotequal %}
+
+ {% ifnotequal other_deps|length 0 %}
+
Other runtime relationships
+
+
+
+ | Package |
+ Version |
+ Size |
+
+
+ Relationship type
+ |
+
+
+
+ {% for other_dep in other_deps %}
+
+ {% if other_dep.installed %}
+
+ |
+
+ {{other_dep.name}}
+
+ |
+ {{other_dep.version}} |
+ {{other_dep.size|filtered_filesizeformat}} |
+
+ {{other_dep.dep_type_display}}
+
+ |
+
+ {% else %}
+
+ | {{other_dep.name}} |
+ {{other_dep.version}} |
+ |
+
+ {{other_dep.dep_type_display}}
+
+ |
+
+ {% endif %}
+
+ {% endfor %}
+
+ {% endifnotequal %}
+
+
+ {% endwith %}
+{% endblock tabcontent %}
diff --git a/bitbake/lib/toaster/toastergui/templates/package_included_detail.html b/bitbake/lib/toaster/toastergui/templates/package_included_detail.html
new file mode 100644
index 0000000000..018de3eb42
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/package_included_detail.html
@@ -0,0 +1,46 @@
+{% extends "package_detail_base.html" %}
+{% load projecttags %}
+
+{% block title %}
+{% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec %}
+ {{fullPackageSpec}} ({{target.target}})
+{% endwith %}
+{% endblock title %}
+
+{% block tabcontent %}
+{% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec packageFileCount=package.buildfilelist_package.count %}
+ {% include "package_included_tabs.html" with active_tab="detail" %}
+
+
+ {% if packageFileCount > 0 %}
+
+
+
+ | File |
+ Size |
+
+
+ {% for file in package.buildfilelist_package.all|dictsort:"path" %}
+
+
+ |
+
+ {{file.path}}
+
+ |
+ {{file.size|filtered_filesizeformat}} |
+
+
+ {% endfor %}
+
+
+ {% else %}
+
+ {{fullPackageSpec}} does not generate any files.
+
+ {% endif %}
+
+
+
+{% endwith %}
+{% endblock tabcontent %}
diff --git a/bitbake/lib/toaster/toastergui/templates/package_included_reverse_dependencies.html b/bitbake/lib/toaster/toastergui/templates/package_included_reverse_dependencies.html
new file mode 100644
index 0000000000..9cfc7fe7c2
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/package_included_reverse_dependencies.html
@@ -0,0 +1,47 @@
+{% extends "package_detail_base.html" %}
+{% load projecttags %}
+
+{% block title %}
+ {% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec %}
+ {{fullPackageSpec}} ({{target.target}})
+ {% endwith %}
+{% endblock title %}
+
+{% block tabcontent %}
+ {% with fullPackageSpec=package.name|add:"-"|add:package.version|add:"-"|add:package.revision|filtered_packagespec packageFileCount=package.buildfilelist_package.count %}
+ {% include "package_included_tabs.html" with active_tab="reverse" %}
+
+
+
+ {% ifequal reverse_deps|length 0 %}
+
+ {{fullPackageSpec}} has no reverse runtime dependencies.
+
+ {% else %}
+
+
+
+ | Package |
+ Package Version |
+ Size |
+
+
+ {% for reverse_dep in reverse_deps|dictsort:"name" %}
+
+
+ |
+
+ {{reverse_dep.name}}
+
+ |
+ {{reverse_dep.version}} |
+ {{reverse_dep.size|filtered_filesizeformat}} |
+
+
+ {% endfor %}
+
+ {% endifequal %}
+
+
+ {% endwith %}
+{% endblock tabcontent %}
diff --git a/bitbake/lib/toaster/toastergui/templates/package_included_tabs.html b/bitbake/lib/toaster/toastergui/templates/package_included_tabs.html
new file mode 100644
index 0000000000..5a97ba36b3
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/package_included_tabs.html
@@ -0,0 +1,33 @@
+
+
diff --git a/bitbake/lib/toaster/toastergui/templates/recipe.html b/bitbake/lib/toaster/toastergui/templates/recipe.html
index 5dea75382f..eba15baad3 100644
--- a/bitbake/lib/toaster/toastergui/templates/recipe.html
+++ b/bitbake/lib/toaster/toastergui/templates/recipe.html
@@ -161,9 +161,9 @@
{% for package in packages %}
- | {{package.name}} |
- {{package.version}}-{{package.revision}} |
- {{package.size}} |
+ {{package.name}} |
+ {{package.version}}_{{package.revision}} |
+ {{package.size}} |
{% endfor %}
diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
index 5105be48d2..667bc38420 100644
--- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
+++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
@@ -20,8 +20,10 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from datetime import datetime, timedelta
+import re
from django import template
from django.utils import timezone
+from django.template.defaultfilters import filesizeformat
register = template.Library()
@@ -101,3 +103,14 @@ def format_none_and_zero(value):
"""Return empty string if the value is None, zero or Not Applicable
"""
return "" if (not value) or (value == 0) or (value == "0") or (value == 'Not Applicable') else value
+
+@register.filter
+def filtered_filesizeformat(value):
+ """Change output from fileformatsize to suppress trailing '.0' and change 'bytes' to 'B'
+ """
+ return filesizeformat(value).replace("bytes", "B").replace(".0", "")
+
+@register.filter
+def filtered_packagespec(value):
+ """Strip off empty version and revision"""
+ return re.sub(r'(--$)', '', value)
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index 6e7595b087..8be27b08bc 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -1,7 +1,4 @@
#
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
# BitBake Toaster Implementation
#
# Copyright (C) 2013 Intel Corporation
@@ -35,7 +32,16 @@ urlpatterns = patterns('toastergui.views',
url(r'^build/(?P\d+)/recipe/(?P\d+)$', 'recipe', name='recipe'),
url(r'^build/(?P\d+)/packages/$', 'bpackage', name='packages'),
- url(r'^build/(?P\d+)/package/(?P\d+)$', 'bfile', name='package'),
+ url(r'^build/(?P\d+)/package/(?P\d+)$', 'package_built_detail',
+ name='package_built_detail'),
+ url(r'^build/(?P\d+)/package_built_dependencies/(?P\d+)$',
+ 'package_built_dependencies', name='package_built_dependencies'),
+ url(r'^build/(?P\d+)/package_included_detail/(?P\d+)/(?P\d+)$',
+ 'package_included_detail', name='package_included_detail'),
+ url(r'^build/(?P\d+)/package_included_dependencies/(?P\d+)/(?P\d+)$',
+ 'package_included_dependencies', name='package_included_dependencies'),
+ url(r'^build/(?P\d+)/package_included_reverse_dependencies/(?P\d+)/(?P\d+)$',
+ 'package_included_reverse_dependencies', name='package_included_reverse_dependencies'),
# images are known as targets in the internal model
url(r'^build/(?P\d+)/target/(?P\d+)$', 'target', name='target'),
@@ -47,6 +53,10 @@ urlpatterns = patterns('toastergui.views',
url(r'^build/(?P\d+)/cpuusage$', 'cpuusage', name='cpuusage'),
url(r'^build/(?P\d+)/diskio$', 'diskio', name='diskio'),
+ # image information dir - not yet implemented
+ url(r'^build/(?P\d+)/target/(?P\d+)/packagefile/(?P\d+)$',
+ 'image_information_dir', name='image_information_dir'),
+
# urls not linked from the dashboard
url(r'^layers/$', 'layer', name='all-layers'),
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 7b84df3340..37e2af2574 100644
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -378,15 +378,6 @@ def recipe(request, build_id, recipe_id):
}
return render(request, template, context)
-def package(request, build_id, package_id):
- template = "singlepackage.html"
- if Build.objects.filter(pk=build_id).count() == 0 :
- return redirect(builds)
- context = {
- 'build' : Build.objects.filter(pk=build_id)[0],
- }
- return render(request, template, context)
-
def target(request, build_id, target_id):
template = "target.html"
if Build.objects.filter(pk=build_id).count() == 0 :
@@ -705,4 +696,191 @@ def layer_versions_recipes(request, layerversion_id):
return render(request, template, context)
+# A set of dependency types valid for both included and built package views
+OTHER_DEPENDS_BASE = [
+ Package_Dependency.TYPE_RSUGGESTS,
+ Package_Dependency.TYPE_RPROVIDES,
+ Package_Dependency.TYPE_RREPLACES,
+ Package_Dependency.TYPE_RCONFLICTS,
+ ]
+
+# value for invalid row id
+INVALID_KEY = -1
+
+"""
+Given a package id, target_id retrieves two sets of this image and package's
+dependencies. The return value is a dictionary consisting of two other
+lists: a list of 'runtime' dependencies, that is, having RDEPENDS
+values in source package's recipe, and a list of other dependencies, that is
+the list of possible recipe variables as found in OTHER_DEPENDS_BASE plus
+the RRECOMENDS or TRECOMENDS value.
+The lists are built in the sort order specified for the package runtime
+dependency views.
+"""
+def get_package_dependencies(package_id, target_id = INVALID_KEY):
+ runtime_deps = []
+ other_deps = []
+ other_depends_types = OTHER_DEPENDS_BASE
+
+ if target_id != INVALID_KEY :
+ rdepends_type = Package_Dependency.TYPE_TRDEPENDS
+ other_depends_types += [Package_Dependency.TYPE_TRECOMMENDS]
+ else :
+ rdepends_type = Package_Dependency.TYPE_RDEPENDS
+ other_depends_types += [Package_Dependency.TYPE_RRECOMMENDS]
+
+ package = Package.objects.get(pk=package_id)
+ if target_id != INVALID_KEY :
+ alldeps = package.package_dependencies_source.filter(target_id__exact = target_id)
+ else :
+ alldeps = package.package_dependencies_source.all()
+ for idep in alldeps:
+ dep_package = Package.objects.get(pk=idep.depends_on_id)
+ dep_entry = Package_Dependency.DEPENDS_DICT[idep.dep_type]
+ if dep_package.version == '' :
+ version = ''
+ else :
+ version = dep_package.version + "-" + dep_package.revision
+ installed = False
+ if target_id != INVALID_KEY :
+ if Target_Installed_Package.objects.filter(target_id__exact = target_id, package_id__exact = dep_package.id).count() > 0:
+ installed = True
+ dep = {
+ 'name' : dep_package.name,
+ 'version' : version,
+ 'size' : dep_package.size,
+ 'dep_type' : idep.dep_type,
+ 'dep_type_display' : dep_entry[0].capitalize(),
+ 'dep_type_help' : dep_entry[1] % (dep_package.name, package.name),
+ 'depends_on_id' : dep_package.id,
+ 'installed' : installed,
+ }
+ if idep.dep_type == rdepends_type :
+ runtime_deps.append(dep)
+ elif idep.dep_type in other_depends_types :
+ other_deps.append(dep)
+
+ rdep_sorted = sorted(runtime_deps, key=lambda k: k['name'])
+ odep_sorted = sorted(
+ sorted(other_deps, key=lambda k: k['name']),
+ key=lambda k: k['dep_type'])
+ retvalues = {'runtime_deps' : rdep_sorted, 'other_deps' : odep_sorted}
+ return retvalues
+
+# Return the count of packages dependent on package for this target_id image
+def get_package_reverse_dep_count(package, target_id):
+ return package.package_dependencies_target.filter(target_id__exact=target_id, dep_type__exact = Package_Dependency.TYPE_TRDEPENDS).count()
+
+# Return the count of the packages that this package_id is dependent on.
+# Use one of the two RDEPENDS types, either TRDEPENDS if the package was
+# installed, or else RDEPENDS if only built.
+def get_package_dependency_count(package, target_id, is_installed):
+ if is_installed :
+ return package.package_dependencies_source.filter(target_id__exact = target_id,
+ dep_type__exact = Package_Dependency.TYPE_TRDEPENDS).count()
+ else :
+ return package.package_dependencies_source.filter(dep_type__exact = Package_Dependency.TYPE_RDEPENDS).count()
+
+def package_built_detail(request, build_id, package_id):
+ template = "package_built_detail.html"
+ if Build.objects.filter(pk=build_id).count() == 0 :
+ return redirect(builds)
+ package = Package.objects.filter(pk=package_id)[0]
+ context = {
+ 'build' : Build.objects.filter(pk=build_id)[0],
+ 'package' : package,
+ 'dependency_count' : get_package_dependency_count(package, -1, False),
+ }
+ return render(request, template, context)
+
+def package_built_dependencies(request, build_id, package_id):
+ template = "package_built_dependencies.html"
+ if Build.objects.filter(pk=build_id).count() == 0 :
+ return redirect(builds)
+
+ package = Package.objects.filter(pk=package_id)[0]
+ dependencies = get_package_dependencies(package_id)
+ context = {
+ 'build' : Build.objects.filter(pk=build_id)[0],
+ 'package' : package,
+ 'runtime_deps' : dependencies['runtime_deps'],
+ 'other_deps' : dependencies['other_deps'],
+ 'dependency_count' : get_package_dependency_count(package, -1, False)
+ }
+ return render(request, template, context)
+
+
+def package_included_detail(request, build_id, target_id, package_id):
+ template = "package_included_detail.html"
+ if Build.objects.filter(pk=build_id).count() == 0 :
+ return redirect(builds)
+
+ package = Package.objects.filter(pk=package_id)[0]
+ target = Target.objects.filter(pk=target_id)[0]
+ context = {
+ 'build' : Build.objects.filter(pk=build_id)[0],
+ 'target' : target,
+ 'package' : package,
+ 'reverse_count' : get_package_reverse_dep_count(package, target_id),
+ 'dependency_count' : get_package_dependency_count(package, target_id, True)
+ }
+ return render(request, template, context)
+
+def package_included_dependencies(request, build_id, target_id, package_id):
+ template = "package_included_dependencies.html"
+ if Build.objects.filter(pk=build_id).count() == 0 :
+ return redirect(builds)
+
+ package = Package.objects.filter(pk=package_id)[0]
+ target = Target.objects.filter(pk=target_id)[0]
+
+ dependencies = get_package_dependencies(package_id, target_id)
+ context = {
+ 'build' : Build.objects.filter(pk=build_id)[0],
+ 'package' : package,
+ 'target' : target,
+ 'runtime_deps' : dependencies['runtime_deps'],
+ 'other_deps' : dependencies['other_deps'],
+ 'reverse_count' : get_package_reverse_dep_count(package, target_id),
+ 'dependency_count' : get_package_dependency_count(package, target_id, True)
+ }
+ return render(request, template, context)
+
+def package_included_reverse_dependencies(request, build_id, target_id, package_id):
+ template = "package_included_reverse_dependencies.html"
+ if Build.objects.filter(pk=build_id).count() == 0 :
+ return redirect(builds)
+
+ package = Package.objects.filter(pk=package_id)[0]
+ target = Target.objects.filter(pk=target_id)[0]
+
+ reverse_deps = []
+ alldeps = package.package_dependencies_target.filter(target_id__exact=target_id)
+ for idep in alldeps:
+ dep_package = Package.objects.get(pk=idep.package_id)
+ version = dep_package.version
+ if version != '' :
+ version += '-' + dep_package.revision
+ dep = {
+ 'name' : dep_package.name,
+ 'dependent_id' : dep_package.id,
+ 'version' : version,
+ 'size' : dep_package.size
+ }
+ if idep.dep_type == Package_Dependency.TYPE_TRDEPENDS :
+ reverse_deps.append(dep)
+
+ context = {
+ 'build' : Build.objects.filter(pk=build_id)[0],
+ 'package' : package,
+ 'target' : target,
+ 'reverse_deps' : reverse_deps,
+ 'reverse_count' : get_package_reverse_dep_count(package, target_id),
+ 'dependency_count' : get_package_dependency_count(package, target_id, True)
+ }
+ return render(request, template, context)
+
+def image_information_dir(request, build_id, target_id, packagefile_id):
+ # stubbed for now
+ return redirect(builds)