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
This commit is contained in:
Sergey Kulanov 2016-06-02 23:06:04 +03:00
parent 07079a0b55
commit 54e5912a88
3 changed files with 29 additions and 12 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)