diff options
author | Nicolás Reynolds <fauno@kiwwwi.com.ar> | 2010-12-31 15:42:55 -0300 |
---|---|---|
committer | Nicolás Reynolds <fauno@kiwwwi.com.ar> | 2010-12-31 15:42:55 -0300 |
commit | c9178286885d60741eb0e696c3e345e3b0dfb9e2 (patch) | |
tree | 7738211d84337e897acfd2263be0b33352becae0 /main/models.py | |
parent | ebcd492d39cd0525b768a48558e50041aa0961e3 (diff) | |
parent | 84897adcdc698678f2ee8d2292cfe4271c6335e4 (diff) |
Merge git://projects.archlinux.org/archweb
Conflicts:
templates/public/index.html
urls.py
Diffstat (limited to 'main/models.py')
-rw-r--r-- | main/models.py | 68 |
1 files changed, 51 insertions, 17 deletions
diff --git a/main/models.py b/main/models.py index 6fdb862f..8858b17b 100644 --- a/main/models.py +++ b/main/models.py @@ -5,6 +5,9 @@ from django.contrib.sites.models import Site from main.utils import cache_function from packages.models import PackageRelation +from itertools import groupby +from operator import attrgetter + class UserProfile(models.Model): id = models.AutoField(primary_key=True) # not technically needed notify = models.BooleanField( @@ -67,6 +70,9 @@ class Arch(models.Model): def __unicode__(self): return self.name + def __lt__(self, other): + return self.name < other.name + class Meta: db_table = 'arches' ordering = ['name'] @@ -85,6 +91,9 @@ class Repo(models.Model): def __unicode__(self): return self.name + def __lt__(self, other): + return self.name < other.name + class Meta: db_table = 'repos' ordering = ['name'] @@ -151,34 +160,61 @@ class Package(models.Model): return len(self.signoffs) >= 2 @cache_function(300) + def applicable_arches(self): + '''The list of (this arch) + (available agnostic arches).''' + arches = set(Arch.objects.filter(agnostic=True)) + arches.add(self.arch) + return list(arches) + + @cache_function(300) def get_requiredby(self): """ - Returns a list of package objects. + Returns a list of package objects. An attempt will be made to keep this + list slim by including the corresponding package in the same testing + category as this package if that check makes sense. """ - arches = list(Arch.objects.filter(agnostic=True)) - arches.append(self.arch) requiredby = Package.objects.select_related('arch', 'repo').filter( packagedepend__depname=self.pkgname, - arch__in=arches).distinct() - return requiredby.order_by('pkgname') + arch__in=self.applicable_arches() + ).distinct().order_by('pkgname') + + # find another package by this name in the opposite testing setup + if not Package.objects.filter(pkgname=self.pkgname, + arch=self.arch).exclude(id=self.id, + repo__testing=self.repo.testing).exists(): + # there isn't one? short circuit, all required by entries are fine + return requiredby + + trimmed = [] + # for each unique package name, try to screen our package list down to + # those packages in the same testing category (yes or no) iff there is + # a package in the same testing category. + for name, pkgs in groupby(requiredby, attrgetter('pkgname')): + pkgs = list(pkgs) + pkg = pkgs[0] + if len(pkgs) > 1: + pkgs = [p for p in pkgs if p.repo.testing == self.repo.testing] + if len(pkgs) > 0: + pkg = pkgs[0] + trimmed.append(pkg) + return trimmed @cache_function(300) def get_depends(self): """ - Returns a list of dicts. Each dict contains ('pkg' and 'dep'). - If it represents a found package both vars will be available; - else pkg will be None if it is a 'virtual' dependency. + Returns a list of dicts. Each dict contains ('pkg' and 'dep'). If it + represents a found package both vars will be available; else pkg will + be None if it is a 'virtual' dependency. Packages will match the + testing status of this package if possible. """ deps = [] - arches = list(Arch.objects.filter(agnostic=True)) - arches.append(self.arch) # TODO: we can use list comprehension and an 'in' query to make this more effective for dep in self.packagedepend_set.order_by('depname'): pkgs = Package.objects.select_related('arch', 'repo').filter( pkgname=dep.depname) if not self.arch.agnostic: # make sure we match architectures if possible - pkgs = pkgs.filter(arch__in=arches) + pkgs = pkgs.filter(arch__in=self.applicable_arches()) if len(pkgs) == 0: # couldn't find a package in the DB # it should be a virtual depend (or a removed package) @@ -189,10 +225,8 @@ class Package(models.Model): # more than one package, see if we can't shrink it down # grab the first though in case we fail pkg = pkgs[0] - if self.repo.testing: - pkgs = pkgs.filter(repo__testing=True) - else: - pkgs = pkgs.filter(repo__testing=False) + # prevents yet more DB queries, these lists should be short + pkgs = [p for p in pkgs if p.repo.testing == self.repo.testing] if len(pkgs) > 0: pkg = pkgs[0] deps.append({'dep': dep, 'pkg': pkg}) @@ -225,11 +259,11 @@ class Package(models.Model): repo.testing flag. For any non-split packages, the return value will be an empty list. """ - return Package.objects.filter(arch=self.arch, + return Package.objects.filter(arch__in=self.applicable_arches, repo__testing=self.repo.testing, pkgbase=self.pkgbase).exclude(id=self.id) def get_svn_link(self, svnpath): - linkbase = "http://repos.archlinux.org/wsvn/%s/%s/%s/" + linkbase = "http://projects.archlinux.org/svntogit/%s.git/tree/%s/%s/" return linkbase % (self.repo.svn_root, self.pkgbase, svnpath) def get_arch_svn_link(self): |