summaryrefslogtreecommitdiff
path: root/main/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'main/models.py')
-rw-r--r--main/models.py68
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):