mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-05 13:14:46 +02:00
update_layer.py: Save and show recipe dependencies
Added a model for the PACKAGECONFIG variable, which has a one to many relationship with the Recipe model. Added models for static build dependencies and dynamic build dependenices, both of which have a many to many relationship with the Recipe model. These objects are created in update_layer.py and are displayed on the Recipe detail page. Added a depends search option for recipes, allowing users to search for recipes based on the recipe's build dependencies. Fixes [YOCTO #12129] Fixes [YOCTO #11415] Signed-off-by: Amanda Brindle <amanda.r.brindle@intel.com>
This commit is contained in:
parent
a64bfed81b
commit
5817a0319e
|
@ -89,12 +89,27 @@ class LayerUpdateAdmin(admin.ModelAdmin):
|
|||
class RecipeAdmin(admin.ModelAdmin):
|
||||
search_fields = ['filename', 'pn']
|
||||
list_filter = ['layerbranch__layer__name', 'layerbranch__branch__name']
|
||||
readonly_fields = [fieldname for fieldname in Recipe._meta.get_all_field_names() if fieldname not in ['recipefiledependency', 'classicrecipe']]
|
||||
readonly_fields = [fieldname for fieldname in Recipe._meta.get_all_field_names() if fieldname not in ['recipefiledependency', 'classicrecipe', 'packageconfig']]
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
class PackageConfigAdmin(admin.ModelAdmin):
|
||||
search_fields = ['feature']
|
||||
list_display = ('feature',)
|
||||
ordering = ('feature',)
|
||||
|
||||
class StaticBuildDepAdmin(admin.ModelAdmin):
|
||||
search_fields = ['name']
|
||||
list_display = ('name',)
|
||||
filter_horizontal = ('recipes',)
|
||||
|
||||
class DynamicBuildDepAdmin(admin.ModelAdmin):
|
||||
search_fields = ['name']
|
||||
list_display = ('name',)
|
||||
filter_horizontal = ('package_configs',)
|
||||
|
||||
class ClassicRecipeAdmin(admin.ModelAdmin):
|
||||
search_fields = ['filename', 'pn']
|
||||
list_filter = ['layerbranch__layer__name', 'layerbranch__branch__name']
|
||||
|
@ -159,6 +174,9 @@ admin.site.register(LayerDependency, LayerDependencyAdmin)
|
|||
admin.site.register(LayerNote, LayerNoteAdmin)
|
||||
admin.site.register(Update, UpdateAdmin)
|
||||
admin.site.register(LayerUpdate, LayerUpdateAdmin)
|
||||
admin.site.register(PackageConfig, PackageConfigAdmin)
|
||||
admin.site.register(StaticBuildDep, StaticBuildDepAdmin)
|
||||
admin.site.register(DynamicBuildDep, DynamicBuildDepAdmin)
|
||||
admin.site.register(Recipe, RecipeAdmin)
|
||||
admin.site.register(RecipeFileDependency)
|
||||
admin.site.register(Machine, MachineAdmin)
|
||||
|
|
50
layerindex/migrations/0010_add_dependencies.py
Normal file
50
layerindex/migrations/0010_add_dependencies.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('layerindex', '0009_layerbranch_collection'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DynamicBuildDep',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
|
||||
('name', models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PackageConfig',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
|
||||
('feature', models.CharField(max_length=255)),
|
||||
('with_option', models.CharField(max_length=255, blank=True)),
|
||||
('without_option', models.CharField(max_length=255, blank=True)),
|
||||
('build_deps', models.CharField(max_length=255, blank=True)),
|
||||
('recipe', models.ForeignKey(to='layerindex.Recipe')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StaticBuildDep',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('recipes', models.ManyToManyField(to='layerindex.Recipe')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='dynamicbuilddep',
|
||||
name='package_configs',
|
||||
field=models.ManyToManyField(to='layerindex.PackageConfig'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='dynamicbuilddep',
|
||||
name='recipes',
|
||||
field=models.ManyToManyField(to='layerindex.Recipe'),
|
||||
),
|
||||
]
|
|
@ -357,6 +357,30 @@ class Recipe(models.Model):
|
|||
def __str__(self):
|
||||
return os.path.join(self.filepath, self.filename)
|
||||
|
||||
class PackageConfig(models.Model):
|
||||
recipe = models.ForeignKey(Recipe)
|
||||
feature = models.CharField(max_length=255)
|
||||
with_option = models.CharField(max_length=255, blank=True)
|
||||
without_option = models.CharField(max_length=255, blank=True)
|
||||
build_deps = models.CharField(max_length=255, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s" % (self.recipe, self.feature)
|
||||
|
||||
class StaticBuildDep(models.Model):
|
||||
recipes = models.ManyToManyField(Recipe)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class DynamicBuildDep(models.Model):
|
||||
package_configs = models.ManyToManyField(PackageConfig)
|
||||
recipes = models.ManyToManyField(Recipe)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class RecipeFileDependency(models.Model):
|
||||
recipe = models.ForeignKey(Recipe)
|
||||
|
|
|
@ -57,6 +57,7 @@ def split_recipe_fn(path):
|
|||
|
||||
def update_recipe_file(tinfoil, data, path, recipe, layerdir_start, repodir):
|
||||
fn = str(os.path.join(path, recipe.filename))
|
||||
from layerindex.models import PackageConfig, StaticBuildDep, DynamicBuildDep
|
||||
try:
|
||||
logger.debug('Updating recipe %s' % fn)
|
||||
if hasattr(tinfoil, 'parse_recipe_file'):
|
||||
|
@ -81,6 +82,43 @@ def update_recipe_file(tinfoil, data, path, recipe, layerdir_start, repodir):
|
|||
recipe.blacklisted = envdata.getVarFlag('PNBLACKLIST', recipe.pn, True) or ""
|
||||
recipe.save()
|
||||
|
||||
# Handle static build dependencies for this recipe
|
||||
static_dependencies = envdata.getVar("DEPENDS", True) or ""
|
||||
for dep in static_dependencies.split():
|
||||
static_build_dependency = StaticBuildDep.objects.get_or_create(name=dep)
|
||||
static_build_dependency[0].save()
|
||||
static_build_dependency[0].recipes.add(recipe)
|
||||
|
||||
# Handle the PACKAGECONFIG variables for this recipe
|
||||
package_config_VarFlags = envdata.getVarFlags("PACKAGECONFIG")
|
||||
for key, value in package_config_VarFlags.items():
|
||||
if key == "doc":
|
||||
continue
|
||||
package_config = PackageConfig()
|
||||
package_config.feature = key
|
||||
package_config.recipe = recipe
|
||||
package_config_vals = value.split(",")
|
||||
try:
|
||||
package_config.build_deps = package_config_vals[2]
|
||||
except IndexError:
|
||||
pass
|
||||
try:
|
||||
package_config.with_option = package_config_vals[0]
|
||||
except IndexError:
|
||||
pass
|
||||
try:
|
||||
package_config.without_option = package_config_vals[1]
|
||||
except IndexError:
|
||||
pass
|
||||
package_config.save()
|
||||
# Handle the dynamic dependencies for the PACKAGECONFIG variable
|
||||
if package_config.build_deps:
|
||||
for dep in package_config.build_deps.split():
|
||||
dynamic_build_dependency = DynamicBuildDep.objects.get_or_create(name=dep)
|
||||
dynamic_build_dependency[0].save()
|
||||
dynamic_build_dependency[0].package_configs.add(package_config)
|
||||
dynamic_build_dependency[0].recipes.add(recipe)
|
||||
|
||||
# Get file dependencies within this layer
|
||||
deps = envdata.getVar('__depends', True)
|
||||
filedeps = []
|
||||
|
|
|
@ -10,7 +10,7 @@ from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidde
|
|||
from django.core.urlresolvers import reverse, reverse_lazy, resolve
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.template import RequestContext
|
||||
from layerindex.models import Branch, LayerItem, LayerMaintainer, LayerBranch, LayerDependency, LayerNote, Update, LayerUpdate, Recipe, Machine, Distro, BBClass, BBAppend, RecipeChange, RecipeChangeset, ClassicRecipe
|
||||
from layerindex.models import Branch, LayerItem, LayerMaintainer, LayerBranch, LayerDependency, LayerNote, Update, LayerUpdate, Recipe, Machine, Distro, BBClass, BBAppend, RecipeChange, RecipeChangeset, ClassicRecipe, StaticBuildDep, DynamicBuildDep
|
||||
from datetime import datetime
|
||||
from django.views.generic import TemplateView, DetailView, ListView
|
||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
||||
|
@ -428,6 +428,19 @@ class RecipeSearchView(ListView):
|
|||
for item in query_items:
|
||||
if item.startswith('inherits:'):
|
||||
inherits.append(item.split(':')[1])
|
||||
|
||||
# support searches by build dependencies
|
||||
elif item.startswith('depends:'):
|
||||
depsearch = item.split(':')[1]
|
||||
qobj = Q(pk__in=[])
|
||||
static_build_dependencies = StaticBuildDep.objects.filter(name=depsearch).first()
|
||||
dynamic_build_dependencies = DynamicBuildDep.objects.filter(name=depsearch).first()
|
||||
if static_build_dependencies:
|
||||
qobj |= Q(staticbuilddep=static_build_dependencies)
|
||||
if dynamic_build_dependencies:
|
||||
qobj |= Q(dynamicbuilddep=dynamic_build_dependencies)
|
||||
init_qs = init_qs.filter(qobj).distinct()
|
||||
|
||||
# support searches by layer name
|
||||
elif item.startswith('layer:'):
|
||||
query_layername = item.split(':')[1].strip().lower()
|
||||
|
@ -845,6 +858,8 @@ class RecipeDetailView(DetailView):
|
|||
if append.matches_recipe(recipe):
|
||||
verappends.append(append)
|
||||
context['verappends'] = verappends
|
||||
context['packageconfigs'] = recipe.packageconfig_set.order_by('feature')
|
||||
context['staticdependencies'] = recipe.staticbuilddep_set.order_by('name')
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
@ -112,6 +112,39 @@
|
|||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Dependencies <i class="icon-exclamation-sign" data-toggle="tooltip" title="NOTE: Dependencies may vary based on configuration"></i></th>
|
||||
<td>
|
||||
{% if staticdependencies %}
|
||||
<ul class="unstyled">
|
||||
{% for dep in staticdependencies %}
|
||||
<li> {{dep.name}} </li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% if packageconfigs %}
|
||||
<ul class="unstyled">
|
||||
{% for pc in packageconfigs %}
|
||||
{% for dep in pc.dynamicbuilddep_set.all %}
|
||||
<li> {{dep.name}}<i class="icon-cog" data-toggle="tooltip" title="If "{{pc.feature}}" is set in PACKAGECONFIG"></i></li>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PACKAGECONFIG options</th>
|
||||
<td>
|
||||
{% if packageconfigs %}
|
||||
<ul class="unstyled">
|
||||
{% for pc in packageconfigs %}
|
||||
<li> {{ pc.feature }} </li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -149,3 +182,11 @@
|
|||
{% endautoescape %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in New Issue
Block a user