Package Differences by Architecture view

Implements FS#20416. Port over the architecture differences view from
archlinux.de and reimplement in Django with our DB schema. Also use a far
simpler SQL query to do the dirty work rather than the triple UNION
operation. This is accomplished by doing a bit more of the fetching work in
code once we know what packages are actually involved.

Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
Dan McGee 2010-08-25 13:45:04 -05:00
parent ebfc46026f
commit ae5483c230
3 changed files with 105 additions and 0 deletions

View File

@ -342,4 +342,71 @@ def download(request, name='', repo='', arch=''):
url = string.Template('${host}${repo}/os/${arch}/${file}').substitute(details)
return HttpResponseRedirect(url)
def arch_differences(request):
from django.db import connection
from operator import itemgetter
# This is a monster. Join packages against itself, looking for packages in
# our non-'any' architectures only, and not having a corresponding package
# entry in the other table (or having one with a different pkgver). We will
# then go and fetch all of these packages from the database and display
# them later using normal ORM models.
# TODO: we have some hardcoded magic here with respect to the arches.
arch_a = Arch.objects.get(name='i686')
arch_b = Arch.objects.get(name='x86_64')
sql = """
SELECT p.id, q.id
FROM packages p
LEFT JOIN packages q
ON (
p.pkgname = q.pkgname
AND p.repo_id = q.repo_id
AND p.arch_id != q.arch_id
AND p.id != q.id
)
WHERE p.arch_id IN (%s, %s)
AND (
q.id IS NULL
OR
p.pkgver != q.pkgver
OR
p.pkgrel != q.pkgrel
)
"""
cursor = connection.cursor()
cursor.execute(sql, [arch_a.id, arch_b.id])
results = cursor.fetchall()
to_fetch = []
for row in results:
# column A will always have a value, column B might be NULL
to_fetch.append(row[0])
# fetch all of the necessary packages
pkgs = Package.objects.in_bulk(to_fetch)
# now build a list of tuples containing differences
differences = []
for row in results:
pkg_a = pkgs.get(row[0])
pkg_b = pkgs.get(row[1])
# We want arch_a to always appear first
# pkg_a should never be None
if pkg_a.arch == arch_a:
item = (pkg_a.pkgname, pkg_a.repo, pkg_a, pkg_b)
else:
# pkg_b can be None in this case, so be careful
name = pkg_a.pkgname if pkg_a else pkg_b.pkgname
repo = pkg_a.repo if pkg_a else pkg_b.repo
item = (name, repo, pkg_b, pkg_a)
if item not in differences:
differences.append(item)
# now sort our list by repository, package name
differences.sort(key=lambda a: (a[1].name, a[0]))
context = {
'arch_a': arch_a,
'arch_b': arch_b,
'differences': differences,
}
return render_to_response('packages/differences.html',
RequestContext(request, context))
# vim: set ts=4 sw=4 et:

View File

@ -0,0 +1,37 @@
{% extends "base.html" %}
{% block title %}Arch Linux - Package Differences by Architecture{% endblock %}
{% block navbarclass %}anb-packages{% endblock %}
{% block content %}
{% if differences %}
<div class="box">
<h2>Package Differences by Architecture</h2>
<table class="results">
<thead>
<tr>
<th>Package Name</th>
<th>Repository</th>
<th>{{ arch_a.name }} Version</th>
<th>{{ arch_b.name }} Version</th>
</tr>
</thead>
<tbody>
{% for name, repo, pkg1, pkg2 in differences %}
<tr class="{% cycle 'odd' 'even' %}">
<td>{{ name }}</td>
<td>{{ repo.name }}</td>
{% if pkg1 %}
<td><a href="{{ pkg1.get_absolute_url }}"
title="View package details for {{ pkg1.pkgname }}">{{ pkg1.pkgver }}-{{ pkg1.pkgrel }}</a></td>
{% else %}<td>-</td>{% endif %}
{% if pkg2 %}
<td><a href="{{ pkg2.get_absolute_url }}"
title="View package details for {{ pkg2.pkgname }}">{{ pkg2.pkgver }}-{{ pkg2.pkgrel }}</a></td>
{% else %}<td>-</td>{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% endblock %}

View File

@ -29,6 +29,7 @@
# because other projects link to it
(r'^packages/search/$', 'packages.views.search'),
(r'^packages/search/(?P<page>\d+)/$', 'packages.views.search'),
(r'^packages/differences/$', 'packages.views.arch_differences'),
(r'^packages/$', 'packages.views.search'),
(r'^packages/(?P<page>\d+)/$', 'packages.views.search'),