diff options
author | Michael Wood <michael.g.wood@intel.com> | 2016-05-26 16:12:20 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-06-15 08:35:04 +0100 |
commit | a786ac14f1c6c02c38dc141125035445413f1250 (patch) | |
tree | 0e591f980a70afecbbde39c77e62b7f12ec4a889 /bitbake | |
parent | b63f9518e718db09e14c8287fadf0bebcdf5ec9e (diff) | |
download | openembedded-core-contrib-a786ac14f1c6c02c38dc141125035445413f1250.tar.gz |
bitbake: toaster: port table for Built packages to ToasterTable
This is the table that displays all the packages built in the build.
Build -> Packages. Adds a template snippet for the git revision popover.
(Bitbake rev: df62f38ff4e634544c9b1e97c5f6ca45e84a4f1e)
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r-- | bitbake/lib/toaster/toastergui/buildtables.py | 152 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/tables.py | 10 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/basebuildpage.html | 26 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/bpackage.html | 106 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html | 23 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/snippets/gitrev_popover.html | 8 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/urls.py | 7 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 90 |
8 files changed, 203 insertions, 219 deletions
diff --git a/bitbake/lib/toaster/toastergui/buildtables.py b/bitbake/lib/toaster/toastergui/buildtables.py new file mode 100644 index 0000000000..cf07ea8789 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/buildtables.py @@ -0,0 +1,152 @@ +# +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# BitBake Toaster Implementation +# +# Copyright (C) 2016 Intel Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from orm.models import Build +import toastergui.tables as tables + +from toastergui.widgets import ToasterTable + + +class BuildTablesMixin(ToasterTable): + def get_context_data(self, **kwargs): + # We need to be explicit about which superclass we're calling here + # Otherwise the MRO gets in a right mess + context = ToasterTable.get_context_data(self, **kwargs) + context['build'] = Build.objects.get(pk=kwargs['build_id']) + return context + + +class BuiltPackagesTableBase(tables.PackagesTable): + """ Table to display all the packages built in a build """ + def __init__(self, *args, **kwargs): + super(BuiltPackagesTableBase, self).__init__(*args, **kwargs) + self.title = "Packages built" + self.default_orderby = "name" + + def setup_queryset(self, *args, **kwargs): + build = Build.objects.get(pk=kwargs['build_id']) + self.static_context_extra['build'] = build + self.queryset = build.package_set.all().exclude(recipe=None) + self.queryset = self.queryset.order_by(self.default_orderby) + + def setup_columns(self, *args, **kwargs): + super(BuiltPackagesTableBase, self).setup_columns(*args, **kwargs) + + def pkg_link_template(val): + """ return the template used for the link with the val as the + element value i.e. inside the <a></a>""" + + return (''' + <a href=" + {%% url "package_built_detail" extra.build.pk data.pk %%} + ">%s</a> + ''' % val) + + def recipe_link_template(val): + return (''' + {%% if data.recipe %%} + <a href=" + {%% url "recipe" extra.build.pk data.recipe.pk %%} + ">%(value)s</a> + {%% else %%} + %(value)s + {%% endif %%} + ''' % {'value': val}) + + add_pkg_link_to = ['name', 'version', 'size', 'license'] + add_recipe_link_to = ['recipe__name', 'recipe__version'] + + # Add the recipe and pkg build links to the required columns + for column in self.columns: + # Convert to template field style accessors + tmplv = column['field_name'].replace('__', '.') + tmplv = "{{data.%s}}" % tmplv + + if column['field_name'] in add_pkg_link_to: + # Don't overwrite an existing template + if column['static_data_template']: + column['static_data_template'] =\ + pkg_link_template(column['static_data_template']) + else: + column['static_data_template'] = pkg_link_template(tmplv) + + column['static_data_name'] = column['field_name'] + + elif column['field_name'] in add_recipe_link_to: + # Don't overwrite an existing template + if column['static_data_template']: + column['static_data_template'] =\ + recipe_link_template(column['static_data_template']) + else: + column['static_data_template'] =\ + recipe_link_template(tmplv) + column['static_data_name'] = column['field_name'] + + self.add_column(title="Layer", + field_name="recipe__layer_version__layer__name", + hidden=True, + orderable=True) + + self.add_column(title="Layer branch", + field_name="recipe__layer_version__branch", + hidden=True, + orderable=True) + + git_rev_template = ''' + {% with vcs_ref=data.recipe.layer_version.commit %} + {% include 'snippets/gitrev_popover.html' %} + {% endwith %} + ''' + + self.add_column(title="Layer commit", + static_data_name='vcs_ref', + static_data_template=git_rev_template, + hidden=True) + + +class BuiltPackagesTable(BuildTablesMixin, BuiltPackagesTableBase): + """ Show all the packages built for the selected build """ + def __init__(self, *args, **kwargs): + super(BuiltPackagesTable, self).__init__(*args, **kwargs) + self.title = "Packages built" + self.default_orderby = "name" + + self.empty_state =\ + ('<strong>No packages were built.</strong> How did this happen?' + 'Well, BitBake reuses as much stuff as possible.' + 'If all of the packages needed were already built and available' + 'in your build infrastructure, BitBake' + 'will not rebuild any of them. This might be slightly confusing,' + 'but it does make everything faster.') + + def setup_columns(self, *args, **kwargs): + super(BuiltPackagesTable, self).setup_columns(*args, **kwargs) + + def remove_dep_cols(columns): + for column in columns: + # We don't need these fields + if column['static_data_name'] in ['reverse_dependencies', + 'dependencies']: + continue + + yield column + + self.columns = list(remove_dep_cols(self.columns)) diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py index 0cf96a0ef3..902f62f708 100644 --- a/bitbake/lib/toaster/toastergui/tables.py +++ b/bitbake/lib/toaster/toastergui/tables.py @@ -146,15 +146,8 @@ class LayersTable(ToasterTable): static_data_template=git_dir_template) revision_template = ''' - {% load projecttags %} {% with vcs_ref=data.get_vcs_reference %} - {% if vcs_ref|is_shaid %} - <a class="btn" data-content="<ul class='unstyled'> <li>{{vcs_ref}}</li> </ul>"> - {{vcs_ref|truncatechars:10}} - </a> - {% else %} - {{vcs_ref}} - {% endif %} + {% include 'snippets/gitrev_popover.html' %} {% endwith %} ''' @@ -718,6 +711,7 @@ class PackagesTable(ToasterTable): self.add_column(title="Approx Size", orderable=True, + field_name="size", static_data_name="size", static_data_template="{% load projecttags %} \ {{data.size|filtered_filesizeformat}}") diff --git a/bitbake/lib/toaster/toastergui/templates/basebuildpage.html b/bitbake/lib/toaster/toastergui/templates/basebuildpage.html index 76a602bf07..c002e42b7d 100644 --- a/bitbake/lib/toaster/toastergui/templates/basebuildpage.html +++ b/bitbake/lib/toaster/toastergui/templates/basebuildpage.html @@ -23,10 +23,19 @@ {% block localbreadcrumb %}{% endblock %} </ul> <script> - $( function () { + $(document).ready(function(){ $('#breadcrumb > li').append('<span class="divider">→</span>'); $('#breadcrumb > li:last').addClass("active"); $('#breadcrumb > li:last > span').remove(); + + $("#build-menu li a").each(function(){ + /* Set the page active state in the Build menu */ + if (window.location.href.split('?')[0] === $(this).prop("href")){ + $(this).parent().addClass("active"); + } else { + $(this).parent().removeClass("active"); + } + }); }); </script> </div> @@ -35,7 +44,7 @@ <div class="row"> <!-- begin left sidebar container --> <div id="nav" class="col-md-2"> - <ul class="nav nav-list well"> + <ul class="nav nav-list well" id="build-menu"> <li {% if request.resolver_match.url_name == 'builddashboard' %} class="active" @@ -54,25 +63,14 @@ {% block nav-configuration %} <li><a href="{% url 'configuration' build.pk %}">Configuration</a></li> {% endblock %} - {% block nav-tasks %} + <li><a href="{% url 'tasks' build.pk %}">Tasks</a></li> - {% endblock %} - {% block nav-recipes %} <li><a href="{% url 'recipes' build.pk %}">Recipes</a></li> - {% endblock %} - {% block nav-packages %} <li><a href="{% url 'packages' build.pk %}">Packages</a></li> - {% endblock %} <li class="nav-header">Performance</li> - {% block nav-buildtime %} <li><a href="{% url 'buildtime' build.pk %}">Time</a></li> - {% endblock %} - {% block nav-cputime %} <li><a href="{% url 'cputime' build.pk %}">CPU usage</a></li> - {% endblock %} - {% block nav-diskio %} <li><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li> - {% endblock %} <li class="divider"></li> diff --git a/bitbake/lib/toaster/toastergui/templates/bpackage.html b/bitbake/lib/toaster/toastergui/templates/bpackage.html deleted file mode 100644 index 575c27b3b5..0000000000 --- a/bitbake/lib/toaster/toastergui/templates/bpackage.html +++ /dev/null @@ -1,106 +0,0 @@ -{% extends "basebuildpage.html" %} - -{% load projecttags %} - -{% block title %} Packages built - {{build.target_set.all|dictsort:"target"|join:", "}} {{build.machine}} - {{build.project.name}} - Toaster {% endblock %} -{% block localbreadcrumb %} -<li>Packages</li> -{% endblock %} - -{% block nav-packages %} - <li class="active"><a href="{% url 'packages' build.pk %}">Packages</a></li> -{% endblock %} - -{% block buildinfomain %} -<div class="col-md-10"> - -{% if not request.GET.filter and not request.GET.search and not objects.paginator.count %} - -<!-- Empty - no data in database --> -<div class="page-header"> - <h1> - Packages - </h1> -</div> -<div class="alert alert-info lead"> - <strong>No packages were built.</strong> How did this happen? Well, BitBake reuses as much stuff as possible. - If all of the packages needed were already built and available in your build infrastructure, BitBake - will not rebuild any of them. This might be slightly confusing, but it does make everything faster. -</div> - -{% else %} - -<div class="page-header"> - <h1> - {% if request.GET.search and objects.paginator.count > 0 %} - {{objects.paginator.count}} package{{objects.paginator.count|pluralize}} found - {%elif request.GET.search and objects.paginator.count == 0%} - No packages found - {%else%} - Packages - {%endif%} - </h1> -</div> - - {% if objects.paginator.count == 0 %} - <div class="alert"> - <form class="no-results input-append" id="searchform"> - <input id="search" name="search" class="input-xxlarge" type="text" value="{{request.GET.search}}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="input-append-addon btn" tabindex="-1"><i class="glyphicon glyphicon-remove"></i></a>{% endif %} - <button class="btn" type="submit" value="Search">Search</button> - <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all packages</button> - </form> - </div> - - {% else %} - {% include "basetable_top.html" %} - - {% for package in objects %} - - <tr class="data"> - - <!-- Package --> - <td class="package_name"><a href="{% url "package_built_detail" build.pk package.pk %}">{{package.name}}</a></td> - <!-- Package Version --> - <td class="package_version">{%if package.version%}<a href="{% url "package_built_detail" build.pk package.pk %}">{{package.version}}-{{package.revision}}</a>{%endif%}</td> - <!-- Package Size --> - <td class="size sizecol">{{package.size|filtered_filesizeformat}}</td> - <!-- License --> - <td class="license">{{package.license}}</td> - - {%if package.recipe%} - <!-- Recipe --> - <td class="recipe__name"><a href="{% url "recipe" build.pk package.recipe.pk %}">{{package.recipe.name}}</a></td> - <!-- Recipe Version --> - <td class="recipe__version"><a href="{% url "recipe" build.pk package.recipe.pk %}">{{package.recipe.version}}</a></td> - - <!-- Layer --> - <td class="recipe__layer_version__layer__name">{{package.recipe.layer_version.layer.name}}</td> - <!-- Layer branch --> - <td class="recipe__layer_version__branch">{{package.recipe.layer_version.branch}}</td> - <!-- Layer commit --> - <td class="recipe__layer_version__layer__commit"> - <a class="btn" - data-content="<ul class='list-unstyled'> - <li>{{package.recipe.layer_version.commit}}</li> - </ul>"> - {{package.recipe.layer_version.commit|truncatechars:13}} - </a> - </td> - <!-- Layer directory --> - {%else%} - <td class="recipe__name"></td> - <td class="recipe__version"></td> - <td class="recipe__layer_version__layer__name"></td> - <td class="recipe__layer_version__branch"></td> - <td class="recipe__layer_version__layer__commit"></td> - <td class="recipe__layer_version__local_path"></td> - {%endif%} - - </tr> - {% endfor %} - - {% include "basetable_bottom.html" %} - {% endif %} {# objects.paginator.count #} -{% endif %} {# Empty #} -</div> -{% endblock %} diff --git a/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html b/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html new file mode 100644 index 0000000000..4ce5c4a8a5 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html @@ -0,0 +1,23 @@ +{% extends "basebuildpage.html" %} + +{% load projecttags %} + +{% block title %} {{title}} - {{build.target_set.all|dictsort:"target"|join:", "}} {{build.machine}} - {{build.project.name}} - Toaster {% endblock %} +{% block localbreadcrumb %} +<li>{{title}}</li> +{% endblock %} + +{% block nav-packages %} +{% endblock %} + +{% block buildinfomain %} +<div class="span10"> +{% url 'builtpackagestable' build.id as xhr_table_url %} + <div class="page-header"> + <h1> + {{title}} (<span class="table-count-{{table_name}}">0</span>) </h2> + </h1> + </div> + {% include "toastertable.html" %} +</div> +{% endblock %} diff --git a/bitbake/lib/toaster/toastergui/templates/snippets/gitrev_popover.html b/bitbake/lib/toaster/toastergui/templates/snippets/gitrev_popover.html new file mode 100644 index 0000000000..281a3bd765 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/templates/snippets/gitrev_popover.html @@ -0,0 +1,8 @@ +{% load projecttags %} +{% if vcs_ref|is_shaid %} +<a class="btn" data-content="<ul class='unstyled'> <li>{{vcs_ref}}</li> </ul>"> + {{vcs_ref|truncatechars:10}} +</a> +{% else %} +{{vcs_ref}} +{% endif %} diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 27b0baabfb..3ce0d51011 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py @@ -21,6 +21,7 @@ from django.views.generic import RedirectView, TemplateView from django.http import HttpResponseBadRequest from toastergui import tables +from toastergui import buildtables from toastergui import typeaheads from toastergui import api @@ -44,7 +45,11 @@ urlpatterns = patterns('toastergui.views', url(r'^build/(?P<build_id>\d+)/recipe/(?P<recipe_id>\d+)$', 'recipe', name='recipe'), url(r'^build/(?P<build_id>\d+)/recipe_packages/(?P<recipe_id>\d+)$', 'recipe_packages', name='recipe_packages'), - url(r'^build/(?P<build_id>\d+)/packages/$', 'bpackage', name='packages'), + url(r'^build/(?P<build_id>\d+)/packages/$', + buildtables.BuiltPackagesTable.as_view( + template_name="buildinfo-toastertable.html"), + name='packages'), + url(r'^build/(?P<build_id>\d+)/package/(?P<package_id>\d+)$', 'package_built_detail', name='package_built_detail'), url(r'^build/(?P<build_id>\d+)/package_built_dependencies/(?P<package_id>\d+)$', diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 05108975ae..de1e4139a1 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py @@ -1493,96 +1493,6 @@ def configvars(request, build_id): _set_parameters_values(pagesize, orderby, request) return response -def bpackage(request, build_id): - template = 'bpackage.html' - (pagesize, orderby) = _get_parameters_values(request, 100, 'name:+') - mandatory_parameters = { 'count' : pagesize, 'page' : 1, 'orderby' : orderby } - retval = _verify_parameters( request.GET, mandatory_parameters ) - if retval: - return _redirect_parameters( 'packages', request.GET, mandatory_parameters, build_id = build_id) - (filter_string, search_term, ordering_string) = _search_tuple(request, Package) - queryset = Package.objects.filter(build = build_id).filter(size__gte=0) - queryset = _get_queryset(Package, queryset, filter_string, search_term, ordering_string, 'name') - - packages = _build_page_range(Paginator(queryset, pagesize),request.GET.get('page', 1)) - - build = Build.objects.get( pk = build_id ) - - context = { - 'objectname': 'packages built', - 'build': build, - 'project': build.project, - 'objects' : packages, - 'default_orderby' : 'name:+', - 'tablecols':[ - { - 'name':'Package', - 'qhelp':'Packaged output resulting from building a recipe', - 'orderfield': _get_toggle_order(request, "name"), - 'ordericon':_get_toggle_order_icon(request, "name"), - }, - { - 'name':'Package version', - 'qhelp':'The package version and revision', - }, - { - 'name':'Size', - 'qhelp':'The size of the package', - 'orderfield': _get_toggle_order(request, "size", True), - 'ordericon':_get_toggle_order_icon(request, "size"), - 'orderkey' : 'size', - 'clclass': 'size', 'hidden': 0, - 'dclass' : 'span2', - }, - { - 'name':'License', - 'qhelp':'The license under which the package is distributed. Multiple license names separated by the pipe character indicates a choice between licenses. Multiple license names separated by the ampersand character indicates multiple licenses exist that cover different parts of the source', - 'orderfield': _get_toggle_order(request, "license"), - 'ordericon':_get_toggle_order_icon(request, "license"), - 'orderkey' : 'license', - 'clclass': 'license', 'hidden': 1, - }, - { - 'name':'Recipe', - 'qhelp':'The name of the recipe building the package', - 'orderfield': _get_toggle_order(request, "recipe__name"), - 'ordericon':_get_toggle_order_icon(request, "recipe__name"), - 'orderkey' : 'recipe__name', - 'clclass': 'recipe__name', 'hidden': 0, - }, - { - 'name':'Recipe version', - 'qhelp':'Version and revision of the recipe building the package', - 'clclass': 'recipe__version', 'hidden': 1, - }, - { - 'name':'Layer', - 'qhelp':'The name of the layer providing the recipe that builds the package', - 'orderfield': _get_toggle_order(request, "recipe__layer_version__layer__name"), - 'ordericon':_get_toggle_order_icon(request, "recipe__layer_version__layer__name"), - 'orderkey' : 'recipe__layer_version__layer__name', - 'clclass': 'recipe__layer_version__layer__name', 'hidden': 1, - }, - { - 'name':'Layer branch', - 'qhelp':'The Git branch of the layer providing the recipe that builds the package', - 'orderfield': _get_toggle_order(request, "recipe__layer_version__branch"), - 'ordericon':_get_toggle_order_icon(request, "recipe__layer_version__branch"), - 'orderkey' : 'recipe__layer_version__branch', - 'clclass': 'recipe__layer_version__branch', 'hidden': 1, - }, - { - 'name':'Layer commit', - 'qhelp':'The Git commit of the layer providing the recipe that builds the package', - 'clclass': 'recipe__layer_version__layer__commit', 'hidden': 1, - }, - ] - } - - response = render(request, template, context) - _set_parameters_values(pagesize, orderby, request) - return response - def bfile(request, build_id, package_id): template = 'bfile.html' files = Package_File.objects.filter(package = package_id) |