Blame dnf/cli/cli.py

Packit Service 21c75c
# Copyright 2005 Duke University
Packit Service 21c75c
# Copyright (C) 2012-2016 Red Hat, Inc.
Packit Service 21c75c
#
Packit Service 21c75c
# This program is free software; you can redistribute it and/or modify
Packit Service 21c75c
# it under the terms of the GNU General Public License as published by
Packit Service 21c75c
# the Free Software Foundation; either version 2 of the License, or
Packit Service 21c75c
# (at your option) any later version.
Packit Service 21c75c
#
Packit Service 21c75c
# This program is distributed in the hope that it will be useful,
Packit Service 21c75c
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 21c75c
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 21c75c
# GNU Library General Public License for more details.
Packit Service 21c75c
#
Packit Service 21c75c
# You should have received a copy of the GNU General Public License
Packit Service 21c75c
# along with this program; if not, write to the Free Software
Packit Service 21c75c
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 21c75c
#
Packit Service 21c75c
# Written by Seth Vidal
Packit Service 21c75c
Packit Service 21c75c
"""
Packit Service 21c75c
Command line interface yum class and related.
Packit Service 21c75c
"""
Packit Service 21c75c
Packit Service 21c75c
from __future__ import print_function
Packit Service 21c75c
from __future__ import absolute_import
Packit Service 21c75c
from __future__ import unicode_literals
Packit Service 21c75c
Packit Service 21c75c
try:
Packit Service 21c75c
    from collections.abc import Sequence
Packit Service 21c75c
except ImportError:
Packit Service 21c75c
    from collections import Sequence
Packit Service 21c75c
import datetime
Packit Service 21c75c
import logging
Packit Service 21c75c
import operator
Packit Service 21c75c
import os
Packit Service 21c75c
import random
Packit Service 21c75c
import rpm
Packit Service 21c75c
import sys
Packit Service 21c75c
import time
Packit Service 21c75c
Packit Service 21c75c
import hawkey
Packit Service 21c75c
import libdnf.transaction
Packit Service 21c75c
Packit Service 21c75c
from . import output
Packit Service 21c75c
from dnf.cli import CliError
Packit Service 21c75c
from dnf.i18n import ucd, _
Packit Service 21c75c
import dnf
Packit Service 21c75c
import dnf.cli.aliases
Packit Service 21c75c
import dnf.cli.commands
Packit Service 21c75c
import dnf.cli.commands.alias
Packit Service 21c75c
import dnf.cli.commands.autoremove
Packit Service 21c75c
import dnf.cli.commands.check
Packit Service 21c75c
import dnf.cli.commands.clean
Packit Service 21c75c
import dnf.cli.commands.deplist
Packit Service 21c75c
import dnf.cli.commands.distrosync
Packit Service 21c75c
import dnf.cli.commands.downgrade
Packit Service 21c75c
import dnf.cli.commands.group
Packit Service 21c75c
import dnf.cli.commands.history
Packit Service 21c75c
import dnf.cli.commands.install
Packit Service 21c75c
import dnf.cli.commands.makecache
Packit Service 21c75c
import dnf.cli.commands.mark
Packit Service 21c75c
import dnf.cli.commands.module
Packit Service 21c75c
import dnf.cli.commands.reinstall
Packit Service 21c75c
import dnf.cli.commands.remove
Packit Service 21c75c
import dnf.cli.commands.repolist
Packit Service 21c75c
import dnf.cli.commands.repoquery
Packit Service 21c75c
import dnf.cli.commands.search
Packit Service 21c75c
import dnf.cli.commands.shell
Packit Service 21c75c
import dnf.cli.commands.swap
Packit Service 21c75c
import dnf.cli.commands.updateinfo
Packit Service 21c75c
import dnf.cli.commands.upgrade
Packit Service 21c75c
import dnf.cli.commands.upgrademinimal
Packit Service 21c75c
import dnf.cli.demand
Packit Service 21c75c
import dnf.cli.format
Packit Service 21c75c
import dnf.cli.option_parser
Packit Service 21c75c
import dnf.conf
Packit Service 21c75c
import dnf.conf.substitutions
Packit Service 21c75c
import dnf.const
Packit Service 21c75c
import dnf.db.history
Packit Service 21c75c
import dnf.exceptions
Packit Service 21c75c
import dnf.logging
Packit Service 21c75c
import dnf.persistor
Packit Service 21c75c
import dnf.plugin
Packit Service 21c75c
import dnf.rpm
Packit Service 21c75c
import dnf.sack
Packit Service 21c75c
import dnf.transaction
Packit Service 21c75c
import dnf.util
Packit Service 21c75c
import dnf.yum.misc
Packit Service 21c75c
Packit Service 21c75c
logger = logging.getLogger('dnf')
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _add_pkg_simple_list_lens(data, pkg, indent=''):
Packit Service 21c75c
    """ Get the length of each pkg's column. Add that to data.
Packit Service 21c75c
        This "knows" about simpleList and printVer. """
Packit Service 21c75c
    na = len(pkg.name) + 1 + len(pkg.arch) + len(indent)
Packit Service 21c75c
    ver = len(pkg.evr)
Packit Service 21c75c
    rid = len(pkg._from_repo)
Packit Service 21c75c
    for (d, v) in (('na', na), ('ver', ver), ('rid', rid)):
Packit Service 21c75c
        data[d].setdefault(v, 0)
Packit Service 21c75c
        data[d][v] += 1
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _list_cmd_calc_columns(output, ypl):
Packit Service 21c75c
    """ Work out the dynamic size of the columns to pass to fmtColumns. """
Packit Service 21c75c
    data = {'na' : {}, 'ver' : {}, 'rid' : {}}
Packit Service 21c75c
    for lst in (ypl.installed, ypl.available, ypl.extras, ypl.autoremove,
Packit Service 21c75c
                ypl.updates, ypl.recent):
Packit Service 21c75c
        for pkg in lst:
Packit Service 21c75c
            _add_pkg_simple_list_lens(data, pkg)
Packit Service 21c75c
    if len(ypl.obsoletes) > 0:
Packit Service 21c75c
        for (npkg, opkg) in ypl.obsoletesTuples:
Packit Service 21c75c
            _add_pkg_simple_list_lens(data, npkg)
Packit Service 21c75c
            _add_pkg_simple_list_lens(data, opkg, indent=" " * 4)
Packit Service 21c75c
Packit Service 21c75c
    data = [data['na'], data['ver'], data['rid']]
Packit Service 21c75c
    columns = output.calcColumns(data, remainder_column=1)
Packit Service 21c75c
    return (-columns[0], -columns[1], -columns[2])
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def print_versions(pkgs, base, output):
Packit Service 21c75c
    def sm_ui_time(x):
Packit Service 21c75c
        return time.strftime("%c", time.gmtime(x))
Packit Service 21c75c
Packit Service 21c75c
    rpmdb_sack = dnf.sack.rpmdb_sack(base)
Packit Service 21c75c
    done = False
Packit Service 21c75c
    for pkg in rpmdb_sack.query().installed().filterm(name=pkgs):
Packit Service 21c75c
        if done:
Packit Service 21c75c
            print("")
Packit Service 21c75c
        done = True
Packit Service 21c75c
        if pkg.epoch == '0':
Packit Service 21c75c
            ver = '%s-%s.%s' % (pkg.version, pkg.release, pkg.arch)
Packit Service 21c75c
        else:
Packit Service 21c75c
            ver = '%s:%s-%s.%s' % (pkg.epoch,
Packit Service 21c75c
                                   pkg.version, pkg.release, pkg.arch)
Packit Service 21c75c
        name = output.term.bold(pkg.name)
Packit Service 21c75c
        print(_("  Installed: %s-%s at %s") %(name, ver,
Packit Service 21c75c
                                              sm_ui_time(pkg.installtime)))
Packit Service 21c75c
        print(_("  Built    : %s at %s") % (pkg.packager if pkg.packager else "",
Packit Service 21c75c
                                            sm_ui_time(pkg.buildtime)))
Packit Service 21c75c
        # :hawkey, no changelist information yet
Packit Service 21c75c
        # print(_("  Committed: %s at %s") % (pkg.committer,
Packit Service 21c75c
        #                                    sm_ui_date(pkg.committime)))
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def report_module_switch(switchedModules):
Packit Service 21c75c
    msg1 = _("The operation would result in switching of module '{0}' stream '{1}' to "
Packit Service 21c75c
             "stream '{2}'")
Packit Service 21c75c
    for moduleName, streams in switchedModules.items():
Packit Service 21c75c
        logger.warning(msg1.format(moduleName, streams[0], streams[1]))
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
class BaseCli(dnf.Base):
Packit Service 21c75c
    """This is the base class for yum cli."""
Packit Service 21c75c
Packit Service 21c75c
    def __init__(self, conf=None):
Packit Service 21c75c
        conf = conf or dnf.conf.Conf()
Packit Service 21c75c
        super(BaseCli, self).__init__(conf=conf)
Packit Service 21c75c
        self.output = output.Output(self, self.conf)
Packit Service 21c75c
Packit Service 21c75c
    def do_transaction(self, display=()):
Packit Service 21c75c
        """Take care of package downloading, checking, user
Packit Service 21c75c
        confirmation and actually running the transaction.
Packit Service 21c75c
Packit Service 21c75c
        :param display: `rpm.callback.TransactionProgress` object(s)
Packit Service 21c75c
        :return: history database transaction ID or None
Packit Service 21c75c
        """
Packit Service 21c75c
        if dnf.base.WITH_MODULES:
Packit Service 21c75c
            switchedModules = dict(self._moduleContainer.getSwitchedStreams())
Packit Service 21c75c
            if switchedModules:
Packit Service 21c75c
                report_module_switch(switchedModules)
Packit Service 21c75c
                msg = _("It is not possible to switch enabled streams of a module.\n"
Packit Service 21c75c
                        "It is recommended to remove all installed content from the module, and "
Packit Service 21c75c
                        "reset the module using '{prog} module reset <module_name>' command. After "
Packit Service 21c75c
                        "you reset the module, you can install the other stream.").format(
Packit Service 21c75c
                    prog=dnf.util.MAIN_PROG)
Packit Service 21c75c
                raise dnf.exceptions.Error(msg)
Packit Service 21c75c
Packit Service 21c75c
        trans = self.transaction
Packit Service 21c75c
        pkg_str = self.output.list_transaction(trans)
Packit Service 21c75c
        if pkg_str:
Packit Service 21c75c
            logger.info(pkg_str)
Packit Service 21c75c
Packit Service 21c75c
        if trans:
Packit Service 21c75c
            # Check which packages have to be downloaded
Packit Service 21c75c
            install_pkgs = []
Packit Service 21c75c
            rmpkgs = []
Packit Service 21c75c
            install_only = True
Packit Service 21c75c
            for tsi in trans:
Packit Service 21c75c
                if tsi.action in dnf.transaction.FORWARD_ACTIONS:
Packit Service 21c75c
                    install_pkgs.append(tsi.pkg)
Packit Service 21c75c
                elif tsi.action in dnf.transaction.BACKWARD_ACTIONS:
Packit Service 21c75c
                    install_only = False
Packit Service 21c75c
                    rmpkgs.append(tsi.pkg)
Packit Service 21c75c
Packit Service 21c75c
            # Close the connection to the rpmdb so that rpm doesn't hold the
Packit Service 21c75c
            # SIGINT handler during the downloads.
Packit Service 21c75c
            del self._ts
Packit Service 21c75c
Packit Service 21c75c
            # report the total download size to the user
Packit Service 21c75c
            if not install_pkgs:
Packit Service 21c75c
                self.output.reportRemoveSize(rmpkgs)
Packit Service 21c75c
            else:
Packit Service 21c75c
                self.output.reportDownloadSize(install_pkgs, install_only)
Packit Service 21c75c
Packit Service 21c75c
        if trans or self._moduleContainer.isChanged() or \
Packit Service 21c75c
                (self._history and (self._history.group or self._history.env)):
Packit Service 21c75c
            # confirm with user
Packit Service 21c75c
            if self.conf.downloadonly:
Packit Service 21c75c
                logger.info(_("{prog} will only download packages for the transaction.").format(
Packit Service 21c75c
                    prog=dnf.util.MAIN_PROG_UPPER))
Packit Service 21c75c
            elif 'test' in self.conf.tsflags:
Packit Service 21c75c
                logger.info(_("{prog} will only download packages, install gpg keys, and check the "
Packit Service 21c75c
                              "transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
Packit Service 21c75c
            if self._promptWanted():
Packit Service 21c75c
                if self.conf.assumeno or not self.output.userconfirm():
Packit Service 21c75c
                    raise CliError(_("Operation aborted."))
Packit Service 21c75c
        else:
Packit Service 21c75c
            logger.info(_('Nothing to do.'))
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        if trans:
Packit Service 21c75c
            if install_pkgs:
Packit Service 21c75c
                logger.info(_('Downloading Packages:'))
Packit Service 21c75c
                try:
Packit Service 21c75c
                    total_cb = self.output.download_callback_total_cb
Packit Service 21c75c
                    self.download_packages(install_pkgs, self.output.progress, total_cb)
Packit Service 21c75c
                except dnf.exceptions.DownloadError as e:
Packit Service 21c75c
                    specific = dnf.cli.format.indent_block(ucd(e))
Packit Service 21c75c
                    errstr = _('Error downloading packages:') + '\n%s' % specific
Packit Service 21c75c
                    # setting the new line to prevent next chars being eaten up
Packit Service 21c75c
                    # by carriage returns
Packit Service 21c75c
                    print()
Packit Service 21c75c
                    raise dnf.exceptions.Error(errstr)
Packit Service 21c75c
            # Check GPG signatures
Packit Service 21c75c
            self.gpgsigcheck(install_pkgs)
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.downloadonly:
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        if not isinstance(display, Sequence):
Packit Service 21c75c
            display = [display]
Packit Service 21c75c
        display = [output.CliTransactionDisplay()] + list(display)
Packit Service 21c75c
        tid = super(BaseCli, self).do_transaction(display)
Packit Service 21c75c
Packit Service 21c75c
        # display last transaction (which was closed during do_transaction())
Packit Service 21c75c
        if tid is not None:
Packit Service 21c75c
            trans = self.history.old([tid])[0]
Packit Service 21c75c
            trans = dnf.db.group.RPMTransaction(self.history, trans._trans)
Packit Service 21c75c
        else:
Packit Service 21c75c
            trans = None
Packit Service 21c75c
Packit Service 21c75c
        if trans:
Packit Service cfdb81
            # the post transaction summary is already written to log during
Packit Service cfdb81
            # Base.do_transaction() so here only print the messages to the
Packit Service cfdb81
            # user arranged in columns
Packit Service cfdb81
            print()
Packit Service cfdb81
            print('\n'.join(self.output.post_transaction_output(trans)))
Packit Service cfdb81
            print()
Packit Service 21c75c
            for tsi in trans:
Packit Service 21c75c
                if tsi.state == libdnf.transaction.TransactionItemState_ERROR:
Packit Service 21c75c
                    raise dnf.exceptions.Error(_('Transaction failed'))
Packit Service 21c75c
Packit Service 21c75c
        return tid
Packit Service 21c75c
Packit Service 21c75c
    def gpgsigcheck(self, pkgs):
Packit Service 21c75c
        """Perform GPG signature verification on the given packages,
Packit Service 21c75c
        installing keys if possible.
Packit Service 21c75c
Packit Service 21c75c
        :param pkgs: a list of package objects to verify the GPG
Packit Service 21c75c
           signatures of
Packit Service 21c75c
        :raises: Will raise :class:`Error` if there's a problem
Packit Service 21c75c
        """
Packit Service 21c75c
        error_messages = []
Packit Service 21c75c
        for po in pkgs:
Packit Service 21c75c
            result, errmsg = self._sig_check_pkg(po)
Packit Service 21c75c
Packit Service 21c75c
            if result == 0:
Packit Service 21c75c
                # Verified ok, or verify not req'd
Packit Service 21c75c
                continue
Packit Service 21c75c
Packit Service 21c75c
            elif result == 1:
Packit Service 21c75c
                ay = self.conf.assumeyes and not self.conf.assumeno
Packit Service 21c75c
                if (not sys.stdin or not sys.stdin.isatty()) and not ay:
Packit Service 21c75c
                    raise dnf.exceptions.Error(_('Refusing to automatically import keys when running ' \
Packit Service 21c75c
                            'unattended.\nUse "-y" to override.'))
Packit Service 21c75c
Packit Service 21c75c
                # the callback here expects to be able to take options which
Packit Service 21c75c
                # userconfirm really doesn't... so fake it
Packit Service 21c75c
                fn = lambda x, y, z: self.output.userconfirm()
Packit Service 21c75c
                try:
Packit Service 21c75c
                    self._get_key_for_package(po, fn)
Packit Service 21c75c
                except dnf.exceptions.Error as e:
Packit Service 21c75c
                    error_messages.append(str(e))
Packit Service 21c75c
Packit Service 21c75c
            else:
Packit Service 21c75c
                # Fatal error
Packit Service 21c75c
                error_messages.append(errmsg)
Packit Service 21c75c
Packit Service 21c75c
        if error_messages:
Packit Service 21c75c
            for msg in error_messages:
Packit Service 21c75c
                logger.critical(msg)
Packit Service 21c75c
            raise dnf.exceptions.Error(_("GPG check FAILED"))
Packit Service 21c75c
Packit Service 21c75c
    def latest_changelogs(self, package):
Packit Service 21c75c
        """Return list of changelogs for package newer then installed version"""
Packit Service 21c75c
        newest = None
Packit Service 21c75c
        # find the date of the newest changelog for installed version of package
Packit Service 21c75c
        # stored in rpmdb
Packit Service 21c75c
        for mi in self._rpmconn.readonly_ts.dbMatch('name', package.name):
Packit Service 21c75c
            changelogtimes = mi[rpm.RPMTAG_CHANGELOGTIME]
Packit Service 21c75c
            if changelogtimes:
Packit Service 21c75c
                newest = datetime.date.fromtimestamp(changelogtimes[0])
Packit Service 21c75c
                break
Packit Service 21c75c
        chlogs = [chlog for chlog in package.changelogs
Packit Service 21c75c
                  if newest is None or chlog['timestamp'] > newest]
Packit Service 21c75c
        return chlogs
Packit Service 21c75c
Packit Service 21c75c
    def format_changelog(self, changelog):
Packit Service 21c75c
        """Return changelog formatted as in spec file"""
Packit Service 21c75c
        chlog_str = '* %s %s\n%s\n' % (
Packit Service 21c75c
            changelog['timestamp'].strftime("%a %b %d %X %Y"),
Packit Service 21c75c
            dnf.i18n.ucd(changelog['author']),
Packit Service 21c75c
            dnf.i18n.ucd(changelog['text']))
Packit Service 21c75c
        return chlog_str
Packit Service 21c75c
Packit Service 21c75c
    def print_changelogs(self, packages):
Packit Service 21c75c
        # group packages by src.rpm to avoid showing duplicate changelogs
Packit Service 21c75c
        bysrpm = dict()
Packit Service 21c75c
        for p in packages:
Packit Service 21c75c
            # there are packages without source_name, use name then.
Packit Service 21c75c
            bysrpm.setdefault(p.source_name or p.name, []).append(p)
Packit Service 21c75c
        for source_name in sorted(bysrpm.keys()):
Packit Service 21c75c
            bin_packages = bysrpm[source_name]
Packit Service 21c75c
            print(_("Changelogs for {}").format(', '.join([str(pkg) for pkg in bin_packages])))
Packit Service 21c75c
            for chl in self.latest_changelogs(bin_packages[0]):
Packit Service 21c75c
                print(self.format_changelog(chl))
Packit Service 21c75c
Packit Service 21c75c
    def check_updates(self, patterns=(), reponame=None, print_=True, changelogs=False):
Packit Service 21c75c
        """Check updates matching given *patterns* in selected repository."""
Packit Service 21c75c
        ypl = self.returnPkgLists('upgrades', patterns, reponame=reponame)
Packit Service 21c75c
        if self.conf.obsoletes or self.conf.verbose:
Packit Service 21c75c
            typl = self.returnPkgLists('obsoletes', patterns, reponame=reponame)
Packit Service 21c75c
            ypl.obsoletes = typl.obsoletes
Packit Service 21c75c
            ypl.obsoletesTuples = typl.obsoletesTuples
Packit Service 21c75c
Packit Service 21c75c
        if print_:
Packit Service 21c75c
            columns = _list_cmd_calc_columns(self.output, ypl)
Packit Service 21c75c
            if len(ypl.updates) > 0:
Packit Service 21c75c
                local_pkgs = {}
Packit Service 21c75c
                highlight = self.output.term.MODE['bold']
Packit Service 21c75c
                if highlight:
Packit Service 21c75c
                    # Do the local/remote split we get in "yum updates"
Packit Service 21c75c
                    for po in sorted(ypl.updates):
Packit Service 21c75c
                        local = po.localPkg()
Packit Service 21c75c
                        if os.path.exists(local) and po.verifyLocalPkg():
Packit Service 21c75c
                            local_pkgs[(po.name, po.arch)] = po
Packit Service 21c75c
Packit Service 21c75c
                cul = self.conf.color_update_local
Packit Service 21c75c
                cur = self.conf.color_update_remote
Packit Service 21c75c
                self.output.listPkgs(ypl.updates, '', outputType='list',
Packit Service 21c75c
                              highlight_na=local_pkgs, columns=columns,
Packit Service 21c75c
                              highlight_modes={'=' : cul, 'not in' : cur})
Packit Service 21c75c
                if changelogs:
Packit Service 21c75c
                    self.print_changelogs(ypl.updates)
Packit Service 21c75c
Packit Service 21c75c
            if len(ypl.obsoletes) > 0:
Packit Service 21c75c
                print(_('Obsoleting Packages'))
Packit Service 21c75c
                # The tuple is (newPkg, oldPkg) ... so sort by new
Packit Service 21c75c
                for obtup in sorted(ypl.obsoletesTuples,
Packit Service 21c75c
                                    key=operator.itemgetter(0)):
Packit Service 21c75c
                    self.output.updatesObsoletesList(obtup, 'obsoletes',
Packit Service 21c75c
                                                     columns=columns)
Packit Service 21c75c
Packit Service 21c75c
        return ypl.updates or ypl.obsoletes
Packit Service 21c75c
Packit Service 21c75c
    def distro_sync_userlist(self, userlist):
Packit Service 21c75c
        """ Upgrade or downgrade packages to match the latest versions available
Packit Service 21c75c
            in the enabled repositories.
Packit Service 21c75c
Packit Service 21c75c
            :return: (exit_code, [ errors ])
Packit Service 21c75c
Packit Service 21c75c
            exit_code is::
Packit Service 21c75c
                0 = we're done, exit
Packit Service 21c75c
                1 = we've errored, exit with error string
Packit Service 21c75c
                2 = we've got work yet to do, onto the next stage
Packit Service 21c75c
        """
Packit Service 21c75c
        oldcount = self._goal.req_length()
Packit Service 21c75c
        if len(userlist) == 0:
Packit Service 21c75c
            self.distro_sync()
Packit Service 21c75c
        else:
Packit Service 21c75c
            for pkg_spec in userlist:
Packit Service 21c75c
                self.distro_sync(pkg_spec)
Packit Service 21c75c
Packit Service 21c75c
        cnt = self._goal.req_length() - oldcount
Packit Service 21c75c
        if cnt <= 0 and not self._goal.req_has_distupgrade_all():
Packit Service 21c75c
            msg = _('No packages marked for distribution synchronization.')
Packit Service 21c75c
            raise dnf.exceptions.Error(msg)
Packit Service 21c75c
Packit Service 21c75c
    def downgradePkgs(self, specs=[], file_pkgs=[], strict=False):
Packit Service 21c75c
        """Attempt to take the user specified list of packages or
Packit Service 21c75c
        wildcards and downgrade them. If a complete version number is
Packit Service 21c75c
        specified, attempt to downgrade them to the specified version
Packit Service 21c75c
Packit Service 21c75c
        :param specs: a list of names or wildcards specifying packages to downgrade
Packit Service 21c75c
        :param file_pkgs: a list of pkg objects from local files
Packit Service 21c75c
        """
Packit Service 21c75c
Packit Service 21c75c
        result = False
Packit Service 21c75c
        for pkg in file_pkgs:
Packit Service 21c75c
            try:
Packit Service 21c75c
                self.package_downgrade(pkg, strict=strict)
Packit Service 21c75c
                result = True
Packit Service 21c75c
            except dnf.exceptions.MarkingError as e:
Packit Service 21c75c
                logger.info(_('No match for argument: %s'),
Packit Service 21c75c
                            self.output.term.bold(pkg.location))
Packit Service 21c75c
Packit Service 21c75c
        for arg in specs:
Packit Service 21c75c
            try:
Packit Service 21c75c
                self.downgrade_to(arg, strict=strict)
Packit Service 21c75c
                result = True
Packit Service 21c75c
            except dnf.exceptions.PackageNotFoundError as err:
Packit Service 21c75c
                msg = _('No package %s available.')
Packit Service 21c75c
                logger.info(msg, self.output.term.bold(arg))
Packit Service 21c75c
            except dnf.exceptions.PackagesNotInstalledError as err:
Packit Service 21c75c
                logger.info(_('Packages for argument %s available, but not installed.'),
Packit Service 21c75c
                            self.output.term.bold(err.pkg_spec))
Packit Service 21c75c
            except dnf.exceptions.MarkingError:
Packit Service 21c75c
                assert False
Packit Service 21c75c
Packit Service 21c75c
        if not result:
Packit Service 21c75c
            raise dnf.exceptions.Error(_('No packages marked for downgrade.'))
Packit Service 21c75c
Packit Service 21c75c
    def output_packages(self, basecmd, pkgnarrow='all', patterns=(), reponame=None):
Packit Service 21c75c
        """Output selection *pkgnarrow* of packages matching *patterns* and *repoid*."""
Packit Service 21c75c
        try:
Packit Service 21c75c
            highlight = self.output.term.MODE['bold']
Packit Service 21c75c
            ypl = self.returnPkgLists(
Packit Service 21c75c
                pkgnarrow, patterns, installed_available=highlight, reponame=reponame)
Packit Service 21c75c
        except dnf.exceptions.Error as e:
Packit Service 21c75c
            return 1, [str(e)]
Packit Service 21c75c
        else:
Packit Service 21c75c
            update_pkgs = {}
Packit Service 21c75c
            inst_pkgs = {}
Packit Service 21c75c
            local_pkgs = {}
Packit Service 21c75c
Packit Service 21c75c
            columns = None
Packit Service 21c75c
            if basecmd == 'list':
Packit Service 21c75c
                # Dynamically size the columns
Packit Service 21c75c
                columns = _list_cmd_calc_columns(self.output, ypl)
Packit Service 21c75c
Packit Service 21c75c
            if highlight and ypl.installed:
Packit Service 21c75c
                #  If we have installed and available lists, then do the
Packit Service 21c75c
                # highlighting for the installed packages so you can see what's
Packit Service 21c75c
                # available to update, an extra, or newer than what we have.
Packit Service 21c75c
                for pkg in (ypl.hidden_available +
Packit Service 21c75c
                            ypl.reinstall_available +
Packit Service 21c75c
                            ypl.old_available):
Packit Service 21c75c
                    key = (pkg.name, pkg.arch)
Packit Service 21c75c
                    if key not in update_pkgs or pkg > update_pkgs[key]:
Packit Service 21c75c
                        update_pkgs[key] = pkg
Packit Service 21c75c
Packit Service 21c75c
            if highlight and ypl.available:
Packit Service 21c75c
                #  If we have installed and available lists, then do the
Packit Service 21c75c
                # highlighting for the available packages so you can see what's
Packit Service 21c75c
                # available to install vs. update vs. old.
Packit Service 21c75c
                for pkg in ypl.hidden_installed:
Packit Service 21c75c
                    key = (pkg.name, pkg.arch)
Packit Service 21c75c
                    if key not in inst_pkgs or pkg > inst_pkgs[key]:
Packit Service 21c75c
                        inst_pkgs[key] = pkg
Packit Service 21c75c
Packit Service 21c75c
            if highlight and ypl.updates:
Packit Service 21c75c
                # Do the local/remote split we get in "yum updates"
Packit Service 21c75c
                for po in sorted(ypl.updates):
Packit Service 21c75c
                    if po.reponame != hawkey.SYSTEM_REPO_NAME:
Packit Service 21c75c
                        local_pkgs[(po.name, po.arch)] = po
Packit Service 21c75c
Packit Service 21c75c
            # Output the packages:
Packit Service 21c75c
            clio = self.conf.color_list_installed_older
Packit Service 21c75c
            clin = self.conf.color_list_installed_newer
Packit Service 21c75c
            clir = self.conf.color_list_installed_reinstall
Packit Service 21c75c
            clie = self.conf.color_list_installed_extra
Packit Service 21c75c
            rip = self.output.listPkgs(ypl.installed, _('Installed Packages'), basecmd,
Packit Service 21c75c
                                highlight_na=update_pkgs, columns=columns,
Packit Service 21c75c
                                highlight_modes={'>' : clio, '<' : clin,
Packit Service 21c75c
                                                 '=' : clir, 'not in' : clie})
Packit Service 21c75c
            clau = self.conf.color_list_available_upgrade
Packit Service 21c75c
            clad = self.conf.color_list_available_downgrade
Packit Service 21c75c
            clar = self.conf.color_list_available_reinstall
Packit Service 21c75c
            clai = self.conf.color_list_available_install
Packit Service 21c75c
            rap = self.output.listPkgs(ypl.available, _('Available Packages'), basecmd,
Packit Service 21c75c
                                highlight_na=inst_pkgs, columns=columns,
Packit Service 21c75c
                                highlight_modes={'<' : clau, '>' : clad,
Packit Service 21c75c
                                                 '=' : clar, 'not in' : clai})
Packit Service 21c75c
            raep = self.output.listPkgs(ypl.autoremove, _('Autoremove Packages'),
Packit Service 21c75c
                                basecmd, columns=columns)
Packit Service 21c75c
            rep = self.output.listPkgs(ypl.extras, _('Extra Packages'), basecmd,
Packit Service 21c75c
                                columns=columns)
Packit Service 21c75c
            cul = self.conf.color_update_local
Packit Service 21c75c
            cur = self.conf.color_update_remote
Packit Service 21c75c
            rup = self.output.listPkgs(ypl.updates, _('Available Upgrades'), basecmd,
Packit Service 21c75c
                                highlight_na=local_pkgs, columns=columns,
Packit Service 21c75c
                                highlight_modes={'=' : cul, 'not in' : cur})
Packit Service 21c75c
Packit Service 21c75c
            # XXX put this into the ListCommand at some point
Packit Service 21c75c
            if len(ypl.obsoletes) > 0 and basecmd == 'list':
Packit Service 21c75c
            # if we've looked up obsolete lists and it's a list request
Packit Service 2bb387
                rop = len(ypl.obsoletes)
Packit Service 21c75c
                print(_('Obsoleting Packages'))
Packit Service 21c75c
                for obtup in sorted(ypl.obsoletesTuples,
Packit Service 21c75c
                                    key=operator.itemgetter(0)):
Packit Service 21c75c
                    self.output.updatesObsoletesList(obtup, 'obsoletes',
Packit Service 21c75c
                                                     columns=columns)
Packit Service 21c75c
            else:
Packit Service 21c75c
                rop = self.output.listPkgs(ypl.obsoletes, _('Obsoleting Packages'),
Packit Service 21c75c
                                    basecmd, columns=columns)
Packit Service 21c75c
            rrap = self.output.listPkgs(ypl.recent, _('Recently Added Packages'),
Packit Service 21c75c
                                 basecmd, columns=columns)
Packit Service 21c75c
            if len(patterns) and \
Packit Service 2bb387
                    rrap == 0 and rop == 0 and rup == 0 and rep == 0 and rap == 0 and raep == 0 and rip == 0:
Packit Service 21c75c
                raise dnf.exceptions.Error(_('No matching Packages to list'))
Packit Service 21c75c
Packit Service 21c75c
    def returnPkgLists(self, pkgnarrow='all', patterns=None,
Packit Service 21c75c
                       installed_available=False, reponame=None):
Packit Service 21c75c
        """Return a :class:`dnf.yum.misc.GenericHolder` object containing
Packit Service 21c75c
        lists of package objects that match the given names or wildcards.
Packit Service 21c75c
Packit Service 21c75c
        :param pkgnarrow: a string specifying which types of packages
Packit Service 21c75c
           lists to produce, such as updates, installed, available, etc.
Packit Service 21c75c
        :param patterns: a list of names or wildcards specifying
Packit Service 21c75c
           packages to list
Packit Service 21c75c
        :param installed_available: whether the available package list
Packit Service 21c75c
           is present as .hidden_available when doing all, available,
Packit Service 21c75c
           or installed
Packit Service 21c75c
        :param reponame: limit packages list to the given repository
Packit Service 21c75c
Packit Service 21c75c
        :return: a :class:`dnf.yum.misc.GenericHolder` instance with the
Packit Service 21c75c
           following lists defined::
Packit Service 21c75c
Packit Service 21c75c
             available = list of packageObjects
Packit Service 21c75c
             installed = list of packageObjects
Packit Service 21c75c
             upgrades = tuples of packageObjects (updating, installed)
Packit Service 21c75c
             extras = list of packageObjects
Packit Service 21c75c
             obsoletes = tuples of packageObjects (obsoleting, installed)
Packit Service 21c75c
             recent = list of packageObjects
Packit Service 21c75c
        """
Packit Service 21c75c
Packit Service 21c75c
        done_hidden_available = False
Packit Service 21c75c
        done_hidden_installed = False
Packit Service 21c75c
        if installed_available and pkgnarrow == 'installed':
Packit Service 21c75c
            done_hidden_available = True
Packit Service 21c75c
            pkgnarrow = 'all'
Packit Service 21c75c
        elif installed_available and pkgnarrow == 'available':
Packit Service 21c75c
            done_hidden_installed = True
Packit Service 21c75c
            pkgnarrow = 'all'
Packit Service 21c75c
Packit Service 21c75c
        ypl = self._do_package_lists(
Packit Service 21c75c
            pkgnarrow, patterns, ignore_case=True, reponame=reponame)
Packit Service 21c75c
        if self.conf.showdupesfromrepos:
Packit Service 21c75c
            for pkg in ypl.reinstall_available:
Packit Service 21c75c
                if not pkg.installed and not done_hidden_available:
Packit Service 21c75c
                    ypl.available.append(pkg)
Packit Service 21c75c
Packit Service 21c75c
        if installed_available:
Packit Service 21c75c
            ypl.hidden_available = ypl.available
Packit Service 21c75c
            ypl.hidden_installed = ypl.installed
Packit Service 21c75c
        if done_hidden_available:
Packit Service 21c75c
            ypl.available = []
Packit Service 21c75c
        if done_hidden_installed:
Packit Service 21c75c
            ypl.installed = []
Packit Service 21c75c
        return ypl
Packit Service 21c75c
Packit Service 21c75c
    def provides(self, args):
Packit Service 21c75c
        """Print out a list of packages that provide the given file or
Packit Service 21c75c
        feature.  This a cli wrapper to the provides methods in the
Packit Service 21c75c
        rpmdb and pkgsack.
Packit Service 21c75c
Packit Service 21c75c
        :param args: the name of a file or feature to search for
Packit Service 21c75c
        :return: (exit_code, [ errors ])
Packit Service 21c75c
Packit Service 21c75c
        exit_code is::
Packit Service 21c75c
Packit Service 21c75c
            0 = we're done, exit
Packit Service 21c75c
            1 = we've errored, exit with error string
Packit Service 21c75c
            2 = we've got work yet to do, onto the next stage
Packit Service 21c75c
        """
Packit Service 21c75c
        # always in showdups mode
Packit Service 21c75c
        old_sdup = self.conf.showdupesfromrepos
Packit Service 21c75c
        self.conf.showdupesfromrepos = True
Packit Service 21c75c
Packit Service 21c75c
        matches = []
Packit Service 21c75c
        used_search_strings = []
Packit Service 21c75c
        for spec in args:
Packit Service 21c75c
            query, used_search_string = super(BaseCli, self).provides(spec)
Packit Service 21c75c
            matches.extend(query)
Packit Service 21c75c
            used_search_strings.extend(used_search_string)
Packit Service 21c75c
        for pkg in sorted(matches):
Packit Service 21c75c
            self.output.matchcallback_verbose(pkg, used_search_strings, args)
Packit Service 21c75c
        self.conf.showdupesfromrepos = old_sdup
Packit Service 21c75c
Packit Service 21c75c
        if not matches:
Packit Service 21c75c
            raise dnf.exceptions.Error(_('No Matches found'))
Packit Service 21c75c
Packit Service 21c75c
    def _promptWanted(self):
Packit Service 21c75c
        # shortcut for the always-off/always-on options
Packit Service 21c75c
        if self.conf.assumeyes and not self.conf.assumeno:
Packit Service 21c75c
            return False
Packit Service 21c75c
        return True
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
class Cli(object):
Packit Service 21c75c
    def __init__(self, base):
Packit Service 21c75c
        self.base = base
Packit Service 21c75c
        self.cli_commands = {}
Packit Service 21c75c
        self.command = None
Packit Service 21c75c
        self.demands = dnf.cli.demand.DemandSheet()  # :api
Packit Service 21c75c
Packit Service 21c75c
        self.register_command(dnf.cli.commands.alias.AliasCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.autoremove.AutoremoveCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.check.CheckCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.clean.CleanCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.distrosync.DistroSyncCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.deplist.DeplistCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.downgrade.DowngradeCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.group.GroupCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.history.HistoryCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.install.InstallCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.makecache.MakeCacheCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.mark.MarkCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.module.ModuleCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.reinstall.ReinstallCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.remove.RemoveCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.repolist.RepoListCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.repoquery.RepoQueryCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.search.SearchCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.shell.ShellCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.swap.SwapCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.updateinfo.UpdateInfoCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.upgrade.UpgradeCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.upgrademinimal.UpgradeMinimalCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.InfoCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.ListCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.ProvidesCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.CheckUpdateCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.RepoPkgsCommand)
Packit Service 21c75c
        self.register_command(dnf.cli.commands.HelpCommand)
Packit Service 21c75c
Packit Service 21c75c
    def _configure_repos(self, opts):
Packit Service 21c75c
        self.base.read_all_repos(opts)
Packit Service 21c75c
        if opts.repofrompath:
Packit Service 21c75c
            for label, path in opts.repofrompath.items():
Packit Service 21c75c
                this_repo = self.base.repos.add_new_repo(label, self.base.conf, baseurl=[path])
Packit Service 21c75c
                this_repo._configure_from_options(opts)
Packit Service 21c75c
                # do not let this repo to be disabled
Packit Service 21c75c
                opts.repos_ed.append((label, "enable"))
Packit Service 21c75c
Packit Service 21c75c
        if opts.repo:
Packit Service 21c75c
            opts.repos_ed.insert(0, ("*", "disable"))
Packit Service 21c75c
            opts.repos_ed.extend([(r, "enable") for r in opts.repo])
Packit Service 21c75c
Packit Service 21c75c
        notmatch = set()
Packit Service 21c75c
Packit Service 21c75c
        # Process repo enables and disables in order
Packit Service 21c75c
        try:
Packit Service 21c75c
            for (repo, operation) in opts.repos_ed:
Packit Service 21c75c
                repolist = self.base.repos.get_matching(repo)
Packit Service 21c75c
                if not repolist:
Packit Service 21c75c
                    if self.base.conf.strict and operation == "enable":
Packit Service 21c75c
                        msg = _("Unknown repo: '%s'")
Packit Service 21c75c
                        raise dnf.exceptions.RepoError(msg % repo)
Packit Service 21c75c
                    notmatch.add(repo)
Packit Service 21c75c
Packit Service 21c75c
                if operation == "enable":
Packit Service 21c75c
                    repolist.enable()
Packit Service 21c75c
                else:
Packit Service 21c75c
                    repolist.disable()
Packit Service 21c75c
        except dnf.exceptions.ConfigError as e:
Packit Service 21c75c
            logger.critical(e)
Packit Service 21c75c
            self.optparser.print_help()
Packit Service 21c75c
            sys.exit(1)
Packit Service 21c75c
Packit Service 21c75c
        for repo in notmatch:
Packit Service 21c75c
            logger.warning(_("No repository match: %s"), repo)
Packit Service 21c75c
Packit Service 21c75c
        expired_repos = self.base._repo_persistor.get_expired_repos()
Packit Service 21c75c
        if expired_repos is None:
Packit Service 21c75c
            expired_repos = self.base.repos.keys()
Packit Service 21c75c
        for rid in expired_repos:
Packit Service 21c75c
            repo = self.base.repos.get(rid)
Packit Service 21c75c
            if repo:
Packit Service 21c75c
                repo._repo.expire()
Packit Service 21c75c
Packit Service 21c75c
        # setup the progress bars/callbacks
Packit Service 21c75c
        (bar, self.base._ds_callback) = self.base.output.setup_progress_callbacks()
Packit Service 21c75c
        self.base.repos.all().set_progress_bar(bar)
Packit Service 21c75c
        key_import = output.CliKeyImport(self.base, self.base.output)
Packit Service 21c75c
        self.base.repos.all()._set_key_import(key_import)
Packit Service 21c75c
Packit Service 21c75c
    def _log_essentials(self):
Packit Service 21c75c
        logger.debug('{prog} version: %s'.format(prog=dnf.util.MAIN_PROG_UPPER),
Packit Service 21c75c
                     dnf.const.VERSION)
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG,
Packit Service 21c75c
                        'Command: %s', self.cmdstring)
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG,
Packit Service 21c75c
                        'Installroot: %s', self.base.conf.installroot)
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, 'Releasever: %s',
Packit Service 21c75c
                        self.base.conf.releasever)
Packit Service 21c75c
        logger.debug("cachedir: %s", self.base.conf.cachedir)
Packit Service 21c75c
Packit Service 21c75c
    def _process_demands(self):
Packit Service 21c75c
        demands = self.demands
Packit Service 21c75c
        repos = self.base.repos
Packit Service 21c75c
Packit Service 21c75c
        if demands.root_user:
Packit Service 21c75c
            if not dnf.util.am_i_root():
Packit Service 21c75c
                raise dnf.exceptions.Error(
Packit Service 21c75c
                    _('This command has to be run with superuser privileges '
Packit Service 21c75c
                        '(under the root user on most systems).'))
Packit Service 21c75c
Packit Service 21c75c
        if demands.changelogs:
Packit Service 21c75c
            for repo in repos.iter_enabled():
Packit Service 21c75c
                repo.load_metadata_other = True
Packit Service 21c75c
Packit Service 21c75c
        if demands.cacheonly or self.base.conf.cacheonly:
Packit Service 21c75c
            self.base.conf.cacheonly = True
Packit Service 21c75c
            for repo in repos.values():
Packit Service 21c75c
                repo._repo.setSyncStrategy(dnf.repo.SYNC_ONLY_CACHE)
Packit Service 21c75c
        else:
Packit Service 21c75c
            if demands.freshest_metadata:
Packit Service 21c75c
                for repo in repos.iter_enabled():
Packit Service 21c75c
                    repo._repo.expire()
Packit Service 21c75c
            elif not demands.fresh_metadata:
Packit Service 21c75c
                for repo in repos.values():
Packit Service 21c75c
                    repo._repo.setSyncStrategy(dnf.repo.SYNC_LAZY)
Packit Service 21c75c
Packit Service 21c75c
        if demands.sack_activation:
Packit Service 21c75c
            self.base.fill_sack(
Packit Service 21c75c
                load_system_repo='auto' if self.demands.load_system_repo else False,
Packit Service 21c75c
                load_available_repos=self.demands.available_repos)
Packit Service 21c75c
Packit Service 21c75c
    def _parse_commands(self, opts, args):
Packit Service 21c75c
        """Check that the requested CLI command exists."""
Packit Service 21c75c
Packit Service 21c75c
        basecmd = opts.command
Packit Service 21c75c
        command_cls = self.cli_commands.get(basecmd)
Packit Service 21c75c
        if command_cls is None:
Packit Service 21c75c
            logger.critical(_('No such command: %s. Please use %s --help'),
Packit Service 21c75c
                            basecmd, sys.argv[0])
Packit Service 21c75c
            if self.base.conf.plugins:
Packit Service 21c75c
                logger.critical(_("It could be a {PROG} plugin command, "
Packit Service 21c75c
                                  "try: \"{prog} install 'dnf-command(%s)'\"").format(
Packit Service 21c75c
                    prog=dnf.util.MAIN_PROG, PROG=dnf.util.MAIN_PROG_UPPER), basecmd)
Packit Service 21c75c
            else:
Packit Service 21c75c
                logger.critical(_("It could be a {prog} plugin command, "
Packit Service 21c75c
                                  "but loading of plugins is currently disabled.").format(
Packit Service 21c75c
                    prog=dnf.util.MAIN_PROG_UPPER))
Packit Service 21c75c
            raise CliError
Packit Service 21c75c
        self.command = command_cls(self)
Packit Service 21c75c
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, 'Base command: %s', basecmd)
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, 'Extra commands: %s', args)
Packit Service 21c75c
Packit Service 21c75c
    def configure(self, args, option_parser=None):
Packit Service 21c75c
        """Parse command line arguments, and set up :attr:`self.base.conf` and
Packit Service 21c75c
        :attr:`self.cmds`, as well as logger objects in base instance.
Packit Service 21c75c
Packit Service 21c75c
        :param args: a list of command line arguments
Packit Service 21c75c
        :param option_parser: a class for parsing cli options
Packit Service 21c75c
        """
Packit Service 21c75c
        aliases = dnf.cli.aliases.Aliases()
Packit Service 21c75c
        args = aliases.resolve(args)
Packit Service 21c75c
Packit Service 21c75c
        self.optparser = dnf.cli.option_parser.OptionParser() \
Packit Service 21c75c
            if option_parser is None else option_parser
Packit Service 21c75c
        opts = self.optparser.parse_main_args(args)
Packit Service 21c75c
Packit Service 21c75c
        # Just print out the version if that's what the user wanted
Packit Service 21c75c
        if opts.version:
Packit Service 21c75c
            print(dnf.const.VERSION)
Packit Service 21c75c
            print_versions(self.base.conf.history_record_packages, self.base,
Packit Service 21c75c
                           self.base.output)
Packit Service 21c75c
            sys.exit(0)
Packit Service 21c75c
Packit Service 21c75c
        if opts.quiet:
Packit Service 21c75c
            opts.debuglevel = 0
Packit Service 21c75c
            opts.errorlevel = 2
Packit Service 21c75c
        if opts.verbose:
Packit Service 21c75c
            opts.debuglevel = opts.errorlevel = dnf.const.VERBOSE_LEVEL
Packit Service 21c75c
Packit Service 21c75c
        # Read up configuration options and initialize plugins
Packit Service 21c75c
        try:
Packit Service 21c75c
            if opts.cacheonly:
Packit Service 21c75c
                self.base.conf._set_value("cachedir", self.base.conf.system_cachedir,
Packit Service 21c75c
                                          dnf.conf.PRIO_DEFAULT)
Packit Service 21c75c
                self.demands.cacheonly = True
Packit Service 21c75c
            self.base.conf._configure_from_options(opts)
Packit Service 21c75c
            self._read_conf_file(opts.releasever)
Packit Service 21c75c
            if 'arch' in opts:
Packit Service 21c75c
                self.base.conf.arch = opts.arch
Packit Service 21c75c
            self.base.conf._adjust_conf_options()
Packit Service 21c75c
        except (dnf.exceptions.ConfigError, ValueError) as e:
Packit Service 21c75c
            logger.critical(_('Config error: %s'), e)
Packit Service 21c75c
            sys.exit(1)
Packit Service 21c75c
        except IOError as e:
Packit Service 21c75c
            e = '%s: %s' % (ucd(str(e)), repr(e.filename))
Packit Service 21c75c
            logger.critical(_('Config error: %s'), e)
Packit Service 21c75c
            sys.exit(1)
Packit Service 21c75c
        if opts.destdir is not None:
Packit Service 21c75c
            self.base.conf.destdir = opts.destdir
Packit Service 21c75c
            if not self.base.conf.downloadonly and opts.command not in (
Packit Service 21c75c
                    'download', 'system-upgrade', 'reposync'):
Packit Service 21c75c
                logger.critical(_('--destdir or --downloaddir must be used with --downloadonly '
Packit Service 21c75c
                                  'or download or system-upgrade command.')
Packit Service 21c75c
                )
Packit Service 21c75c
                sys.exit(1)
Packit Service 21c75c
        if (opts.set_enabled or opts.set_disabled) and opts.command != 'config-manager':
Packit Service 21c75c
            logger.critical(
Packit Service 21c75c
                _('--enable, --set-enabled and --disable, --set-disabled '
Packit Service 21c75c
                  'must be used with config-manager command.'))
Packit Service 21c75c
            sys.exit(1)
Packit Service 21c75c
Packit Service 21c75c
        if opts.sleeptime is not None:
Packit Service 21c75c
            time.sleep(random.randrange(opts.sleeptime * 60))
Packit Service 21c75c
Packit Service 21c75c
        # store the main commands & summaries, before plugins are loaded
Packit Service 21c75c
        self.optparser.add_commands(self.cli_commands, 'main')
Packit Service 21c75c
        # store the plugin commands & summaries
Packit Service 21c75c
        self.base.init_plugins(opts.disableplugin, opts.enableplugin, self)
Packit Service 21c75c
        self.optparser.add_commands(self.cli_commands,'plugin')
Packit Service 21c75c
Packit Service 21c75c
        # show help if no command specified
Packit Service 21c75c
        # this is done here, because we first have the full
Packit Service 21c75c
        # usage info after the plugins are loaded.
Packit Service 21c75c
        if not opts.command:
Packit Service 21c75c
            self.optparser.print_help()
Packit Service 21c75c
            sys.exit(0)
Packit Service 21c75c
Packit Service 21c75c
        # save our original args out
Packit Service 21c75c
        self.base.args = args
Packit Service 21c75c
        # save out as a nice command string
Packit Service 21c75c
        self.cmdstring = self.optparser.prog + ' '
Packit Service 21c75c
        for arg in self.base.args:
Packit Service 21c75c
            self.cmdstring += '%s ' % arg
Packit Service 21c75c
Packit Service 21c75c
        self._log_essentials()
Packit Service 21c75c
        try:
Packit Service 21c75c
            self._parse_commands(opts, args)
Packit Service 21c75c
        except CliError:
Packit Service 21c75c
            sys.exit(1)
Packit Service 21c75c
Packit Service 21c75c
        # show help for dnf <command> --help / --help-cmd
Packit Service 21c75c
        if opts.help:
Packit Service 21c75c
            self.optparser.print_help(self.command)
Packit Service 21c75c
            sys.exit(0)
Packit Service 21c75c
Packit Service 21c75c
        opts = self.optparser.parse_command_args(self.command, args)
Packit Service 21c75c
Packit Service 21c75c
        if opts.allowerasing:
Packit Service 21c75c
            self.demands.allow_erasing = opts.allowerasing
Packit Service 21c75c
            self.base._allow_erasing = True
Packit Service 21c75c
        if opts.freshest_metadata:
Packit Service 21c75c
            self.demands.freshest_metadata = opts.freshest_metadata
Packit Service 21c75c
        if opts.debugsolver:
Packit Service 21c75c
            self.base.conf.debug_solver = True
Packit Service 21c75c
        if opts.obsoletes:
Packit Service 21c75c
            self.base.conf.obsoletes = True
Packit Service 21c75c
        self.command.pre_configure()
Packit Service 21c75c
        self.base.pre_configure_plugins()
Packit Service 21c75c
Packit Service 21c75c
        # with cachedir in place we can configure stuff depending on it:
Packit Service 21c75c
        self.base._activate_persistor()
Packit Service 21c75c
Packit Service 21c75c
        self._configure_repos(opts)
Packit Service 21c75c
Packit Service 21c75c
        self.base.configure_plugins()
Packit Service 21c75c
Packit Service 8a4ae5
        self.base.conf._configure_from_options(opts)
Packit Service 8a4ae5
Packit Service 21c75c
        self.command.configure()
Packit Service 21c75c
Packit Service 21c75c
        if self.base.conf.destdir:
Packit Service 21c75c
            dnf.util.ensure_dir(self.base.conf.destdir)
Packit Service 21c75c
            self.base.repos.all().pkgdir = self.base.conf.destdir
Packit Service 21c75c
Packit Service 21c75c
        if self.base.conf.color != 'auto':
Packit Service 21c75c
            self.base.output.term.reinit(color=self.base.conf.color)
Packit Service 21c75c
Packit Service 21c75c
        if rpm.expandMacro('%_pkgverify_level') in ('signature', 'all'):
Packit Service 21c75c
            forcing = False
Packit Service 21c75c
            for repo in self.base.repos.iter_enabled():
Packit Service 21c75c
                if repo.gpgcheck:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                repo.gpgcheck = True
Packit Service 21c75c
                forcing = True
Packit Service 21c75c
            if not self.base.conf.localpkg_gpgcheck:
Packit Service 21c75c
                self.base.conf.localpkg_gpgcheck = True
Packit Service 21c75c
                forcing = True
Packit Service 21c75c
            if forcing:
Packit Service 21c75c
                logger.warning(
Packit Service 21c75c
                    _("Warning: Enforcing GPG signature check globally "
Packit Service 21c75c
                      "as per active RPM security policy (see 'gpgcheck' in "
Packit Service 21c75c
                      "dnf.conf(5) for how to squelch this message)"
Packit Service 21c75c
                      )
Packit Service 21c75c
                )
Packit Service 21c75c
Packit Service 21c75c
    def _read_conf_file(self, releasever=None):
Packit Service 21c75c
        timer = dnf.logging.Timer('config')
Packit Service 21c75c
        conf = self.base.conf
Packit Service 21c75c
Packit Service 21c75c
        # replace remote config path with downloaded file
Packit Service 21c75c
        conf._check_remote_file('config_file_path')
Packit Service 21c75c
Packit Service 21c75c
        # search config file inside the installroot first
Packit Service 21c75c
        conf._search_inside_installroot('config_file_path')
Packit Service 21c75c
Packit Service 21c75c
        # check whether a config file is requested from command line and the file exists
Packit Service 21c75c
        filename = conf._get_value('config_file_path')
Packit Service 21c75c
        if (conf._get_priority('config_file_path') == dnf.conf.PRIO_COMMANDLINE) and \
Packit Service 21c75c
                not os.path.isfile(filename):
Packit Service 21c75c
            raise dnf.exceptions.ConfigError(_('Config file "{}" does not exist').format(filename))
Packit Service 21c75c
Packit Service 21c75c
        # read config
Packit Service 21c75c
        conf.read(priority=dnf.conf.PRIO_MAINCONFIG)
Packit Service 21c75c
Packit Service 21c75c
        # search reposdir file inside the installroot first
Packit Service 21c75c
        from_root = conf._search_inside_installroot('reposdir')
Packit Service 21c75c
        # Update vars from same root like repos were taken
Packit Service 21c75c
        if conf._get_priority('varsdir') == dnf.conf.PRIO_COMMANDLINE:
Packit Service 21c75c
            from_root = "/"
Packit Service 21c75c
        subst = conf.substitutions
Packit Service 21c75c
        subst.update_from_etc(from_root, varsdir=conf._get_value('varsdir'))
Packit Service 21c75c
        # cachedir, logs, releasever, and gpgkey are taken from or stored in installroot
Packit Service 21c75c
        if releasever is None and conf.releasever is None:
Packit Service 21c75c
            releasever = dnf.rpm.detect_releasever(conf.installroot)
Packit Service 21c75c
        elif releasever == '/':
Packit Service 21c75c
            releasever = dnf.rpm.detect_releasever(releasever)
Packit Service 21c75c
        if releasever is not None:
Packit Service 21c75c
            conf.releasever = releasever
Packit Service 21c75c
        if conf.releasever is None:
Packit Service 21c75c
            logger.warning(_("Unable to detect release version (use '--releasever' to specify "
Packit Service 21c75c
                             "release version)"))
Packit Service 21c75c
Packit Service 21c75c
        for opt in ('cachedir', 'logdir', 'persistdir'):
Packit Service 21c75c
            conf.prepend_installroot(opt)
Packit Service 21c75c
Packit Service 21c75c
        self.base._logging._setup_from_dnf_conf(conf)
Packit Service 21c75c
Packit Service 21c75c
        timer()
Packit Service 21c75c
        return conf
Packit Service 21c75c
Packit Service 21c75c
    def _populate_update_security_filter(self, opts, query, cmp_type='eq', all=None):
Packit Service 21c75c
        """
Packit Service 21c75c
Packit Service 21c75c
        :param opts:
Packit Service 21c75c
        :param query: base package set for filters
Packit Service 21c75c
        :param cmp_type: string like "eq", "gt", "gte", "lt", "lte"
Packit Service 21c75c
        :param all:
Packit Service 21c75c
        :return:
Packit Service 21c75c
        """
Packit Service 21c75c
        if (opts is None) and (all is None):
Packit Service 21c75c
            return
Packit Service 21c75c
        filters = []
Packit Service 21c75c
        if opts.bugfix or all:
Packit Service 21c75c
            key = {'advisory_type__' + cmp_type: 'bugfix'}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        if opts.enhancement or all:
Packit Service 21c75c
            key = {'advisory_type__' + cmp_type: 'enhancement'}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        if opts.newpackage or all:
Packit Service 21c75c
            key = {'advisory_type__' + cmp_type: 'newpackage'}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        if opts.security or all:
Packit Service 21c75c
            key = {'advisory_type__' + cmp_type: 'security'}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        if opts.advisory:
Packit Service 21c75c
            key = {'advisory__' + cmp_type: opts.advisory}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        if opts.bugzilla:
Packit Service 21c75c
            key = {'advisory_bug__' + cmp_type: opts.bugzilla}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        if opts.cves:
Packit Service 21c75c
            key = {'advisory_cve__' + cmp_type: opts.cves}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        if opts.severity:
Packit Service 21c75c
            key = {'advisory_severity__' + cmp_type: opts.severity}
Packit Service 21c75c
            filters.append(query.filter(**key))
Packit Service 21c75c
        self.base._update_security_filters = filters
Packit Service 21c75c
Packit Service 21c75c
    def redirect_logger(self, stdout=None, stderr=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """
Packit Service 21c75c
        Change minimal logger level for terminal output to stdout and stderr according to specific
Packit Service 21c75c
        command requirements
Packit Service 21c75c
        @param stdout: logging.INFO, logging.WARNING, ...
Packit Service 21c75c
        @param stderr:logging.INFO, logging.WARNING, ...
Packit Service 21c75c
        """
Packit Service 21c75c
        if stdout is not None:
Packit Service 21c75c
            self.base._logging.stdout_handler.setLevel(stdout)
Packit Service 21c75c
        if stderr is not None:
Packit Service 21c75c
            self.base._logging.stderr_handler.setLevel(stderr)
Packit Service 21c75c
Packit Service 21c75c
    def redirect_repo_progress(self, fo=sys.stderr):
Packit Service 21c75c
        progress = dnf.cli.progress.MultiFileProgressMeter(fo)
Packit Service 21c75c
        self.base.output.progress = progress
Packit Service 21c75c
        self.base.repos.all().set_progress_bar(progress)
Packit Service 21c75c
Packit Service 21c75c
    def _check_running_kernel(self):
Packit Service 21c75c
        kernel = self.base.sack.get_running_kernel()
Packit Service 21c75c
        if kernel is None:
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        q = self.base.sack.query().filterm(provides=kernel.name)
Packit Service 21c75c
        q = q.installed()
Packit Service 21c75c
        q.filterm(advisory_type='security')
Packit Service 21c75c
Packit Service 21c75c
        ikpkg = kernel
Packit Service 21c75c
        for pkg in q:
Packit Service 21c75c
            if pkg > ikpkg:
Packit Service 21c75c
                ikpkg = pkg
Packit Service 21c75c
Packit Service 21c75c
        if ikpkg > kernel:
Packit Service 21c75c
            print('Security: %s is an installed security update' % ikpkg)
Packit Service 21c75c
            print('Security: %s is the currently running version' % kernel)
Packit Service 21c75c
Packit Service 21c75c
    def _option_conflict(self, option_string_1, option_string_2):
Packit Service 21c75c
        print(self.optparser.print_usage())
Packit Service 21c75c
        raise dnf.exceptions.Error(_("argument {}: not allowed with argument {}".format(
Packit Service 21c75c
            option_string_1, option_string_2)))
Packit Service 21c75c
Packit Service 21c75c
    def register_command(self, command_cls):
Packit Service 21c75c
        """Register a Command. :api"""
Packit Service 21c75c
        for name in command_cls.aliases:
Packit Service 21c75c
            if name in self.cli_commands:
Packit Service 21c75c
                raise dnf.exceptions.ConfigError(_('Command "%s" already defined') % name)
Packit Service 21c75c
            self.cli_commands[name] = command_cls
Packit Service 21c75c
Packit Service 21c75c
    def run(self):
Packit Service 21c75c
        """Call the base command, and pass it the extended commands or
Packit Service 21c75c
           arguments.
Packit Service 21c75c
Packit Service 21c75c
        :return: (exit_code, [ errors ])
Packit Service 21c75c
Packit Service 21c75c
        exit_code is::
Packit Service 21c75c
Packit Service 21c75c
            0 = we're done, exit
Packit Service 21c75c
            1 = we've errored, exit with error string
Packit Service 21c75c
            2 = we've got work yet to do, onto the next stage
Packit Service 21c75c
        """
Packit Service 21c75c
        self._process_demands()
Packit Service 21c75c
Packit Service 21c75c
        # Reports about excludes and includes (but not from plugins)
Packit Service 21c75c
        if self.base.conf.excludepkgs:
Packit Service 21c75c
            logger.debug(
Packit Service 21c75c
                _('Excludes in dnf.conf: ') + ", ".join(sorted(set(self.base.conf.excludepkgs))))
Packit Service 21c75c
        if self.base.conf.includepkgs:
Packit Service 21c75c
            logger.debug(
Packit Service 21c75c
                _('Includes in dnf.conf: ') + ", ".join(sorted(set(self.base.conf.includepkgs))))
Packit Service 21c75c
        for repo in self.base.repos.iter_enabled():
Packit Service 21c75c
            if repo.excludepkgs:
Packit Service 21c75c
                logger.debug(_('Excludes in repo ') + repo.id + ": "
Packit Service 21c75c
                             + ", ".join(sorted(set(repo.excludepkgs))))
Packit Service 21c75c
            if repo.includepkgs:
Packit Service 21c75c
                logger.debug(_('Includes in repo ') + repo.id + ": "
Packit Service 21c75c
                             + ", ".join(sorted(set(repo.includepkgs))))
Packit Service 21c75c
Packit Service 21c75c
        return self.command.run()