summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2010-08-25 13:45:04 -0500
committerDan McGee <dan@archlinux.org>2010-08-25 13:45:04 -0500
commitae5483c230d08c65d91eb7cece106b4f13a56232 (patch)
tree95fd2c95d29da95a544e1ac110e94e363a91d179
parentebfc46026fd726222c32ed1251a4752dee88ca42 (diff)
downloadarchweb-ae5483c230d08c65d91eb7cece106b4f13a56232.tar.gz
archweb-ae5483c230d08c65d91eb7cece106b4f13a56232.zip
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>
-rw-r--r--packages/views.py67
-rw-r--r--templates/packages/differences.html37
-rw-r--r--urls.py1
3 files changed, 105 insertions, 0 deletions
diff --git a/packages/views.py b/packages/views.py
index 277b7900..1ab4749d 100644
--- a/packages/views.py
+++ b/packages/views.py
@@ -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:
diff --git a/templates/packages/differences.html b/templates/packages/differences.html
new file mode 100644
index 00000000..bc749016
--- /dev/null
+++ b/templates/packages/differences.html
@@ -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 %}
diff --git a/urls.py b/urls.py
index 74c439fc..f2ad6b2a 100644
--- a/urls.py
+++ b/urls.py
@@ -29,6 +29,7 @@ urlpatterns = patterns('',
# 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'),