def _file_conflict_is_permitted(self, left, right, filename): """ Returns True if rpm would allow both the given packages to share ownership of the given filename. """ if not hasattr(rpm, 'files'): return self._file_conflict_is_permitted_rpm411( left, right, filename) ts = rpm.TransactionSet() ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES) left_hdr = ts.hdrFromFdno(open(left.lookup_location()[0], 'rb')) right_hdr = ts.hdrFromFdno(open(self.download_package(right), 'rb')) left_files = rpm.files(left_hdr) right_files = rpm.files(right_hdr) if left_files[filename].matches(right_files[filename]): logger.debug( 'Conflict on %s between %s and %s permitted because files match', filename, left, right) return True if left_files[filename].color != right_files[filename].color: logger.debug( 'Conflict on %s between %s and %s permitted because colors differ', filename, left, right) return True return False
def test_conflict_is_ignored_if_file_colors_are_different(request, dir_server): # This is part of RPM's multilib support. If two packages own the same file # but the file color is different in each, the preferred color wins (and # there is no conflict). This lets both .i386 and .x86_64 packages own # /bin/bash while installing only the .x86_64 version. p2 = rpmfluff.SimpleRpmBuild('a', '0.1', '1', ['i386', 'x86_64']) p2.add_simple_compilation(installPath='usr/bin/thing') baserepo = rpmfluff.YumRepoBuild([p2]) baserepo.make('i386', 'x86_64') dir_server.basepath = baserepo.repoDir p1 = rpmfluff.SimpleRpmBuild('a', '0.2', '1', ['i386', 'x86_64']) p1.add_simple_compilation(installPath='usr/bin/thing') p1.make() def cleanUp(): shutil.rmtree(baserepo.repoDir) shutil.rmtree(p2.get_base_dir()) shutil.rmtree(p1.get_base_dir()) request.addfinalizer(cleanUp) # Make sure we really have different files with different colors # (this was surprisingly hard to get right) rpmheader_32 = p1.get_built_rpm_header('i386') rpmheader_64 = p1.get_built_rpm_header('x86_64') if hasattr(rpm, 'files'): # rpm 4.12+ assert 1 == rpm.files(rpmheader_32)['/usr/bin/thing'].color assert 2 == rpm.files(rpmheader_64)['/usr/bin/thing'].color else: # sad old rpm < 4.12 fi_32 = rpm.fi(rpmheader_32) while fi_32.FN() != '/usr/bin/thing': fi_32.next() assert fi_32.FColor() == 1 fi_64 = rpm.fi(rpmheader_64) while fi_64.FN() != '/usr/bin/thing': fi_64.next() assert fi_64.FColor() == 2 exitcode, out, err = run_rpmdeplint([ 'rpmdeplint', 'check-conflicts', '--repo=base,{}'.format(dir_server.url), p1.get_built_rpm('i386') ]) assert exitcode == 0
def test_conflict_is_ignored_if_file_colors_are_different(request, dir_server): # This is part of RPM's multilib support. If two packages own the same file # but the file color is different in each, the preferred color wins (and # there is no conflict). This lets both .i386 and .x86_64 packages own # /bin/bash while installing only the .x86_64 version. p2 = rpmfluff.SimpleRpmBuild('a', '0.1', '1', ['i386', 'x86_64']) p2.add_simple_compilation(installPath='usr/bin/thing') baserepo = rpmfluff.YumRepoBuild([p2]) baserepo.make('i386', 'x86_64') dir_server.basepath = baserepo.repoDir p1 = rpmfluff.SimpleRpmBuild('a', '0.2', '1', ['i386', 'x86_64']) p1.add_simple_compilation(installPath='usr/bin/thing') p1.make() def cleanUp(): shutil.rmtree(baserepo.repoDir) shutil.rmtree(p2.get_base_dir()) shutil.rmtree(p1.get_base_dir()) request.addfinalizer(cleanUp) # Make sure we really have different files with different colors # (this was surprisingly hard to get right) rpmheader_32 = p1.get_built_rpm_header('i386') rpmheader_64 = p1.get_built_rpm_header('x86_64') if hasattr(rpm, 'files'): # rpm 4.12+ assert 1 == rpm.files(rpmheader_32)['/usr/bin/thing'].color assert 2 == rpm.files(rpmheader_64)['/usr/bin/thing'].color else: # sad old rpm < 4.12 fi_32 = rpm.fi(rpmheader_32) while fi_32.FN() != '/usr/bin/thing': fi_32.next() assert fi_32.FColor() == 1 fi_64 = rpm.fi(rpmheader_64) while fi_64.FN() != '/usr/bin/thing': fi_64.next() assert fi_64.FColor() == 2 exitcode, out, err = run_rpmdeplint(['rpmdeplint', 'check-conflicts', '--repo=base,{}'.format(dir_server.url), p1.get_built_rpm('i386')]) assert exitcode == 0
def _file_conflict_is_permitted(self, left, right, filename): """ Returns True if rpm would allow both the given packages to share ownership of the given filename. """ if not hasattr(rpm, 'files'): return self._file_conflict_is_permitted_rpm411(left, right, filename) ts = rpm.TransactionSet() ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES) left_hdr = ts.hdrFromFdno(open(left.lookup_location()[0], 'rb')) right_hdr = ts.hdrFromFdno(open(self.download_package(right), 'rb')) left_files = rpm.files(left_hdr) right_files = rpm.files(right_hdr) if left_files[filename].matches(right_files[filename]): logger.debug('Conflict on %s between %s and %s permitted because files match', filename, left, right) return True if left_files[filename].color != right_files[filename].color: logger.debug('Conflict on %s between %s and %s permitted because colors differ', filename, left, right) return True return False
def _check_rpm(self, repo, rpm_dir, rpm_file, test_name): """Check the contents of the rpm against the expected test results """ ts = rpm.TransactionSet() fd = os.open(os.path.join(rpm_dir, rpm_file), os.O_RDONLY) hdr = ts.hdrFromFdno(fd) os.close(fd) self.assertEqual(hdr[rpm.RPMTAG_NAME].decode("UTF-8"), repo["rpmname"]) self.assertEqual(hdr[rpm.RPMTAG_VERSION].decode("UTF-8"), repo["rpmversion"]) self.assertEqual(hdr[rpm.RPMTAG_RELEASE].decode("UTF-8"), repo["rpmrelease"]) self.assertEqual(hdr[rpm.RPMTAG_URL].decode("UTF-8"), repo["repo"]) files = sorted(f.name for f in rpm.files(hdr) if stat.S_ISREG(f.mode)) self.assertEqual(files, [os.path.join(repo["destination"], f) for f in self.test_results[test_name]])
def read_rpm(filename): rpm.addMacro("_dbpath", os.path.join(dirname(__file__), "fake_pkg_db")) rpm.addMacro("_topdir", dirname(__file__)) ts = rpm.TransactionSet( ".", rpm.RPMVSF_MASK_NODIGESTS | rpm.RPMVSF_MASK_NOSIGNATURES) fd = rpm.fd.open(filename) header = ts.hdrFromFdno(fd) # hdr[rpm.RPMTAG_NAME] = "test_rpm" # fo = os.fdopen(fd, "w+") # hdr.write(fd) print(header[rpm.RPMTAG_NAME]) files = rpm.files(header) payload = rpm.fd.open(fd, flags=header["payloadcompressor"]) archive = files.archive(payload, write=False) for t in archive: if t.fflags & rpm.RPMFILE_SPECFILE: od = os.open(t.name, os.O_RDWR | os.O_CREAT) archive.readto(od) print(t.name)
def spec_from_srpm(srpm_path): ts = rpm.ts() fd = rpm.fd.open(srpm_path) try: hdr = ts.hdrFromFdno(fd) if not hdr.isSource(): raise ValueError('Not an SRPM: {}'.format(srpm_path)) files = rpm.files(hdr) payload = rpm.fd.open(fd, flags=bytes(hdr['PAYLOADCOMPRESSOR']).decode()) try: archive = files.archive(payload) for f in archive: if f.fflags & rpm.RPMFILE_SPECFILE: return archive.read() finally: rpm.fd.close(payload) finally: rpm.fd.close(fd) raise ValueError('No spec file found in SRPM: {}'.format(srpm_path))
def _check_rpm(self, repo, rpm_dir, rpm_file, test_name): """Check the contents of the rpm against the expected test results """ ts = rpm.TransactionSet() fd = os.open(os.path.join(rpm_dir, rpm_file), os.O_RDONLY) hdr = ts.hdrFromFdno(fd) os.close(fd) self.assertEqual(hdr[rpm.RPMTAG_NAME], repo["rpmname"]) self.assertEqual(hdr[rpm.RPMTAG_VERSION], repo["rpmversion"]) self.assertEqual(hdr[rpm.RPMTAG_RELEASE], repo["rpmrelease"]) self.assertEqual(hdr[rpm.RPMTAG_URL], repo["repo"]) files = sorted(f.name for f in rpm.files(hdr) if stat.S_ISREG(f.mode)) self.assertEqual(files, [ os.path.join(repo["destination"], f) for f in self.test_results[test_name] ]) # / should never be included in the rpm, doing so conflicts with the filesystem package self.assertFalse(any(True for f in files if f == "/"))