diff --git a/abichecker/abichecker.py b/abichecker/abichecker.py index eb8b2db7..9c815303 100755 --- a/abichecker/abichecker.py +++ b/abichecker/abichecker.py @@ -43,18 +43,19 @@ PROJECT_BLACKLIST = { 'SUSE:SLE-11-SP2:Update' : "abi-checker doesn't support SLE 11", 'SUSE:SLE-11-SP3:Update' : "abi-checker doesn't support SLE 11", 'SUSE:SLE-11-SP4:Update' : "abi-checker doesn't support SLE 11", + 'SUSE:SLE-11-SP5:Update' : "abi-checker doesn't support SLE 11", } # some project have more repos than what we are interested in REPO_WHITELIST = { 'openSUSE:Factory': ('standard', 'snapshot'), - 'openSUSE:13.1:Update': 'standard', - 'openSUSE:13.2:Update': 'standard', - 'SUSE:SLE-12:Update' : 'standard', } # same for arch +ARCH_BLACKLIST = { + } + ARCH_WHITELIST = { 'SUSE:SLE-12:Update' : ('i586', 'ppc64le', 's390', 's390x', 'x86_64'), } @@ -207,7 +208,6 @@ class ABIChecker(ReviewBot.ReviewBot): if dst_srcinfo is None: msg = "%s/%s seems to be a new package, no need to review"%(dst_project, dst_package) self.logger.info(msg) - self.text_summary += msg + "\n" self.reports.append(report) return True src_srcinfo = self.get_sourceinfo(src_project, src_package, src_rev) @@ -288,7 +288,7 @@ class ABIChecker(ReviewBot.ReviewBot): for mr in myrepos: try: - dst_libs = self.extract(dst_project, dst_package, dst_srcinfo, mr.dstrepo, mr.arch) + dst_libs, dst_libdebug = self.extract(dst_project, dst_package, dst_srcinfo, mr.dstrepo, mr.arch) # nothing to fetch, so no libs if dst_libs is None: continue @@ -308,7 +308,7 @@ class ABIChecker(ReviewBot.ReviewBot): continue try: - src_libs = self.extract(src_project, src_package, src_srcinfo, mr.srcrepo, mr.arch) + src_libs, src_libdebug = self.extract(src_project, src_package, src_srcinfo, mr.srcrepo, mr.arch) if src_libs is None: if dst_libs: self.text_summary += "*Warning*: the submission does not contain any libs anymore\n\n" @@ -357,10 +357,10 @@ class ABIChecker(ReviewBot.ReviewBot): # for each pair dump and compare the abi for old, new in pairs: # abi dump of old lib - new_base = os.path.join(UNPACKDIR, dst_project, dst_package, mr.dstrepo, mr.arch) + old_base = os.path.join(UNPACKDIR, dst_project, dst_package, mr.dstrepo, mr.arch) old_dump = os.path.join(CACHEDIR, 'old.dump') # abi dump of new lib - old_base = os.path.join(UNPACKDIR, src_project, src_package, mr.srcrepo, mr.arch) + new_base = os.path.join(UNPACKDIR, src_project, src_package, mr.srcrepo, mr.arch) new_dump = os.path.join(CACHEDIR, 'new.dump') def cleanup(): @@ -373,12 +373,12 @@ class ABIChecker(ReviewBot.ReviewBot): # we just need that to pass a name to abi checker m = so_re.match(old) - htmlreport = 'report-%s-%s-%s-%s-%s-%08x.html'%(mr.srcrepo, os.path.basename(old), mr.dstrepo, os.path.basename(new), mr.arch, time.time()) + htmlreport = 'report-%s-%s-%s-%s-%s-%08x.html'%(mr.srcrepo, os.path.basename(old), mr.dstrepo, os.path.basename(new), mr.arch, int(time.time())) # run abichecker if m \ - and self.run_abi_dumper(old_dump, new_base, old) \ - and self.run_abi_dumper(new_dump, old_base, new): + and self.run_abi_dumper(old_dump, old_base, old, dst_libdebug[old]) \ + and self.run_abi_dumper(new_dump, new_base, new, src_libdebug[new]): reportfn = os.path.join(CACHEDIR, htmlreport) r = self.run_abi_checker(m.group(1), old_dump, new_dump, reportfn) if r is not None: @@ -647,14 +647,12 @@ class ABIChecker(ReviewBot.ReviewBot): return None return r == 0 - def run_abi_dumper(self, output, base, filename): + def run_abi_dumper(self, output, base, filename, debuglib): cmd = ['abi-dumper', '-o', output, '-lver', os.path.basename(filename), '/'.join([base, filename])] - debuglib = '%s/usr/lib/debug/%s.debug'%(base, filename) - if os.path.exists(debuglib): - cmd.append(debuglib) + cmd.append('/'.join([base, debuglib])) self.logger.debug(cmd) r = subprocess.Popen(cmd, close_fds=True, cwd=CACHEDIR).wait() if r != 0: @@ -666,12 +664,12 @@ class ABIChecker(ReviewBot.ReviewBot): def extract(self, project, package, srcinfo, repo, arch): # fetch cpio headers # check file lists for library packages - fetchlist, liblist = self.compute_fetchlist(project, package, srcinfo, repo, arch) + fetchlist, liblist, debuglist = self.compute_fetchlist(project, package, srcinfo, repo, arch) if not fetchlist: msg = "no libraries found in %s/%s %s/%s"%(project, package, repo, arch) self.logger.info(msg) - return None + return None, None # mtimes in cpio are not the original ones, so we need to fetch # that separately :-( @@ -679,8 +677,9 @@ class ABIChecker(ReviewBot.ReviewBot): self.logger.debug("fetchlist %s", pformat(fetchlist)) self.logger.debug("liblist %s", pformat(liblist)) + self.logger.debug("debuglist %s", pformat(debuglist)) - debugfiles = set(['/usr/lib/debug%s.debug'%f for f in liblist]) + debugfiles = debuglist.values() # fetch binary rpms downloaded = self.download_files(project, package, repo, arch, fetchlist, mtimes) @@ -701,7 +700,7 @@ class ABIChecker(ReviewBot.ReviewBot): cpio = CpioRead(tmpfile) cpio.read() for ch in cpio: - fn = ch.filename + fn = ch.filename.decode('utf-8') if fn.startswith('./'): # rpm payload is relative fn = fn[1:] self.logger.debug("cpio fn %s", fn) @@ -719,12 +718,12 @@ class ABIChecker(ReviewBot.ReviewBot): with open(dst, 'wb') as fh: while True: buf = cpiofh.read(4096) - if buf is None or buf == '': + if buf is None or buf == b'': break fh.write(buf) os.unlink(tmpfile) - return liblist + return liblist, debuglist def download_files(self, project, package, repo, arch, filenames, mtimes): downloaded = dict() @@ -852,6 +851,9 @@ class ABIChecker(ReviewBot.ReviewBot): if project in ARCH_WHITELIST and arch not in ARCH_WHITELIST[project]: continue + if project in ARCH_BLACKLIST and arch in ARCH_BLACKLIST[project]: + continue + repos.add((name, arch)) return repos @@ -913,6 +915,8 @@ class ABIChecker(ReviewBot.ReviewBot): for node in repo.findall('arch'): arch = node.text dstname = path[0].attrib['repository'] + if prj == 'openSUSE:Factory' and dstname == 'snapshot': + dstname = 'standard' # XXX: hack if (dstname, arch) in dstrepos: matchrepos.add(MR(name, dstname, arch)) @@ -940,7 +944,7 @@ class ABIChecker(ReviewBot.ReviewBot): # common with repochecker def _md5_disturl(self, disturl): """Get the md5 from the DISTURL from a RPM file.""" - return os.path.basename(disturl.decode('utf-8')).split('-')[0] + return os.path.basename(disturl).split('-')[0] def disturl_matches_md5(self, disturl, md5): if self._md5_disturl(disturl) != md5: @@ -974,19 +978,21 @@ class ABIChecker(ReviewBot.ReviewBot): # skip src rpm if h['sourcepackage']: continue - pkgname = h['name'] - if pkgname.endswith(b'-32bit') or pkgname.endswith(b'-64bit'): + pkgname = h['name'].decode('utf-8') + if pkgname.endswith('-32bit') or pkgname.endswith('-64bit'): # -32bit and -64bit packages are just repackaged, so # we skip them and only check the original one. continue - self.logger.debug(pkgname) - if not self.disturl_matches(h['disturl'], prj, srcinfo): - raise DistUrlMismatch(h['disturl'], srcinfo) + self.logger.debug("inspecting %s", pkgname) + if not self.disturl_matches(h['disturl'].decode('utf-8'), prj, srcinfo): + raise DistUrlMismatch(h['disturl'].decode('utf-8'), srcinfo) pkgs[pkgname] = (rpmfn, h) - if debugpkg_re.match(pkgname.decode('utf-8')): + if debugpkg_re.match(pkgname): continue for fn, mode, lnk in zip(h['filenames'], h['filemodes'], h['filelinktos']): - if so_re.match(fn.decode('utf-8')): + fn = fn.decode('utf-8') + lnk = lnk.decode('utf-8') + if so_re.match(fn): if S_ISREG(mode): self.logger.debug('found lib: %s'%fn) lib_packages.setdefault(pkgname, set()).add(fn) @@ -998,9 +1004,9 @@ class ABIChecker(ReviewBot.ReviewBot): fetchlist = set() liblist = dict() + debuglist = dict() # check whether debug info exists for each lib for pkgname in sorted(lib_packages.keys()): - pkgname = pkgname.decode('utf-8') dpkgname = pkgname+'-debuginfo' if not dpkgname in pkgs: missing_debuginfo.add((prj, pkg, repo, arch, pkgname)) @@ -1008,17 +1014,31 @@ class ABIChecker(ReviewBot.ReviewBot): # check file list of debuginfo package rpmfn, h = pkgs[dpkgname] - files = set (h['filenames']) + files = set ([f.decode('utf-8') for f in h['filenames']]) ok = True for lib in lib_packages[pkgname]: - fn = '/usr/lib/debug%s.debug'%lib - if not fn in files: - missing_debuginfo.add((prj, pkg, repo, arch, pkgname, lib)) - ok = False + libdebug = '/usr/lib/debug%s.debug'%lib + if not libdebug in files: + # some new format that includes version, release and arch in debuginfo? + # FIXME: version and release are actually the + # one from the main package, sub packages may + # differ. BROKEN RIGHT NOW + # XXX: would have to actually read debuglink + # info to get that right so just guessing + arch = h['arch'].decode('utf-8') + if arch == 'i586': + arch = 'i386' + libdebug = '/usr/lib/debug%s-%s-%s.%s.debug'%(lib, + h['version'].decode('utf-8'), h['release'].decode('utf-8'), arch) + if not libdebug in files: + missing_debuginfo.add((prj, pkg, repo, arch, pkgname, lib)) + ok = False + if ok: fetchlist.add(pkgs[pkgname][0]) fetchlist.add(rpmfn) liblist.setdefault(lib, set()) + debuglist.setdefault(lib, libdebug) libname = os.path.basename(lib) if libname in lib_aliases: liblist[lib] |= lib_aliases[libname] @@ -1027,7 +1047,7 @@ class ABIChecker(ReviewBot.ReviewBot): self.logger.error('missing debuginfo: %s'%pformat(missing_debuginfo)) raise MissingDebugInfo(missing_debuginfo) - return fetchlist, liblist + return fetchlist, liblist, debuglist class CommandLineInterface(ReviewBot.CommandLineInterface):