Support reversed other distro recipe list / filtering

Enable "reversing" the comparison, so you can see which recipes on the
OE side match up (or don't) with the other distro. The filtering for
this is a bit awkward, since we don't have an actual foreign key for the
link, hence the hairiness of the code.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
Paul Eggleton 2018-02-14 08:51:45 +13:00
parent 5c56e16a49
commit 8ef315c6bf
2 changed files with 107 additions and 22 deletions

View File

@ -872,28 +872,10 @@ class RecipeDetailView(DetailView):
return context
class ClassicRecipeLinkWrapper:
class LinkWrapper:
def __init__(self, queryset):
self.queryset = queryset
# This function is required by generic views, create another proxy
def _clone(self):
return ClassicRecipeLinkIterator(self.queryset._clone(), **self.kwargs)
def _annotate(self, obj):
recipe = None
vercmp = 0
if obj.cover_layerbranch and obj.cover_pn:
rq = Recipe.objects.filter(layerbranch=obj.cover_layerbranch).filter(pn=obj.cover_pn)
if rq:
recipe = rq.first()
if obj.pv and recipe.pv:
obj_ver = parse_version(obj.pv)
recipe_ver = parse_version(recipe.pv)
vercmp = ((recipe_ver > obj_ver) - (recipe_ver < obj_ver))
setattr(obj, 'cover_recipe', recipe)
setattr(obj, 'cover_vercmp', vercmp)
def __iter__(self):
for obj in self.queryset:
self._annotate(obj)
@ -916,6 +898,49 @@ class ClassicRecipeLinkWrapper:
else:
return len(self.queryset)
class ClassicRecipeLinkWrapper(LinkWrapper):
# This function is required by generic views, create another proxy
def _clone(self):
return ClassicRecipeLinkWrapper(self.queryset._clone(), **self.kwargs)
def _annotate(self, obj):
recipe = None
vercmp = 0
if obj.cover_layerbranch and obj.cover_pn:
rq = Recipe.objects.filter(layerbranch=obj.cover_layerbranch).filter(pn=obj.cover_pn)
if rq:
recipe = rq.first()
if obj.pv and recipe.pv:
obj_ver = parse_version(obj.pv)
recipe_ver = parse_version(recipe.pv)
vercmp = ((recipe_ver > obj_ver) - (recipe_ver < obj_ver))
setattr(obj, 'cover_recipe', recipe)
setattr(obj, 'cover_vercmp', vercmp)
class ClassicRecipeReverseLinkWrapper(LinkWrapper):
def __init__(self, queryset, branch):
self.queryset = queryset
self.branch = branch
# This function is required by generic views, create another proxy
def _clone(self):
return ClassicRecipeReverseLinkWrapper(self.queryset._clone(), **self.kwargs)
def _annotate(self, obj):
recipe = None
vercmp = 0
rq = ClassicRecipe.objects.filter(layerbranch__branch__name=self.branch).filter(cover_layerbranch=obj.layerbranch).filter(cover_pn=obj.pn)
if rq:
recipe = rq.first()
if obj.pv and recipe.pv:
obj_ver = parse_version(obj.pv)
recipe_ver = parse_version(recipe.pv)
vercmp = ((recipe_ver > obj_ver) - (recipe_ver < obj_ver))
setattr(obj, 'cover_recipe', recipe)
setattr(obj, 'cover_vercmp', vercmp)
class ClassicRecipeSearchView(RecipeSearchView):
def render_to_response(self, context, **kwargs):
# Bypass the redirect-to-single-instance behaviour of RecipeSearchView
@ -930,7 +955,10 @@ class ClassicRecipeSearchView(RecipeSearchView):
oe_layer = self.request.GET.get('oe_layer', None)
has_patches = self.request.GET.get('has_patches', '')
needs_attention = self.request.GET.get('needs_attention', '')
qreversed = self.request.GET.get('reversed', '')
init_qs = ClassicRecipe.objects.filter(layerbranch__branch__name=self.kwargs['branch']).filter(deleted=False)
filtered = False
cover_null = False
if cover_status:
if cover_status == '!':
init_qs = init_qs.filter(cover_status__in=['U', 'N', 'S'])
@ -938,13 +966,18 @@ class ClassicRecipeSearchView(RecipeSearchView):
init_qs = init_qs.exclude(cover_status__in=['U', 'N', 'S'])
else:
init_qs = init_qs.filter(cover_status=cover_status)
filtered = True
if cover_status in ['U', '!']:
cover_null = True
if cover_verified:
init_qs = init_qs.filter(cover_verified=(cover_verified=='1'))
filtered = True
if category:
if category == "''" or category == '""':
init_qs = init_qs.filter(classic_category='')
else:
init_qs = init_qs.filter(classic_category__icontains=category)
filtered = True
if oe_layer:
init_qs = init_qs.filter(cover_layerbranch__layer=oe_layer)
if has_patches.strip():
@ -952,11 +985,13 @@ class ClassicRecipeSearchView(RecipeSearchView):
init_qs = init_qs.filter(patch__isnull=False).distinct()
else:
init_qs = init_qs.filter(patch__isnull=True)
filtered = True
if needs_attention.strip():
if needs_attention == '1':
init_qs = init_qs.filter(needs_attention=True)
else:
init_qs = init_qs.filter(needs_attention=False)
filtered = True
if query_string.strip():
order_by = (Lower('pn'), 'layerbranch__layer')
@ -969,6 +1004,7 @@ class ClassicRecipeSearchView(RecipeSearchView):
qs2 = init_qs.filter(entry_query).order_by(*order_by)
qs = list(utils.chain_unique(qs0, qs1, qs2))
filtered = True
else:
if 'q' in self.request.GET:
qs = init_qs.order_by(Lower('pn'), 'layerbranch__layer')
@ -977,7 +1013,34 @@ class ClassicRecipeSearchView(RecipeSearchView):
# won't actually want that (if they do they can just hit the search button
# with no query string)
return Recipe.objects.none()
return ClassicRecipeLinkWrapper(qs)
if qreversed:
init_rqs = Recipe.objects.filter(layerbranch__branch__name='master')
if oe_layer:
init_rqs = init_rqs.filter(layerbranch__layer=oe_layer)
all_values = []
if filtered:
if isinstance(qs, list):
values = []
for item in qs:
if item.cover_layerbranch and item.cover_pn:
values.append((item.cover_layerbranch.id, item.cover_pn))
else:
values = qs.filter(cover_layerbranch__isnull=False).filter(cover_pn__isnull=False).values_list('cover_layerbranch__id', 'cover_pn').distinct()
if cover_null:
all_values = ClassicRecipe.objects.filter(layerbranch__branch__name=self.kwargs['branch']).filter(deleted=False).filter(cover_layerbranch__isnull=False).filter(cover_pn__isnull=False).values_list('cover_layerbranch__id', 'cover_pn').distinct()
else:
values = None
rqs = init_rqs.order_by(Lower('pn'), 'layerbranch__layer')
if filtered:
items = []
for item in rqs:
recipe_values = (item.layerbranch.id, item.pn)
if (cover_null and recipe_values not in all_values) or (recipe_values in values):
items.append(item)
return ClassicRecipeReverseLinkWrapper(items, self.kwargs['branch'])
return ClassicRecipeReverseLinkWrapper(rqs, self.kwargs['branch'])
else:
return ClassicRecipeLinkWrapper(qs)
def get_context_data(self, **kwargs):
context = super(ClassicRecipeSearchView, self).get_context_data(**kwargs)
@ -991,6 +1054,7 @@ class ClassicRecipeSearchView(RecipeSearchView):
searched = False
search_form = ClassicRecipeSearchForm()
context['compare'] = self.request.GET.get('compare', False)
context['reversed'] = self.request.GET.get('reversed', False)
context['search_form'] = search_form
context['searched'] = searched
return context

View File

@ -54,6 +54,7 @@
</tr>
{% endfor %}
<tr><td><label class="checkbox"><input type="checkbox" name="compare" {% if compare %}checked{% endif %}></input>Show comparison</label></td></tr>
<tr><td><label class="checkbox"><input type="checkbox" name="reversed" {% if reversed %}checked{% endif %}></input>Reversed</label></td></tr>
</tbody>
</table>
<button class="btn" type="submit">Search</button>
@ -64,7 +65,19 @@
<table class="table table-striped table-bordered recipestable">
<thead>
<tr>
{% if compare %}
{% if reversed %}
<th>Recipe name</th>
<th>OE Layer</th>
<th>Version</th>
<th class="span7">Description</th>
<th>Section</th>
<th class="span5">Status</th>
{% if branch.name == 'oe-classic' %}
<th>Covering recipe</th>
{% else %}
<th>Covering package</th>
{% endif %}
{% elif compare %}
{% if branch.name == 'oe-classic' %}
<th>Recipe name</th>
{% else %}
@ -95,7 +108,15 @@
<tbody>
{% for recipe in recipe_list %}
<tr {% if recipe.preferred_count > 0 %}class="muted"{% endif %}>
{% if compare %}
{% if reversed %}
<td><a href="{% url 'recipe' recipe.id %}">{{ recipe.name }}{% if recipe.needs_attention %} <i class="icon-exclamation-sign" data-toggle="tooltip" title="Needs attention"></i>{% endif %}</a></td>
<td><a href="{% url 'layer_item' 'master' recipe.layerbranch.layer.name %}">{{ recipe.layerbranch.layer.name }}</a></td>
<td>{{ recipe.pv }}</td>
<td>{{ recipe.short_desc }}</td>
<td>{{ recipe.section }}</td>
<td>{% if recipe.cover_recipe %}{{ recipe.cover_recipe.get_cover_status_display }}{% endif %}</td>
<td>{% if recipe.cover_recipe %}<a href="{% url 'comparison_recipe' recipe.cover_recipe.id %}">{% endif %}{{ recipe.cover_recipe.pn }}{% if recipe.cover_recipe %}</a>{% endif %}</td>
{% elif compare %}
<td><a href="{% url 'comparison_recipe' recipe.id %}">{{ recipe.name }}{% if recipe.needs_attention %} <i class="icon-exclamation-sign" data-toggle="tooltip" title="Needs attention"></i>{% endif %}</a></td>
<td>{{ recipe.pv|truncatechars:10 }}</td>
<td>{% if recipe.patch_set.exists %}{{ recipe.patch_set.count }}{% endif %}</td>