Collect machine information from layers

Look for conf/machine/*.conf and add a record for each file found. These
are displayed in the layer detail page if any are present.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
Paul Eggleton 2013-02-24 22:34:20 +00:00
parent 3b5c7ad825
commit e4eb8213cf
5 changed files with 99 additions and 6 deletions

2
TODO
View File

@ -15,6 +15,7 @@ TODO:
* Usage links in list page? * Usage links in list page?
* Layer submission interface design * Layer submission interface design
* Style/extend about page * Style/extend about page
* Style machine list on detail
* Recipe info page * Recipe info page
* Captcha for layer submission interface? * Captcha for layer submission interface?
* Touch up publishing interface * Touch up publishing interface
@ -27,4 +28,3 @@ Later:
* Tool for finding/comparing duplicate recipes? * Tool for finding/comparing duplicate recipes?
* Tool for editing SUMMARY/DESCRIPTION? * Tool for editing SUMMARY/DESCRIPTION?
* Dynamic loading/filtering for recipes list * Dynamic loading/filtering for recipes list
* Collect information on machines added by BSP layers?

View File

@ -48,8 +48,18 @@ class RecipeAdmin(admin.ModelAdmin):
def has_delete_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None):
return False return False
class MachineAdmin(admin.ModelAdmin):
search_fields = ['name']
list_filter = ['layer__name']
readonly_fields = Machine._meta.get_all_field_names()
def has_add_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
admin.site.register(LayerItem, LayerItemAdmin) admin.site.register(LayerItem, LayerItemAdmin)
admin.site.register(LayerMaintainer, LayerMaintainerAdmin) admin.site.register(LayerMaintainer, LayerMaintainerAdmin)
admin.site.register(LayerDependency, LayerDependencyAdmin) admin.site.register(LayerDependency, LayerDependencyAdmin)
admin.site.register(LayerNote, LayerNoteAdmin) admin.site.register(LayerNote, LayerNoteAdmin)
admin.site.register(Recipe, RecipeAdmin) admin.site.register(Recipe, RecipeAdmin)
admin.site.register(Machine, MachineAdmin)

View File

@ -118,6 +118,29 @@
</div> <!-- end of row-fluid --> </div> <!-- end of row-fluid -->
</div> <!-- end of container-fluid --> </div> <!-- end of container-fluid -->
{% if layeritem.machine_set.count > 0 %}
<div class="container-fluid" style="margin-bottom:1em;">
<div class="row-fluid">
<div class="navbar">
<div class="navbar-inner">
<a class="brand pull-left">{{ layeritem.name }} machines</a>
</div>
</div>
<table class="table table-bordered">
<tbody>
{% for machine in layeritem.machine_set.all %}
<tr>
<td><a href="{{ machine.vcs_web_url }}">{{ machine.name }}</a></td>
<td>{{ machine.description }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<div class="container-fluid" style="margin-bottom:1em;"> <div class="container-fluid" style="margin-bottom:1em;">
<div class="row-fluid"> <div class="row-fluid">
<div class="navbar"> <div class="navbar">

View File

@ -150,3 +150,16 @@ class Recipe(models.Model):
def __unicode__(self): def __unicode__(self):
return os.path.join(self.filepath, self.filename) return os.path.join(self.filepath, self.filename)
class Machine(models.Model):
layer = models.ForeignKey(LayerItem)
name = models.CharField(max_length=255)
description = models.CharField(max_length=255)
def vcs_web_url(self):
url = self.layer.file_url(os.path.join('conf/machine/%s.conf' % self.name))
return url or ''
def __unicode__(self):
return '%s (%s)' % (self.name, self.layer.name)

View File

@ -15,6 +15,7 @@ import logging
import subprocess import subprocess
from datetime import datetime from datetime import datetime
import fnmatch import fnmatch
import re
from distutils.version import LooseVersion from distutils.version import LooseVersion
def logger_create(): def logger_create():
@ -65,7 +66,7 @@ def sanitise_path(inpath):
return outpath return outpath
def split_path(subdir_start, recipe_path): def split_bb_file_path(recipe_path, subdir_start):
if recipe_path.startswith(subdir_start) and fnmatch.fnmatch(recipe_path, "*.bb"): if recipe_path.startswith(subdir_start) and fnmatch.fnmatch(recipe_path, "*.bb"):
if subdir_start: if subdir_start:
filepath = os.path.relpath(os.path.dirname(recipe_path), subdir_start) filepath = os.path.relpath(os.path.dirname(recipe_path), subdir_start)
@ -74,6 +75,13 @@ def split_path(subdir_start, recipe_path):
return (filepath, os.path.basename(recipe_path)) return (filepath, os.path.basename(recipe_path))
return (None, None) return (None, None)
conf_re = re.compile(r'conf/machine/([^/.]*).conf$')
def check_machine_conf(path, subdir_start = None):
if not subdir_start or path.startswith(subdir_start):
res = conf_re.search(path)
if res:
return res.group(1)
return None
def update_recipe_file(data, path, recipe): def update_recipe_file(data, path, recipe):
fn = str(os.path.join(path, recipe.filename)) fn = str(os.path.join(path, recipe.filename))
@ -90,6 +98,14 @@ def update_recipe_file(data, path, recipe):
except Exception as e: except Exception as e:
logger.info("Unable to read %s: %s", fn, str(e)) logger.info("Unable to read %s: %s", fn, str(e))
def update_machine_conf_file(path, machine):
with open(path) as f:
for line in f:
if line.startswith('#@DESCRIPTION:'):
desc = line[14:].strip()
desc = re.sub(r'Machine configuration for (the )*', '', desc)
machine.description = desc
break
def setup_bitbake_path(basepath): def setup_bitbake_path(basepath):
# Set path to bitbake lib dir # Set path to bitbake lib dir
@ -149,7 +165,7 @@ def main():
from django.core.management import setup_environ from django.core.management import setup_environ
from django.conf import settings from django.conf import settings
from layerindex.models import LayerItem, Recipe from layerindex.models import LayerItem, Recipe, Machine
from django.db import transaction from django.db import transaction
import settings import settings
@ -236,6 +252,7 @@ def main():
layerdir = os.path.join(repodir, layer.vcs_subdir) layerdir = os.path.join(repodir, layer.vcs_subdir)
layerrecipes = Recipe.objects.filter(layer=layer) layerrecipes = Recipe.objects.filter(layer=layer)
layermachines = Machine.objects.filter(layer=layer)
if layer.vcs_last_rev != topcommit.hexsha or options.reload: if layer.vcs_last_rev != topcommit.hexsha or options.reload:
logger.info("Collecting data for layer %s" % layer.name) logger.info("Collecting data for layer %s" % layer.name)
@ -262,13 +279,17 @@ def main():
for d in diff.iter_change_type('D'): for d in diff.iter_change_type('D'):
path = d.a_blob.path path = d.a_blob.path
(filepath, filename) = split_path(subdir_start, path) (filepath, filename) = split_bb_file_path(path, subdir_start)
if filename: if filename:
layerrecipes.filter(filepath=filepath).filter(filename=filename).delete() layerrecipes.filter(filepath=filepath).filter(filename=filename).delete()
else:
machinename = check_machine_conf(path, subdir_start)
if machinename:
layermachines.filter(name=machinename).delete()
for d in diff.iter_change_type('A'): for d in diff.iter_change_type('A'):
path = d.b_blob.path path = d.b_blob.path
(filepath, filename) = split_path(subdir_start, path) (filepath, filename) = split_bb_file_path(path, subdir_start)
if filename: if filename:
recipe = Recipe() recipe = Recipe()
recipe.layer = layer recipe.layer = layer
@ -276,19 +297,36 @@ def main():
recipe.filepath = filepath recipe.filepath = filepath
update_recipe_file(config_data_copy, os.path.join(layerdir, filepath), recipe) update_recipe_file(config_data_copy, os.path.join(layerdir, filepath), recipe)
recipe.save() recipe.save()
else:
machinename = check_machine_conf(path, subdir_start)
if machinename:
machine = Machine()
machine.layer = layer
machine.name = machinename
update_machine_conf_file(os.path.join(repodir, path), machine)
machine.save()
for d in diff.iter_change_type('M'): for d in diff.iter_change_type('M'):
path = d.a_blob.path path = d.a_blob.path
(filepath, filename) = split_path(subdir_start, path) (filepath, filename) = split_bb_file_path(path, subdir_start)
if filename: if filename:
results = layerrecipes.filter(filepath=filepath).filter(filename=filename)[:1] results = layerrecipes.filter(filepath=filepath).filter(filename=filename)[:1]
if results: if results:
recipe = results[0] recipe = results[0]
update_recipe_file(config_data_copy, os.path.join(layerdir, filepath), recipe) update_recipe_file(config_data_copy, os.path.join(layerdir, filepath), recipe)
recipe.save() recipe.save()
else:
machinename = check_machine_conf(path, subdir_start)
if machinename:
results = layermachines.filter(name=machinename)
if results:
machine = results[0]
update_machine_conf_file(os.path.join(repodir, path), machine)
machine.save()
else: else:
# Collect recipe data from scratch # Collect recipe data from scratch
layerrecipes.delete() layerrecipes.delete()
layermachines.delete()
for root, dirs, files in os.walk(layerdir): for root, dirs, files in os.walk(layerdir):
for f in files: for f in files:
if fnmatch.fnmatch(f, "*.bb"): if fnmatch.fnmatch(f, "*.bb"):
@ -298,6 +336,15 @@ def main():
recipe.filepath = os.path.relpath(root, layerdir) recipe.filepath = os.path.relpath(root, layerdir)
update_recipe_file(config_data_copy, root, recipe) update_recipe_file(config_data_copy, root, recipe)
recipe.save() recipe.save()
else:
fullpath = os.path.join(root, f)
machinename = check_machine_conf(fullpath)
if machinename:
machine = Machine()
machine.layer = layer
machine.name = machinename
update_machine_conf_file(fullpath, machine)
machine.save()
# Save repo info # Save repo info
layer.vcs_last_rev = topcommit.hexsha layer.vcs_last_rev = topcommit.hexsha