Edit file File name : dnfdebuginfo.py Content :# coding=UTF-8 ## Copyright (C) 2015 ABRT team <abrt-devel-list@redhat.com> ## Copyright (C) 2015 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA import sys import dnf import dnf.rpm from dnf.exceptions import DownloadError, RepoError from dnf.callback import (STATUS_OK, STATUS_DRPM, STATUS_ALREADY_EXISTS, STATUS_MIRROR, STATUS_FAILED) from reportclient import (_, log1, log2) from reportclient.debuginfo import DebugInfoDownload class DNFProgress(dnf.callback.DownloadProgress): def __init__(self, observer): super(DNFProgress, self).__init__() self.observer = observer def end(self, payload, status, msg): # One may objects that this call back isn't necessary because the # progress() callback is called when downloading finishes, but if the # downloaded package is already in a local cache, DNF doesn't call # progress() callback at all but yet we want to inform user about that # progress. if status in [STATUS_OK, STATUS_DRPM, STATUS_ALREADY_EXISTS]: self.observer.update(str(payload), 100) elif status == STATUS_MIRROR: # In this case dnf (librepo) tries other mirror if available log1("Mirror failed: %s" % (msg or "DNF did not provide more details")) elif status == STATUS_FAILED: log2("Downloading failed: %s" % (msg or "DNF did not provide more details")) else: sys.stderr.write("Unknown DNF download status: %s\n" % (msg)) def progress(self, payload, done): log2("Updated a package") self.observer.update(str(payload), int(100 * (done / payload.download_size))) def start(self, total_files, total_size): log2("Started downloading of a package") class DNFDebugInfoDownload(DebugInfoDownload): def __init__(self, cache, tmp, repo_pattern="*debug*", keep_rpms=False, noninteractive=True, releasever=None): super(DNFDebugInfoDownload, self).__init__(cache, tmp, repo_pattern, keep_rpms, noninteractive) self.progress = None self.base = dnf.Base() if not releasever is None: self.base.conf.substitutions['releasever'] = releasever # bug resurfaces in different forms. if it appears again try uncommenting ###### dnf pre API enforced # self.base.logging.presetup() ###### dnf 1.9 API enforced # self.base._logging.presetup() ###### dnf 2.0 # self.base._logging._presetup() def prepare(self): try: self.base.read_all_repos() except dnf.exceptions.Error as ex: print(_("Error reading repository configuration: '{0!s}'").format(str(ex))) def initialize_progress(self, updater): self.progress = DNFProgress(updater) def initialize_repositories(self): # enable only debug repositories for repo in self.base.repos.all(): repo.disable() for repo in self.base.repos.get_matching(self.repo_pattern): repo.skip_if_unavailable = True repo.enable() try: self.base.fill_sack() except RepoError as ex: print(_("Error setting up repositories: '{0!s}'").format(str(ex))) def triage(self, files): dnf_query = self.base.sack.query() dnf_available = dnf_query.available() package_files_dict = {} not_found = [] todownload_size = 0 installed_size = 0 def required_packages(query, package, origin): """ Recursive function to find all required packages of required packages of ... origin - should stop infinite recursion (A => B => ... => X => A) """ required_pkg_list = [] if package.requires: pkg_reqs = query.filter(provides=package.requires, arch=package.arch) for p in pkg_reqs: if p.name != origin.name and p not in required_pkg_list: required_pkg_list.append(p) required_pkg_list += required_packages(query, p, origin) return required_pkg_list for debuginfo_path in files: di_package_list = [] packages = dnf_available.filter(file=debuginfo_path) if not packages: log2("not found package for %s", debuginfo_path) not_found.append(debuginfo_path) else: di_package_list.append(packages[0]) if packages[0].requires: package_reqs = required_packages(dnf_available, packages[0], packages[0]) for pkg in package_reqs: if pkg not in di_package_list: di_package_list.append(pkg) log2("found required package {0} for {1}".format(pkg, packages[0])) for pkg in di_package_list: if pkg in package_files_dict.keys(): package_files_dict[pkg].append(debuginfo_path) else: package_files_dict[pkg] = [debuginfo_path] todownload_size += float(pkg.downloadsize) installed_size += float(pkg.installsize) log2("found packages for %s: %s", debuginfo_path, pkg) return (package_files_dict, not_found, todownload_size, installed_size) def download_package(self, pkg): try: self.base.download_packages([pkg], self.progress) except DownloadError as ex: return (None, str(ex)) return (pkg.localPkg(), None) Save