Move package utility functions
We now have a few of them, so move them to their own file like we do in the other applications. Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
4c3100ab90
commit
2750b94345
103
packages/utils.py
Normal file
103
packages/utils.py
Normal file
@ -0,0 +1,103 @@
|
||||
from django.db import connection
|
||||
from django.db.models import Count, Max
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
from main.models import Package
|
||||
from main.utils import cache_function
|
||||
from .models import PackageGroup
|
||||
|
||||
@cache_function(300)
|
||||
def get_group_info():
|
||||
raw_groups = PackageGroup.objects.values_list(
|
||||
'name', 'pkg__arch__name').order_by('name').annotate(
|
||||
cnt=Count('pkg'), last_update=Max('pkg__last_update'))
|
||||
# now for post_processing. we need to seperate things out and add
|
||||
# the count in for 'any' to all of the other architectures.
|
||||
group_mapping = {}
|
||||
for grp in raw_groups:
|
||||
arch_groups = group_mapping.setdefault(grp[1], {})
|
||||
arch_groups[grp[0]] = {'name': grp[0], 'arch': grp[1],
|
||||
'count': grp[2], 'last_update': grp[3]}
|
||||
|
||||
# we want to promote the count of 'any' packages in groups to the
|
||||
# other architectures, and also add any 'any'-only groups
|
||||
if 'any' in group_mapping:
|
||||
any_groups = group_mapping['any']
|
||||
del group_mapping['any']
|
||||
for arch, arch_groups in group_mapping.iteritems():
|
||||
for grp in any_groups.itervalues():
|
||||
if grp['name'] in arch_groups:
|
||||
found = arch_groups[grp['name']]
|
||||
found['count'] += grp['count']
|
||||
if grp['last_update'] > found['last_update']:
|
||||
found['last_update'] = grp['last_update']
|
||||
else:
|
||||
new_g = grp.copy()
|
||||
# override the arch to not be 'any'
|
||||
new_g['arch'] = arch
|
||||
arch_groups[grp['name']] = new_g
|
||||
|
||||
# now transform it back into a sorted list
|
||||
groups = []
|
||||
for val in group_mapping.itervalues():
|
||||
groups.extend(val.itervalues())
|
||||
return sorted(groups, key=itemgetter('name', 'arch'))
|
||||
|
||||
@cache_function(300)
|
||||
def get_differences_info(arch_a, arch_b):
|
||||
# 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.
|
||||
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]))
|
||||
return differences
|
||||
|
||||
# vim: set ts=4 sw=4 et:
|
@ -11,17 +11,17 @@
|
||||
from django.views.decorators.cache import never_cache
|
||||
from django.views.decorators.vary import vary_on_headers
|
||||
from django.views.generic import list_detail
|
||||
from django.db.models import Count, Max, Q
|
||||
from django.db.models import Q
|
||||
|
||||
from datetime import datetime
|
||||
from operator import itemgetter
|
||||
import string
|
||||
|
||||
from main.models import Package, PackageFile
|
||||
from main.models import Arch, Repo, Signoff
|
||||
from main.models import MirrorUrl
|
||||
from main.utils import cache_function, make_choice
|
||||
from packages.models import PackageGroup, PackageRelation
|
||||
from main.utils import make_choice
|
||||
from .models import PackageGroup, PackageRelation
|
||||
from .utils import get_group_info, get_differences_info
|
||||
|
||||
def opensearch(request):
|
||||
if request.is_secure():
|
||||
@ -85,45 +85,8 @@ def details(request, name='', repo='', arch=''):
|
||||
return HttpResponseRedirect("/packages/?arch=%s&repo=%s&q=%s" % (
|
||||
arch.lower(), repo.title(), name))
|
||||
|
||||
@cache_function(300)
|
||||
def get_group_information():
|
||||
raw_groups = PackageGroup.objects.values_list(
|
||||
'name', 'pkg__arch__name').order_by('name').annotate(
|
||||
cnt=Count('pkg'), last_update=Max('pkg__last_update'))
|
||||
# now for post_processing. we need to seperate things out and add
|
||||
# the count in for 'any' to all of the other architectures.
|
||||
group_mapping = {}
|
||||
for g in raw_groups:
|
||||
arch_groups = group_mapping.setdefault(g[1], {})
|
||||
arch_groups[g[0]] = {'name': g[0], 'arch': g[1],
|
||||
'count': g[2], 'last_update': g[3]}
|
||||
|
||||
# we want to promote the count of 'any' packages in groups to the
|
||||
# other architectures, and also add any 'any'-only groups
|
||||
if 'any' in group_mapping:
|
||||
any_groups = group_mapping['any']
|
||||
del group_mapping['any']
|
||||
for arch, arch_groups in group_mapping.iteritems():
|
||||
for g in any_groups.itervalues():
|
||||
if g['name'] in arch_groups:
|
||||
found = arch_groups[g['name']]
|
||||
found['count'] += g['count']
|
||||
if g['last_update'] > found['last_update']:
|
||||
found['last_update'] = g['last_update']
|
||||
else:
|
||||
new_g = g.copy()
|
||||
# override the arch to not be 'any'
|
||||
new_g['arch'] = arch
|
||||
arch_groups[g['name']] = new_g
|
||||
|
||||
# now transform it back into a sorted list
|
||||
groups = []
|
||||
for v in group_mapping.itervalues():
|
||||
groups.extend(v.itervalues())
|
||||
return sorted(groups, key=itemgetter('name', 'arch'))
|
||||
|
||||
def groups(request):
|
||||
groups = get_group_information()
|
||||
groups = get_group_info()
|
||||
return render_to_response('packages/groups.html',
|
||||
RequestContext(request, {'groups': groups}))
|
||||
|
||||
@ -400,68 +363,11 @@ def download(request, name='', repo='', arch=''):
|
||||
url = string.Template('${host}${repo}/os/${arch}/${file}').substitute(details)
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
@cache_function(300)
|
||||
def get_differences_information(arch_a, arch_b):
|
||||
from django.db import connection
|
||||
# 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.
|
||||
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]))
|
||||
return differences
|
||||
|
||||
def arch_differences(request):
|
||||
# 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')
|
||||
differences = get_differences_information(arch_a, arch_b)
|
||||
differences = get_differences_info(arch_a, arch_b)
|
||||
context = {
|
||||
'arch_a': arch_a,
|
||||
'arch_b': arch_b,
|
||||
|
@ -1,6 +1,6 @@
|
||||
from django.contrib.sitemaps import Sitemap
|
||||
from main.models import Package, News
|
||||
from packages.views import get_group_information
|
||||
from packages.views import get_group_info
|
||||
|
||||
class PackagesSitemap(Sitemap):
|
||||
changefreq = "weekly"
|
||||
@ -30,7 +30,7 @@ class PackageGroupsSitemap(Sitemap):
|
||||
priority = "0.4"
|
||||
|
||||
def items(self):
|
||||
return get_group_information()
|
||||
return get_group_info()
|
||||
|
||||
def lastmod(self, obj):
|
||||
return obj['last_update']
|
||||
|
Loading…
Reference in New Issue
Block a user