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.cache import never_cache
|
||||||
from django.views.decorators.vary import vary_on_headers
|
from django.views.decorators.vary import vary_on_headers
|
||||||
from django.views.generic import list_detail
|
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 datetime import datetime
|
||||||
from operator import itemgetter
|
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from main.models import Package, PackageFile
|
from main.models import Package, PackageFile
|
||||||
from main.models import Arch, Repo, Signoff
|
from main.models import Arch, Repo, Signoff
|
||||||
from main.models import MirrorUrl
|
from main.models import MirrorUrl
|
||||||
from main.utils import cache_function, make_choice
|
from main.utils import make_choice
|
||||||
from packages.models import PackageGroup, PackageRelation
|
from .models import PackageGroup, PackageRelation
|
||||||
|
from .utils import get_group_info, get_differences_info
|
||||||
|
|
||||||
def opensearch(request):
|
def opensearch(request):
|
||||||
if request.is_secure():
|
if request.is_secure():
|
||||||
@ -85,45 +85,8 @@ def details(request, name='', repo='', arch=''):
|
|||||||
return HttpResponseRedirect("/packages/?arch=%s&repo=%s&q=%s" % (
|
return HttpResponseRedirect("/packages/?arch=%s&repo=%s&q=%s" % (
|
||||||
arch.lower(), repo.title(), name))
|
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):
|
def groups(request):
|
||||||
groups = get_group_information()
|
groups = get_group_info()
|
||||||
return render_to_response('packages/groups.html',
|
return render_to_response('packages/groups.html',
|
||||||
RequestContext(request, {'groups': groups}))
|
RequestContext(request, {'groups': groups}))
|
||||||
|
|
||||||
@ -400,68 +363,11 @@ def download(request, name='', repo='', arch=''):
|
|||||||
url = string.Template('${host}${repo}/os/${arch}/${file}').substitute(details)
|
url = string.Template('${host}${repo}/os/${arch}/${file}').substitute(details)
|
||||||
return HttpResponseRedirect(url)
|
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):
|
def arch_differences(request):
|
||||||
# TODO: we have some hardcoded magic here with respect to the arches.
|
# TODO: we have some hardcoded magic here with respect to the arches.
|
||||||
arch_a = Arch.objects.get(name='i686')
|
arch_a = Arch.objects.get(name='i686')
|
||||||
arch_b = Arch.objects.get(name='x86_64')
|
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 = {
|
context = {
|
||||||
'arch_a': arch_a,
|
'arch_a': arch_a,
|
||||||
'arch_b': arch_b,
|
'arch_b': arch_b,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django.contrib.sitemaps import Sitemap
|
from django.contrib.sitemaps import Sitemap
|
||||||
from main.models import Package, News
|
from main.models import Package, News
|
||||||
from packages.views import get_group_information
|
from packages.views import get_group_info
|
||||||
|
|
||||||
class PackagesSitemap(Sitemap):
|
class PackagesSitemap(Sitemap):
|
||||||
changefreq = "weekly"
|
changefreq = "weekly"
|
||||||
@ -30,7 +30,7 @@ class PackageGroupsSitemap(Sitemap):
|
|||||||
priority = "0.4"
|
priority = "0.4"
|
||||||
|
|
||||||
def items(self):
|
def items(self):
|
||||||
return get_group_information()
|
return get_group_info()
|
||||||
|
|
||||||
def lastmod(self, obj):
|
def lastmod(self, obj):
|
||||||
return obj['last_update']
|
return obj['last_update']
|
||||||
|
Loading…
Reference in New Issue
Block a user