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. +
+ + + + + + + + + {% for runtime_dep in runtime_deps %} + + {% ifequal runtime_dep.version '' %} + + + + + + + {% else %} + + + + + + {% endifequal %} + + {% endfor %} +
PackageVersionSize
{{runtime_dep.name}}{{runtime_dep.version}}
+ + {{runtime_dep.name}} + + {{runtime_dep.version}}{{runtime_dep.size|filtered_filesizeformat}}
+ {% endifequal %} + {% ifnotequal other_deps|length 0 %} +

Other runtime relationships

+ + + + + + + + + + + + {% for other_dep in other_deps %} + + {% ifequal other_dep.version '' %} + + + + + + + {% else %} + + + + + + + + {% endifequal %} + {% endfor %} +
PackageVersionSize + + Relationship type +
{{other_dep.name}}{{other_dep.version}} + {{other_dep.dep_type_display}} + +
+ + {{other_dep.name}} + + {{other_dep.version}}{{other_dep.size|filtered_filesizeformat}} + {{other_dep.dep_type_display}} + +
+ {% 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. +
+ + + + + + + + {% for file in package.buildfilelist_package.all|dictsort:"path" %} + + + + + + + {% endfor %} +
FileSize
{{file.path}}{{file.size|filtered_filesizeformat}}
+ + {% else %} +
+ {{fullPackageSpec}} does not generate any files. +
+ {% endif %} + +
+
+ {% else %} + {# Included case #} +
+
+
+ Package included in: + {% for itarget in package.buildtargetlist_package.all|dictsort:"target.target" %} + + {% if forloop.counter0 > 0 %} + ,  + {% endif %} + {{itarget.target.target}} + + {% endfor %} +
+
+
+ {% 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 %} + + + + + + + + + {% for runtime_dep in runtime_deps %} + + + + + + + + {% endfor %} +
    PackageVersionSize
    + + {{runtime_dep.name}} + + {{runtime_dep.version}}{{runtime_dep.size|filtered_filesizeformat}}
    + {% else %} +
    + {{fullPackageSpec}} has no runtime dependencies. +
    + {% endifnotequal %} + + {% ifnotequal other_deps|length 0 %} +

    Other runtime relationships

    + + + + + + + + + + + {% for other_dep in other_deps %} + + {% if other_dep.installed %} + + + + + + + {% else %} + + + + + + + {% endif %} + + {% endfor %} +
    PackageVersionSize + + Relationship type +
    + + {{other_dep.name}} + + {{other_dep.version}}{{other_dep.size|filtered_filesizeformat}} + {{other_dep.dep_type_display}} + +
    {{other_dep.name}}{{other_dep.version}} + {{other_dep.dep_type_display}} + +
    + {% 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 %} + + + + + + + + {% for file in package.buildfilelist_package.all|dictsort:"path" %} + + + + + + + {% endfor %} +
    FileSize
    + + {{file.path}} + + {{file.size|filtered_filesizeformat}}
    + + {% 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 %} + + + + + + + + + {% for reverse_dep in reverse_deps|dictsort:"name" %} + + + + + + + + {% endfor %} +
    PackagePackage VersionSize
    + + {{reverse_dep.name}} + + {{reverse_dep.version}}{{reverse_dep.size|filtered_filesizeformat}}
    + {% 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)