From 54e5912a887f353d206538bf6fc5542ae2a69a93 Mon Sep 17 00:00:00 2001 From: Sergey Kulanov Date: Thu, 2 Jun 2016 23:06:04 +0300 Subject: [PATCH] Fix rpm package equality issue If package depends on exact equality of =name+version we also need to search candidates in release section: =name+version+(>=release) eg: name: foo-1.1-3 Requires: bar == 5.5 then the below package must meet the requiremets: name: bar-5.5-56.el7 To make this true we need: * always search for candidates in package.name and package.provides, package.obsoletes, [check PackagesTree.find_all()] * make an assumption that foo-1.1 and foo-1.1-33 has intersection, [check RpmPackageVersion.cmp()] Tests: ====== gen_package() in stubs.generator must always generate Provides section, which is always: name=version, eg: 1) Name: my-python-requests Version: 2.10.0 Release: 1.el7~mos1 will result PROVIDES: my-python-requests = 2.10.0-1.el7~mos1 2) Name: my-python-urllib3 Version: 1.15.1 Release: 7777 Provides: test will result PROVIDES: test my-python-urllib3 = 1.15.1-7777 Change-Id: Ib26918b2e1d98733fbd49f1fc05403ca5665e3fe Closes-Bug: #1588399 --- packetary/drivers/rpm_driver.py | 10 +++++++++- packetary/objects/packages_tree.py | 24 ++++++++++++++++-------- packetary/tests/stubs/generator.py | 7 ++++--- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/packetary/drivers/rpm_driver.py b/packetary/drivers/rpm_driver.py index 720ddee..2a52fac 100644 --- a/packetary/drivers/rpm_driver.py +++ b/packetary/drivers/rpm_driver.py @@ -109,7 +109,15 @@ class RpmPackageVersion(ComparableObject): def cmp(self, other): if not isinstance(other, RpmPackageVersion): other = RpmPackageVersion.from_string(str(other)) - + # if some package doesn't have release then we are processing + # some Require section, so let's assume foo-1.2 == foo-1.2-45 + # in order to build correct list of providers + if self.release == '' or other.release == '': + return rpmUtils.miscutils.compareEVR( + (self.epoch, self.version, ''), + (other.epoch, other.version, '') + ) + # we have full evr, so let's compare them all return rpmUtils.miscutils.compareEVR( (self.epoch, self.version, self.release), (other.epoch, other.version, other.release) diff --git a/packetary/objects/packages_tree.py b/packetary/objects/packages_tree.py index 871eab7..f02df59 100644 --- a/packetary/objects/packages_tree.py +++ b/packetary/objects/packages_tree.py @@ -57,6 +57,7 @@ class PackagesTree(object): """ candidates = self.find_all(name, version_range) if len(candidates) > 0: + # we return candidates in sorted order, so let's take the highest return candidates[-1] return None @@ -67,19 +68,25 @@ class PackagesTree(object): :param version_range: the range of versions. :return: the list of suitable packages """ + candidates = set() + # find package by name if name in self.packages: - candidates = self.packages.find_all(name, version_range) - if len(candidates) > 0: - return candidates + candidates.update(self.packages.find_all(name, version_range)) + # find package by provides + # in case of rpm: + # set(candidates) >= set(provides) if name in self.provides: - result = self._resolve_relation(self.provides[name], version_range) - if result: - return result + candidates.update(self._resolve_relation( + self.provides[name], version_range) + ) if name in self.obsoletes: - return self._resolve_relation(self.obsoletes[name], version_range) - return [] + candidates.update(self._resolve_relation( + self.obsoletes[name], version_range) + ) + + return sorted(candidates, key=lambda x: x.version) def get_unresolved_dependencies(self): """Gets the set of unresolved dependencies. @@ -111,5 +118,6 @@ class PackagesTree(object): result.extend( self.packages.find_all(key[0], VersionRange('=', key[1])) ) + # sort related packages ASC result.sort(key=lambda x: x.version) return result diff --git a/packetary/tests/stubs/generator.py b/packetary/tests/stubs/generator.py index 1218b5a..f836f89 100644 --- a/packetary/tests/stubs/generator.py +++ b/packetary/tests/stubs/generator.py @@ -40,14 +40,15 @@ def gen_package(idx=1, **kwargs): repository = gen_repository() name = kwargs.setdefault("name", "package{0}".format(idx)) kwargs.setdefault("repository", repository) - kwargs.setdefault("version", 1) + version = kwargs.setdefault("version", 1) kwargs.setdefault("checksum", objects.FileChecksum("1", "2", "3")) kwargs.setdefault("filename", "{0}.pkg".format(name)) kwargs.setdefault("filesize", 1) - for relation in ("requires", "provides", "obsoletes"): + kwargs["provides"] = [gen_relation(name, ["=", version])] + for relation in ("requires", "obsoletes"): if relation not in kwargs: kwargs[relation] = [gen_relation( - "{0}{1}".format(relation, idx), ["<=", idx + 1] + "{0}{1}".format(relation, idx), ["<", idx + 1] )] return objects.Package(**kwargs)