summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/models.py55
-rw-r--r--packages/models.py23
2 files changed, 71 insertions, 7 deletions
diff --git a/main/models.py b/main/models.py
index b49edde3..bb2320e8 100644
--- a/main/models.py
+++ b/main/models.py
@@ -11,6 +11,7 @@ from django.utils.timezone import now
from .fields import PositiveBigIntegerField
from .utils import cache_function, set_created_field
+from packages.alpm import AlpmAPI
class TodolistManager(models.Manager):
@@ -189,16 +190,42 @@ class Package(models.Model):
category as this package if that check makes sense.
"""
from packages.models import Depend
- provides = set(self.provides.values_list('name', flat=True))
- provides.add(self.pkgname)
+ provides = self.provides.all()
+ provide_names = set(provide.name for provide in provides)
+ provide_names.add(self.pkgname)
requiredby = Depend.objects.select_related('pkg',
'pkg__arch', 'pkg__repo').filter(
- name__in=provides).order_by(
+ name__in=provide_names).order_by(
'pkg__pkgname', 'pkg__arch__name', 'pkg__repo__name')
if not self.arch.agnostic:
# make sure we match architectures if possible
requiredby = requiredby.filter(
pkg__arch__in=self.applicable_arches())
+
+ # if we can use ALPM, ensure our returned Depend objects abide by the
+ # version comparison operators they may specify
+ alpm = AlpmAPI()
+ if alpm.available:
+ new_rqd = []
+ for dep in requiredby:
+ if not dep.comparison or not dep.version:
+ # no comparisson/version, so always let it through
+ new_rqd.append(dep)
+ elif self.pkgname == dep.name:
+ # depends on this package, so check it directly
+ if alpm.compare_versions(self.full_version,
+ dep.comparison, dep.version):
+ new_rqd.append(dep)
+ else:
+ # it must be a provision of ours at this point
+ for provide in (p for p in provides if p.name == dep.name):
+ print(provide.version, dep.comparison, dep.version)
+ if alpm.compare_versions(provide.version,
+ dep.comparison, dep.version):
+ new_rqd.append(dep)
+ break
+ requiredby = new_rqd
+
# sort out duplicate packages; this happens if something has a double
# versioned depend such as a kernel module
requiredby = [list(vals)[0] for _, vals in
@@ -263,10 +290,24 @@ class Package(models.Model):
"""
Returns a list of packages with conflicts against this package.
"""
- # TODO: fix this; right now we cheat since we can't do proper version
- # number checking without using alpm or vercmp directly.
- return Package.objects.filter(conflicts__name=self.pkgname,
- conflicts__comparison='').distinct()
+ pkgs = Package.objects.filter(conflicts__name=self.pkgname)
+ alpm = AlpmAPI()
+ if not alpm.available:
+ return pkgs
+
+ # If we can use ALPM, we can filter out items that don't actually
+ # conflict due to the version specification.
+ pkgs = pkgs.prefetch_related('conflicts')
+ new_pkgs = []
+ for package in pkgs:
+ for conflict in package.conflicts.all():
+ if conflict.name != self.pkgname:
+ continue
+ if not conflict.comparison or not conflict.version \
+ or alpm.compare_versions(self.full_version,
+ conflict.comparison, conflict.version):
+ new_pkgs.append(package)
+ return new_pkgs
@cache_function(125)
def base_package(self):
diff --git a/packages/models.py b/packages/models.py
index 1959183f..403dfef0 100644
--- a/packages/models.py
+++ b/packages/models.py
@@ -7,6 +7,7 @@ from django.contrib.auth.models import User
from main.models import Arch, Repo, Package
from main.utils import set_created_field, database_vendor
+from packages.alpm import AlpmAPI
class PackageRelation(models.Model):
@@ -341,6 +342,13 @@ class RelatedToBase(models.Model):
# make sure we match architectures if possible
arches = self.pkg.applicable_arches()
pkgs = pkgs.filter(arch__in=arches)
+ # if we have a comparison operation, make sure the packages we grab
+ # actually satisfy the requirements
+ if self.comparison and self.version:
+ alpm = AlpmAPI()
+ pkgs = [pkg for pkg in pkgs if not alpm.available or
+ alpm.compare_versions(pkg.full_version, self.comparison,
+ self.version)]
if len(pkgs) == 0:
# couldn't find a package in the DB
# it should be a virtual depend (or a removed package)
@@ -373,6 +381,21 @@ class RelatedToBase(models.Model):
arches = self.pkg.applicable_arches()
pkgs = pkgs.filter(arch__in=arches)
+ # If we have a comparison operation, make sure the packages we grab
+ # actually satisfy the requirements.
+ alpm = AlpmAPI()
+ if alpm.available and self.comparison and self.version:
+ pkgs = pkgs.prefetch_related('provides')
+ new_pkgs = []
+ for package in pkgs:
+ for provide in package.provides.all():
+ if provide.name != self.name:
+ continue
+ if alpm.compare_versions(provide.version,
+ self.comparison, self.version):
+ new_pkgs.append(package)
+ pkgs = new_pkgs
+
# Logic here is to filter out packages that are in multiple repos if
# they are not requested. For example, if testing is False, only show a
# testing package if it doesn't exist in a non-testing repo.