diff options
-rw-r--r-- | main/models.py | 55 | ||||
-rw-r--r-- | packages/models.py | 23 |
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. |