diff options
Diffstat (limited to 'packages/views.py')
-rw-r--r-- | packages/views.py | 161 |
1 files changed, 119 insertions, 42 deletions
diff --git a/packages/views.py b/packages/views.py index b64beb68..f45c25d6 100644 --- a/packages/views.py +++ b/packages/views.py @@ -8,7 +8,7 @@ from django.core.mail import send_mail from django.core.serializers.json import DjangoJSONEncoder from django.db.models import Q from django.http import HttpResponse, Http404 -from django.shortcuts import get_object_or_404, redirect +from django.shortcuts import get_object_or_404, get_list_or_404, redirect from django.template import loader, Context from django.utils import simplejson from django.views.decorators.cache import never_cache @@ -18,15 +18,16 @@ from django.views.generic import list_detail from django.views.generic.simple import direct_to_template from datetime import datetime +from operator import attrgetter import string from urllib import urlencode -from main.models import Package, PackageFile -from main.models import Arch, Repo, Signoff -from main.utils import make_choice +from main.models import Package, PackageFile, Arch, Repo +from main.utils import make_choice, groupby_preserve_order, PackageStandin from mirrors.models import MirrorUrl -from .models import PackageRelation, PackageGroup -from .utils import get_group_info, get_differences_info, get_wrong_permissions +from .models import PackageRelation, PackageGroup, Signoff +from .utils import (get_group_info, get_differences_info, + get_wrong_permissions, get_current_signoffs) class PackageJSONEncoder(DjangoJSONEncoder): pkg_attributes = [ 'pkgname', 'pkgbase', 'repo', 'arch', 'pkgver', @@ -118,7 +119,8 @@ def details(request, name='', repo='', arch=''): arches.extend(Arch.objects.filter(agnostic=True)) repo = get_object_or_404(Repo, name__iexact=repo) pkgs = Package.objects.normal().filter(pkgbase=name, - repo__testing=repo.testing, arch__in=arches).order_by('pkgname') + repo__testing=repo.testing, repo__staging=repo.staging, + arch__in=arches).order_by('pkgname') if len(pkgs) == 0: raise Http404 context = { @@ -191,6 +193,7 @@ class PackageSearchForm(forms.Form): arch = forms.MultipleChoiceField(required=False) q = forms.CharField(required=False) maintainer = forms.ChoiceField(required=False) + packager = forms.ChoiceField(required=False) last_update = forms.DateField(required=False, widget=AdminDateWidget(), label='Last Updated After') flagged = forms.ChoiceField( @@ -213,6 +216,9 @@ class PackageSearchForm(forms.Form): self.fields['maintainer'].choices = \ [('', 'All'), ('orphan', 'Orphan')] + \ [(m.username, m.get_full_name()) for m in maints] + self.fields['packager'].choices = \ + [('', 'All'), ('unknown', 'Unknown')] + \ + [(m.username, m.get_full_name()) for m in maints] def search(request, page=None): limit = 50 @@ -237,6 +243,12 @@ def search(request, page=None): user__username=form.cleaned_data['maintainer']).values('pkgbase') packages = packages.filter(pkgbase__in=inner_q) + if form.cleaned_data['packager'] == 'unknown': + packages = packages.filter(packager__isnull=True) + elif form.cleaned_data['packager']: + packages = packages.filter( + packager__username=form.cleaned_data['packager']) + if form.cleaned_data['flagged'] == 'Flagged': packages = packages.filter(flag_date__isnull=False) elif form.cleaned_data['flagged'] == 'Not Flagged': @@ -262,15 +274,14 @@ def search(request, page=None): else: form = PackageSearchForm() - if packages.count() == 1: - return redirect(packages[0]) - current_query = request.GET.urlencode() page_dict = { 'search_form': form, 'current_query': current_query } - allowed_sort = ["arch", "repo", "pkgname", "last_update", "flag_date"] + allowed_sort = ["arch", "repo", "pkgname", "pkgbase", + "compressed_size", "installed_size", + "build_date", "last_update", "flag_date"] allowed_sort += ["-" + s for s in allowed_sort] sort = request.GET.get('sort', None) # TODO: sorting by multiple fields makes using a DB index much harder @@ -293,11 +304,14 @@ def files(request, name, repo, arch): pkg = get_object_or_404(Package, pkgname=name, repo__name__iexact=repo, arch__name=arch) fileslist = PackageFile.objects.filter(pkg=pkg).order_by('directory', 'filename') + context = { + 'pkg': pkg, + 'files': fileslist, + } template = 'packages/files.html' if request.is_ajax(): template = 'packages/files-list.html' - return direct_to_template(request, template, - {'pkg':pkg, 'files':fileslist}) + return direct_to_template(request, template, context) def details_json(request, name, repo, arch): pkg = get_object_or_404(Package, @@ -333,45 +347,106 @@ def unflag_all(request, name, repo, arch): pkg = get_object_or_404(Package, pkgname=name, repo__name__iexact=repo, arch__name=arch) # find all packages from (hopefully) the same PKGBUILD - pkgs = Package.objects.filter( - pkgbase=pkg.pkgbase, repo__testing=pkg.repo.testing) + pkgs = Package.objects.filter(pkgbase=pkg.pkgbase, + repo__testing=pkg.repo.testing, repo__staging=pkg.repo.staging) pkgs.update(flag_date=None) return redirect(pkg) +class PackageSignoffGroup(object): + '''Encompasses all packages in testing with the same pkgbase.''' + def __init__(self, packages, target_repo=None, signoffs=None): + if len(packages) == 0: + raise Exception + self.packages = packages + self.target_repo = target_repo + self.signoffs = signoffs + + first = packages[0] + self.pkgbase = first.pkgbase + self.arch = first.arch + self.repo = first.repo + self.version = '' + + version = first.full_version + if all(version == pkg.full_version for pkg in packages): + self.version = version + + @property + def package(self): + '''Try and return a relevant single package object representing this + group. Start by seeing if there is only one package, then look for the + matching package by name, finally falling back to a standin package + object.''' + if len(self.packages) == 1: + return self.packages[0] + + same_pkgs = [p for p in self.packages if p.pkgname == p.pkgbase] + if same_pkgs: + return same_pkgs[0] + + return PackageStandin(self.packages[0]) + + def find_signoffs(self, all_signoffs): + '''Look through a list of Signoff objects for ones matching this + particular group and store them on the object.''' + if self.signoffs is None: + self.signoffs = [] + for s in all_signoffs: + if s.pkgbase != self.pkgbase: + continue + if self.version and not s.full_version == self.version: + continue + if s.arch_id == self.arch.id and s.repo_id == self.repo.id: + self.signoffs.append(s) + + def approved(self): + if self.signoffs: + good_signoffs = [s for s in self.signoffs if not s.revoked] + return len(good_signoffs) >= Signoff.REQUIRED + return False + @permission_required('main.change_package') @never_cache def signoffs(request): - packages = Package.objects.select_related('arch', 'repo', 'signoffs').filter(repo__testing=True).order_by("pkgname") - package_list = [] - - q_pkgname = Package.objects.filter(repo__testing=True).values('pkgname').distinct().query - package_repos = Package.objects.values('pkgname', 'repo__name').exclude(repo__testing=True).filter(pkgname__in=q_pkgname) - pkgtorepo = dict() - for pr in package_repos: - pkgtorepo[pr['pkgname']] = pr['repo__name'] - - for package in packages: - if package.pkgname in pkgtorepo: - repo = pkgtorepo[package.pkgname] - else: - repo = "Unknown" - package_list.append((package, repo)) + test_pkgs = Package.objects.normal().filter(repo__testing=True) + packages = test_pkgs.order_by('pkgname') + + # Collect all pkgbase values in testing repos + q_pkgbase = test_pkgs.values('pkgbase') + package_repos = Package.objects.order_by().values_list( + 'pkgbase', 'repo__name').filter( + repo__testing=False, repo__staging=False, + pkgbase__in=q_pkgbase).distinct() + pkgtorepo = dict(package_repos) + + # Collect all existing signoffs for these packages + signoffs = get_current_signoffs() + + same_pkgbase_key = lambda x: (x.repo.name, x.arch.name, x.pkgbase) + grouped = groupby_preserve_order(packages, same_pkgbase_key) + signoff_groups = [] + for group in grouped: + signoff_group = PackageSignoffGroup(group) + signoff_group.target_repo = pkgtorepo.get(signoff_group.pkgbase, + "Unknown") + signoff_group.find_signoffs(signoffs) + signoff_groups.append(signoff_group) + + signoff_groups.sort(key=attrgetter('pkgbase')) + return direct_to_template(request, 'packages/signoffs.html', - {'packages': package_list}) + {'signoff_groups': signoff_groups}) @permission_required('main.change_package') @never_cache -def signoff_package(request, arch, pkgname): - pkg = get_object_or_404(Package, - arch__name=arch, - pkgname=pkgname, - repo__testing=True) +def signoff_package(request, name, repo, arch): + packages = get_list_or_404(Package, pkgbase=name, + arch__name=arch, repo__name__iexact=repo, repo__testing=True) + pkg = packages[0] signoff, created = Signoff.objects.get_or_create( - pkg=pkg, - pkgver=pkg.pkgver, - pkgrel=pkg.pkgrel, - packager=request.user) + pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel, + epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo, user=request.user) if request.is_ajax(): data = { @@ -406,7 +481,8 @@ def flag(request, name, repo, arch): # find all packages from (hopefully) the same PKGBUILD pkgs = Package.objects.normal().filter( pkgbase=pkg.pkgbase, flag_date__isnull=True, - repo__testing=pkg.repo.testing).order_by( + repo__testing=pkg.repo.testing, + repo__staging=pkg.repo.staging).order_by( 'pkgname', 'repo__name', 'arch__name') if request.POST: @@ -461,7 +537,8 @@ def flag_confirmed(request, name, repo, arch): pkgname=name, repo__name__iexact=repo, arch__name=arch) pkgs = Package.objects.normal().filter( pkgbase=pkg.pkgbase, flag_date=pkg.flag_date, - repo__testing=pkg.repo.testing).order_by( + repo__testing=pkg.repo.testing, + repo__staging=pkg.repo.staging).order_by( 'pkgname', 'repo__name', 'arch__name') context = {'package': pkg, 'packages': pkgs} |