File Explorer

/proc/self/root/proc/thread-self/root/usr/lib/python3.9/site-packages/dnf/cli/commands

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

check.py7.1 KB · 149 lines
## Copyright (C) 2016 Red Hat, Inc.## This copyrighted material is made available to anyone wishing to use,# modify, copy, or redistribute it subject to the terms and conditions of# the GNU General Public License v.2, or (at your option) any later version.# This program is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY expressed or implied, including the implied warranties 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, Fifth Floor, Boston, MA# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the# source code or documentation are not subject to the GNU General Public# License and may only be used or replicated with the express permission of# Red Hat, Inc.# from __future__ import absolute_importfrom __future__ import unicode_literalsfrom dnf.i18n import _from dnf.cli import commands import argparseimport dnf.exceptions  class CheckCommand(commands.Command):    """A class containing methods needed by the cli to execute the check    command.    """     aliases = ('check',)    summary = _('check for problems in the packagedb')     @staticmethod    def set_argparser(parser):        parser.add_argument('--all', dest='check_types',                            action='append_const', const='all',                            help=_('show all problems; default'))        parser.add_argument('--dependencies', dest='check_types',                            action='append_const', const='dependencies',                            help=_('show dependency problems'))        parser.add_argument('--duplicates', dest='check_types',                            action='append_const', const='duplicates',                            help=_('show duplicate problems'))        parser.add_argument('--obsoleted', dest='check_types',                            action='append_const', const='obsoleted',                            help=_('show obsoleted packages'))        parser.add_argument('--provides', dest='check_types',                            action='append_const', const='provides',                            help=_('show problems with provides'))        # Add compatibility with yum but invisible in help        # In choices [] allows to return empty list if no argument otherwise it fails        parser.add_argument('check_yum_types', nargs='*', choices=[            'all', 'dependencies', 'duplicates', 'obsoleted', 'provides', []],                            help=argparse.SUPPRESS)     def configure(self):        self.cli.demands.sack_activation = True        if self.opts.check_yum_types:            if self.opts.check_types:                self.opts.check_types = self.opts.check_types + \                                        self.opts.check_yum_types            else:                self.opts.check_types = self.opts.check_yum_types        if not self.opts.check_types:            self.opts.check_types = {'all'}        else:            self.opts.check_types = set(self.opts.check_types)        self.base.conf.disable_excludes += ["all"]     def run(self):        output_set = set()        q = self.base.sack.query().installed()         if self.opts.check_types.intersection({'all', 'dependencies'}):            sack = None            for pkg in q:                for require in set(pkg.regular_requires) | set(set(pkg.requires_pre) - set(pkg.prereq_ignoreinst)):                    if str(require).startswith('rpmlib'):                        continue                    if not len(q.filter(provides=[require])):                        if str(require).startswith('('):                            # rich deps can be only tested by solver                            if sack is None:                                sack = dnf.sack.rpmdb_sack(self.base)                            selector = dnf.selector.Selector(sack)                            selector.set(provides=str(require))                            goal = dnf.goal.Goal(sack)                            goal.protect_running_kernel = self.base.conf.protect_running_kernel                            goal.install(select=selector, optional=False)                            solved = goal.run()                            # there ase only @system repo in sack, therefore solved is only in case                            # when rich deps doesn't require any additional package                            if solved:                                continue                        msg = _("{} has missing requires of {}")                        output_set.add(msg.format(                            self.base.output.term.bold(pkg),                            self.base.output.term.bold(require)))                for conflict in pkg.conflicts:                    conflicted = q.filter(provides=[conflict],                                          name=str(conflict).split()[0])                    for conflict_pkg in conflicted:                        msg = '{} has installed conflict "{}": {}'                        output_set.add(msg.format(                            self.base.output.term.bold(pkg),                            self.base.output.term.bold(conflict),                            self.base.output.term.bold(conflict_pkg)))         if self.opts.check_types.intersection({'all', 'duplicates'}):            installonly = self.base._get_installonly_query(q)            dups = q.duplicated().difference(installonly)._name_dict()            for name, pkgs in dups.items():                pkgs.sort()                for dup in pkgs[1:]:                    msg = _("{} is a duplicate with {}").format(                        self.base.output.term.bold(pkgs[0]),                        self.base.output.term.bold(dup))                    output_set.add(msg)         if self.opts.check_types.intersection({'all', 'obsoleted'}):            for pkg in q:                for obsolete in pkg.obsoletes:                    obsoleted = q.filter(provides=[obsolete],                                         name=str(obsolete).split()[0])                    if len(obsoleted):                        msg = _("{} is obsoleted by {}").format(                            self.base.output.term.bold(obsoleted[0]),                            self.base.output.term.bold(pkg))                        output_set.add(msg)         if self.opts.check_types.intersection({'all', 'provides'}):            for pkg in q:                for provide in pkg.provides:                    if pkg not in q.filter(provides=[provide]):                        msg = _("{} provides {} but it cannot be found")                        output_set.add(msg.format(                            self.base.output.term.bold(pkg),                            self.base.output.term.bold(provide)))         for msg in sorted(output_set):            print(msg)         if output_set:            raise dnf.exceptions.Error(                'Check discovered {} problem(s)'.format(len(output_set)))