diff --git a/dnf/package.py b/dnf/package.py index baef04f..836e0e4 100644 --- a/dnf/package.py +++ b/dnf/package.py @@ -26,11 +26,13 @@ from __future__ import unicode_literals from dnf.i18n import _ import binascii +import dnf.exceptions import dnf.rpm import dnf.yum.misc import hawkey import logging import os +import rpm logger = logging.getLogger("dnf") @@ -95,6 +97,11 @@ class Package(hawkey.Package): @property def _header(self): + """ + Returns the header of a locally present rpm package file. As opposed to + self.get_header(), which retrieves the header of an installed package + from rpmdb. + """ return dnf.rpm._header(self.localPkg()) @property @@ -164,6 +171,23 @@ class Package(hawkey.Package): src_name = self.source_name if self.source_name is not None else self.name return src_name + self.DEBUGSOURCE_SUFFIX + def get_header(self): + """ + Returns the rpm header of the package if it is installed. If not + installed, returns None. The header is not cached, it is retrieved from + rpmdb on every call. In case of a failure (e.g. when the rpmdb changes + between loading the data and calling this method), raises an instance + of PackageNotFoundError. + """ + if not self._from_system: + return None + + try: + # RPMDBI_PACKAGES stands for the header of the package + return next(self.base._ts.dbMatch(rpm.RPMDBI_PACKAGES, self.rpmdbid)) + except StopIteration: + raise dnf.exceptions.PackageNotFoundError("Package not found when attempting to retrieve header", str(self)) + @property def source_debug_name(self): # :api diff --git a/tests/test_package.py b/tests/test_package.py index cd4872e..514e5bf 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -68,6 +68,18 @@ class PackageTest(tests.support.DnfBaseTestCase): with self.assertRaises(IOError): pkg._header + # rpm.hdr() is not easy to construct with custom data, we just return a string + # instead, as we don't actually need an instance of rpm.hdr for the test + @mock.patch("rpm.TransactionSet.dbMatch", lambda self, a, b: iter(["package_header_test_data"])) + def test_get_header(self): + pkg = self.sack.query().installed().filter(name="pepper")[0] + header = pkg.get_header() + self.assertEqual(header, "package_header_test_data") + + pkg = self.sack.query().available().filter(name="pepper")[0] + header = pkg.get_header() + self.assertEqual(header, None) + @mock.patch("dnf.package.Package.rpmdbid", long(3)) def test_idx(self): """ pkg.idx is an int. """