Blame dnf/base.py

Packit Service 21c75c
# Copyright 2005 Duke University
Packit Service 21c75c
# Copyright (C) 2012-2018 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
"""
Packit Service 21c75c
Supplies the Base class.
Packit Service 21c75c
"""
Packit Service 21c75c
Packit Service 21c75c
from __future__ import absolute_import
Packit Service 21c75c
from __future__ import division
Packit Service 21c75c
from __future__ import print_function
Packit Service 21c75c
from __future__ import unicode_literals
Packit Service 21c75c
Packit Service 21c75c
import argparse
Packit Service 21c75c
import dnf
Packit Service 21c75c
import libdnf.transaction
Packit Service 21c75c
Packit Service 21c75c
from dnf.comps import CompsQuery
Packit Service 21c75c
from dnf.i18n import _, P_, ucd
Packit Service 21c75c
from dnf.util import _parse_specs
Packit Service 21c75c
from dnf.db.history import SwdbInterface
Packit Service 21c75c
from dnf.yum import misc
Packit Service 572e28
from functools import reduce
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 dnf.callback
Packit Service 21c75c
import dnf.comps
Packit Service 21c75c
import dnf.conf
Packit Service 21c75c
import dnf.conf.read
Packit Service 21c75c
import dnf.crypto
Packit Service 21c75c
import dnf.dnssec
Packit Service 21c75c
import dnf.drpm
Packit Service 21c75c
import dnf.exceptions
Packit Service 21c75c
import dnf.goal
Packit Service 21c75c
import dnf.history
Packit Service 21c75c
import dnf.lock
Packit Service 21c75c
import dnf.logging
Packit Service 21c75c
# WITH_MODULES is used by ansible (lib/ansible/modules/packaging/os/dnf.py)
Packit Service 21c75c
try:
Packit Service 21c75c
    import dnf.module.module_base
Packit Service 21c75c
    WITH_MODULES = True
Packit Service 21c75c
except ImportError:
Packit Service 21c75c
    WITH_MODULES = False
Packit Service 21c75c
import dnf.persistor
Packit Service 21c75c
import dnf.plugin
Packit Service 21c75c
import dnf.query
Packit Service 21c75c
import dnf.repo
Packit Service 21c75c
import dnf.repodict
Packit Service 21c75c
import dnf.rpm.connection
Packit Service 21c75c
import dnf.rpm.miscutils
Packit Service 21c75c
import dnf.rpm.transaction
Packit Service 21c75c
import dnf.sack
Packit Service 21c75c
import dnf.selector
Packit Service 21c75c
import dnf.subject
Packit Service 21c75c
import dnf.transaction
Packit Service 21c75c
import dnf.util
Packit Service 21c75c
import dnf.yum.rpmtrans
Packit Service 21c75c
import functools
Packit Service 21c75c
import hawkey
Packit Service 21c75c
import itertools
Packit Service 21c75c
import logging
Packit Service 21c75c
import math
Packit Service 21c75c
import os
Packit Service 21c75c
import operator
Packit Service 21c75c
import re
Packit Service 21c75c
import rpm
Packit Service 21c75c
import time
Packit Service 21c75c
import shutil
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
logger = logging.getLogger("dnf")
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
class Base(object):
Packit Service 21c75c
Packit Service 21c75c
    def __init__(self, conf=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        self._closed = False
Packit Service 21c75c
        self._conf = conf or self._setup_default_conf()
Packit Service 21c75c
        self._goal = None
Packit Service 21c75c
        self._repo_persistor = None
Packit Service 21c75c
        self._sack = None
Packit Service 21c75c
        self._transaction = None
Packit Service 21c75c
        self._priv_ts = None
Packit Service 21c75c
        self._comps = None
Packit Service 21c75c
        self._comps_trans = dnf.comps.TransactionBunch()
Packit Service 21c75c
        self._history = None
Packit Service 21c75c
        self._tempfiles = set()
Packit Service 21c75c
        self._trans_tempfiles = set()
Packit Service 21c75c
        self._ds_callback = dnf.callback.Depsolve()
Packit Service 21c75c
        self._logging = dnf.logging.Logging()
Packit Service 21c75c
        self._repos = dnf.repodict.RepoDict()
Packit Service 21c75c
        self._rpm_probfilter = set([rpm.RPMPROB_FILTER_OLDPACKAGE])
Packit Service 21c75c
        self._plugins = dnf.plugin.Plugins()
Packit Service 21c75c
        self._trans_success = False
Packit Service 21c75c
        self._trans_install_set = False
Packit Service 21c75c
        self._tempfile_persistor = None
Packit Service 21c75c
        self._update_security_filters = []
Packit Service 21c75c
        self._allow_erasing = False
Packit Service 21c75c
        self._repo_set_imported_gpg_keys = set()
Packit Service 21c75c
        self.output = None
Packit Service 21c75c
Packit Service 21c75c
    def __enter__(self):
Packit Service 21c75c
        return self
Packit Service 21c75c
Packit Service 21c75c
    def __exit__(self, *exc_args):
Packit Service 21c75c
        self.close()
Packit Service 21c75c
Packit Service 21c75c
    def __del__(self):
Packit Service 21c75c
        self.close()
Packit Service 21c75c
Packit Service 21c75c
    def _add_tempfiles(self, files):
Packit Service 21c75c
        if self._transaction:
Packit Service 21c75c
            self._trans_tempfiles.update(files)
Packit Service 21c75c
        elif self.conf.destdir:
Packit Service 21c75c
            pass
Packit Service 21c75c
        else:
Packit Service 21c75c
            self._tempfiles.update(files)
Packit Service 21c75c
Packit Service 21c75c
    def _add_repo_to_sack(self, repo):
Packit Service 21c75c
        repo.load()
Packit Service 21c75c
        mdload_flags = dict(load_filelists=True,
Packit Service 21c75c
                            load_presto=repo.deltarpm,
Packit Service 21c75c
                            load_updateinfo=True)
Packit Service 21c75c
        if repo.load_metadata_other:
Packit Service 21c75c
            mdload_flags["load_other"] = True
Packit Service 21c75c
        try:
Packit Service 21c75c
            self._sack.load_repo(repo._repo, build_cache=True, **mdload_flags)
Packit Service 21c75c
        except hawkey.Exception as e:
Packit Service 21c75c
            logger.debug(_("loading repo '{}' failure: {}").format(repo.id, e))
Packit Service 21c75c
            raise dnf.exceptions.RepoError(
Packit Service 21c75c
                _("Loading repository '{}' has failed").format(repo.id))
Packit Service 21c75c
Packit Service 21c75c
    @staticmethod
Packit Service 21c75c
    def _setup_default_conf():
Packit Service 21c75c
        conf = dnf.conf.Conf()
Packit Service 21c75c
        subst = conf.substitutions
Packit Service 21c75c
        if 'releasever' not in subst:
Packit Service 21c75c
            subst['releasever'] = \
Packit Service 21c75c
                dnf.rpm.detect_releasever(conf.installroot)
Packit Service 21c75c
        return conf
Packit Service 21c75c
Packit Service 21c75c
    def _setup_modular_excludes(self):
Packit Service 21c75c
        hot_fix_repos = [i.id for i in self.repos.iter_enabled() if i.module_hotfixes]
Packit Service 21c75c
        try:
Packit Service 21c75c
            solver_errors = self.sack.filter_modules(
Packit Service 21c75c
                self._moduleContainer, hot_fix_repos, self.conf.installroot,
Packit Service 21c75c
                self.conf.module_platform_id, update_only=False, debugsolver=self.conf.debug_solver)
Packit Service 21c75c
        except hawkey.Exception as e:
Packit Service 21c75c
            raise dnf.exceptions.Error(ucd(e))
Packit Service 21c75c
        if solver_errors:
Packit Service 21c75c
            logger.warning(
Packit Service 21c75c
                dnf.module.module_base.format_modular_solver_errors(solver_errors[0]))
Packit Service 21c75c
Packit Service 21c75c
    def _setup_excludes_includes(self, only_main=False):
Packit Service 21c75c
        disabled = set(self.conf.disable_excludes)
Packit Service 21c75c
        if 'all' in disabled and WITH_MODULES:
Packit Service 21c75c
            self._setup_modular_excludes()
Packit Service 21c75c
            return
Packit Service 21c75c
        repo_includes = []
Packit Service 21c75c
        repo_excludes = []
Packit Service 21c75c
        # first evaluate repo specific includes/excludes
Packit Service 21c75c
        if not only_main:
Packit Service 21c75c
            for r in self.repos.iter_enabled():
Packit Service 21c75c
                if r.id in disabled:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                if len(r.includepkgs) > 0:
Packit Service 21c75c
                    incl_query = self.sack.query().filterm(empty=True)
Packit Service 21c75c
                    for incl in set(r.includepkgs):
Packit Service 21c75c
                        subj = dnf.subject.Subject(incl)
Packit Service 21c75c
                        incl_query = incl_query.union(subj.get_best_query(
Packit Service 21c75c
                            self.sack, with_nevra=True, with_provides=False, with_filenames=False))
Packit Service 21c75c
                    incl_query.filterm(reponame=r.id)
Packit Service 21c75c
                    repo_includes.append((incl_query.apply(), r.id))
Packit Service 21c75c
                excl_query = self.sack.query().filterm(empty=True)
Packit Service 21c75c
                for excl in set(r.excludepkgs):
Packit Service 21c75c
                    subj = dnf.subject.Subject(excl)
Packit Service 21c75c
                    excl_query = excl_query.union(subj.get_best_query(
Packit Service 21c75c
                        self.sack, with_nevra=True, with_provides=False, with_filenames=False))
Packit Service 21c75c
                excl_query.filterm(reponame=r.id)
Packit Service 21c75c
                if excl_query:
Packit Service 21c75c
                    repo_excludes.append((excl_query, r.id))
Packit Service 21c75c
Packit Service 21c75c
        # then main (global) includes/excludes because they can mask
Packit Service 21c75c
        # repo specific settings
Packit Service 21c75c
        if 'main' not in disabled:
Packit Service 21c75c
            include_query = self.sack.query().filterm(empty=True)
Packit Service 21c75c
            if len(self.conf.includepkgs) > 0:
Packit Service 21c75c
                for incl in set(self.conf.includepkgs):
Packit Service 21c75c
                    subj = dnf.subject.Subject(incl)
Packit Service 21c75c
                    include_query = include_query.union(subj.get_best_query(
Packit Service 21c75c
                        self.sack, with_nevra=True, with_provides=False, with_filenames=False))
Packit Service 21c75c
            exclude_query = self.sack.query().filterm(empty=True)
Packit Service 21c75c
            for excl in set(self.conf.excludepkgs):
Packit Service 21c75c
                subj = dnf.subject.Subject(excl)
Packit Service 21c75c
                exclude_query = exclude_query.union(subj.get_best_query(
Packit Service 21c75c
                    self.sack, with_nevra=True, with_provides=False, with_filenames=False))
Packit Service 21c75c
            if len(self.conf.includepkgs) > 0:
Packit Service 21c75c
                self.sack.add_includes(include_query)
Packit Service 21c75c
                self.sack.set_use_includes(True)
Packit Service 21c75c
            if exclude_query:
Packit Service 21c75c
                self.sack.add_excludes(exclude_query)
Packit Service 21c75c
Packit Service 21c75c
        if repo_includes:
Packit Service 21c75c
            for query, repoid in repo_includes:
Packit Service 21c75c
                self.sack.add_includes(query)
Packit Service 21c75c
                self.sack.set_use_includes(True, repoid)
Packit Service 21c75c
Packit Service 21c75c
        if repo_excludes:
Packit Service 21c75c
            for query, repoid in repo_excludes:
Packit Service 21c75c
                self.sack.add_excludes(query)
Packit Service 21c75c
Packit Service 21c75c
        if not only_main and WITH_MODULES:
Packit Service 21c75c
            self._setup_modular_excludes()
Packit Service 21c75c
Packit Service 21c75c
    def _store_persistent_data(self):
Packit Service 21c75c
        if self._repo_persistor and not self.conf.cacheonly:
Packit Service 21c75c
            expired = [r.id for r in self.repos.iter_enabled()
Packit Service 21c75c
                       if (r.metadata and r._repo.isExpired())]
Packit Service 21c75c
            self._repo_persistor.expired_to_add.update(expired)
Packit Service 21c75c
            self._repo_persistor.save()
Packit Service 21c75c
Packit Service 21c75c
        if self._tempfile_persistor:
Packit Service 21c75c
            self._tempfile_persistor.save()
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def comps(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        return self._comps
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def conf(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        return self._conf
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def repos(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        return self._repos
Packit Service 21c75c
Packit Service 21c75c
    @repos.deleter
Packit Service 21c75c
    def repos(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        self._repos = None
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    @dnf.util.lazyattr("_priv_rpmconn")
Packit Service 21c75c
    def _rpmconn(self):
Packit Service 21c75c
        return dnf.rpm.connection.RpmConnection(self.conf.installroot)
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def sack(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        return self._sack
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def _moduleContainer(self):
Packit Service 21c75c
        if self.sack is None:
Packit Service 21c75c
            raise dnf.exceptions.Error("Sack was not initialized")
Packit Service 21c75c
        if self.sack._moduleContainer is None:
Packit Service 21c75c
            self.sack._moduleContainer = libdnf.module.ModulePackageContainer(
Packit Service 21c75c
                False, self.conf.installroot, self.conf.substitutions["arch"], self.conf.persistdir)
Packit Service 21c75c
        return self.sack._moduleContainer
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def transaction(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        return self._transaction
Packit Service 21c75c
Packit Service 21c75c
    @transaction.setter
Packit Service 21c75c
    def transaction(self, value):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        if self._transaction:
Packit Service 21c75c
            raise ValueError('transaction already set')
Packit Service 21c75c
        self._transaction = value
Packit Service 21c75c
Packit Service 21c75c
    def _activate_persistor(self):
Packit Service 21c75c
        self._repo_persistor = dnf.persistor.RepoPersistor(self.conf.cachedir)
Packit Service 21c75c
Packit Service 21c75c
    def init_plugins(self, disabled_glob=(), enable_plugins=(), cli=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Load plugins and run their __init__()."""
Packit Service 21c75c
        if self.conf.plugins:
Packit Service 21c75c
            self._plugins._load(self.conf, disabled_glob, enable_plugins)
Packit Service 21c75c
        self._plugins._run_init(self, cli)
Packit Service 21c75c
Packit Service 21c75c
    def pre_configure_plugins(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Run plugins pre_configure() method."""
Packit Service 21c75c
        self._plugins._run_pre_config()
Packit Service 21c75c
Packit Service 21c75c
    def configure_plugins(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Run plugins configure() method."""
Packit Service 21c75c
        self._plugins._run_config()
Packit Service 21c75c
Packit Service 21c75c
    def update_cache(self, timer=False):
Packit Service 21c75c
        # :api
Packit Service 21c75c
Packit Service 21c75c
        period = self.conf.metadata_timer_sync
Packit Service 21c75c
        persistor = self._repo_persistor
Packit Service 21c75c
        if timer:
Packit Service 21c75c
            if dnf.util.on_metered_connection():
Packit Service 21c75c
                msg = _('Metadata timer caching disabled '
Packit Service 21c75c
                        'when running on metered connection.')
Packit Service 21c75c
                logger.info(msg)
Packit Service 21c75c
                return False
Packit Service 21c75c
            if dnf.util.on_ac_power() is False:
Packit Service 21c75c
                msg = _('Metadata timer caching disabled '
Packit Service 21c75c
                        'when running on a battery.')
Packit Service 21c75c
                logger.info(msg)
Packit Service 21c75c
                return False
Packit Service 21c75c
            if period <= 0:
Packit Service 21c75c
                msg = _('Metadata timer caching disabled.')
Packit Service 21c75c
                logger.info(msg)
Packit Service 21c75c
                return False
Packit Service 21c75c
            since_last_makecache = persistor.since_last_makecache()
Packit Service 21c75c
            if since_last_makecache is not None and since_last_makecache < period:
Packit Service 21c75c
                logger.info(_('Metadata cache refreshed recently.'))
Packit Service 21c75c
                return False
Packit Service 21c75c
            for repo in self.repos.values():
Packit Service 21c75c
                repo._repo.setMaxMirrorTries(1)
Packit Service 21c75c
Packit Service 21c75c
        if not self.repos._any_enabled():
Packit Service 21c75c
            logger.info(_('There are no enabled repositories in "{}".').format(
Packit Service 21c75c
                '", "'.join(self.conf.reposdir)))
Packit Service 21c75c
            return False
Packit Service 21c75c
Packit Service 21c75c
        for r in self.repos.iter_enabled():
Packit Service 21c75c
            (is_cache, expires_in) = r._metadata_expire_in()
Packit Service 21c75c
            if expires_in is None:
Packit Service 21c75c
                logger.info(_('%s: will never be expired and will not be refreshed.'), r.id)
Packit Service 21c75c
            elif not is_cache or expires_in <= 0:
Packit Service 21c75c
                logger.debug(_('%s: has expired and will be refreshed.'), r.id)
Packit Service 21c75c
                r._repo.expire()
Packit Service 21c75c
            elif timer and expires_in < period:
Packit Service 21c75c
                # expires within the checking period:
Packit Service 21c75c
                msg = _("%s: metadata will expire after %d seconds and will be refreshed now")
Packit Service 21c75c
                logger.debug(msg, r.id, expires_in)
Packit Service 21c75c
                r._repo.expire()
Packit Service 21c75c
            else:
Packit Service 21c75c
                logger.debug(_('%s: will expire after %d seconds.'), r.id,
Packit Service 21c75c
                             expires_in)
Packit Service 21c75c
Packit Service 21c75c
        if timer:
Packit Service 21c75c
            persistor.reset_last_makecache = True
Packit Service 21c75c
        self.fill_sack(load_system_repo=False, load_available_repos=True)  # performs the md sync
Packit Service 21c75c
        logger.info(_('Metadata cache created.'))
Packit Service 21c75c
        return True
Packit Service 21c75c
Packit Service 21c75c
    def fill_sack(self, load_system_repo=True, load_available_repos=True):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Prepare the Sack and the Goal objects. """
Packit Service 21c75c
        timer = dnf.logging.Timer('sack setup')
Packit Service 21c75c
        self.reset(sack=True, goal=True)
Packit Service 21c75c
        self._sack = dnf.sack._build_sack(self)
Packit Service 21c75c
        lock = dnf.lock.build_metadata_lock(self.conf.cachedir, self.conf.exit_on_lock)
Packit Service 21c75c
        with lock:
Packit Service 21c75c
            if load_system_repo is not False:
Packit Service 21c75c
                try:
Packit Service 21c75c
                    # FIXME: If build_cache=True, @System.solv is incorrectly updated in install-
Packit Service 21c75c
                    # remove loops
Packit Service 21c75c
                    self._sack.load_system_repo(build_cache=False)
Packit Service 21c75c
                except IOError:
Packit Service 21c75c
                    if load_system_repo != 'auto':
Packit Service 21c75c
                        raise
Packit Service 21c75c
            if load_available_repos:
Packit Service 21c75c
                error_repos = []
Packit Service 21c75c
                mts = 0
Packit Service 21c75c
                age = time.time()
Packit Service 21c75c
                # Iterate over installed GPG keys and check their validity using DNSSEC
Packit Service 21c75c
                if self.conf.gpgkey_dns_verification:
Packit Service 21c75c
                    dnf.dnssec.RpmImportedKeys.check_imported_keys_validity()
Packit Service 21c75c
                for r in self.repos.iter_enabled():
Packit Service 21c75c
                    try:
Packit Service 21c75c
                        self._add_repo_to_sack(r)
Packit Service 21c75c
                        if r._repo.getTimestamp() > mts:
Packit Service 21c75c
                            mts = r._repo.getTimestamp()
Packit Service 21c75c
                        if r._repo.getAge() < age:
Packit Service 21c75c
                            age = r._repo.getAge()
Packit Service 21c75c
                        logger.debug(_("%s: using metadata from %s."), r.id,
Packit Service 21c75c
                                     dnf.util.normalize_time(
Packit Service 21c75c
                                         r._repo.getMaxTimestamp()))
Packit Service 21c75c
                    except dnf.exceptions.RepoError as e:
Packit Service 21c75c
                        r._repo.expire()
Packit Service 21c75c
                        if r.skip_if_unavailable is False:
Packit Service 21c75c
                            raise
Packit Service 21c75c
                        logger.warning("Error: %s", e)
Packit Service 21c75c
                        error_repos.append(r.id)
Packit Service 21c75c
                        r.disable()
Packit Service 21c75c
                if error_repos:
Packit Service 21c75c
                    logger.warning(
Packit Service 21c75c
                        _("Ignoring repositories: %s"), ', '.join(error_repos))
Packit Service 21c75c
                if self.repos._any_enabled():
Packit Service 21c75c
                    if age != 0 and mts != 0:
Packit Service 21c75c
                        logger.info(_("Last metadata expiration check: %s ago on %s."),
Packit Service 21c75c
                                    datetime.timedelta(seconds=int(age)),
Packit Service 21c75c
                                    dnf.util.normalize_time(mts))
Packit Service 21c75c
            else:
Packit Service 21c75c
                self.repos.all().disable()
Packit Service 21c75c
        conf = self.conf
Packit Service 21c75c
        self._sack._configure(conf.installonlypkgs, conf.installonly_limit, conf.allow_vendor_change)
Packit Service 21c75c
        self._setup_excludes_includes()
Packit Service 21c75c
        timer()
Packit Service 21c75c
        self._goal = dnf.goal.Goal(self._sack)
Packit Service 21c75c
        self._goal.protect_running_kernel = conf.protect_running_kernel
Packit Service 21c75c
        self._plugins.run_sack()
Packit Service 21c75c
        return self._sack
Packit Service 21c75c
Packit Service 21c75c
    def _finalize_base(self):
Packit Service 21c75c
        self._tempfile_persistor = dnf.persistor.TempfilePersistor(
Packit Service 21c75c
            self.conf.cachedir)
Packit Service 21c75c
Packit Service 21c75c
        if not self.conf.keepcache:
Packit Service 21c75c
            self._clean_packages(self._tempfiles)
Packit Service 21c75c
            if self._trans_success:
Packit Service 21c75c
                self._trans_tempfiles.update(
Packit Service 21c75c
                    self._tempfile_persistor.get_saved_tempfiles())
Packit Service 21c75c
                self._tempfile_persistor.empty()
Packit Service 21c75c
                if self._trans_install_set:
Packit Service 21c75c
                    self._clean_packages(self._trans_tempfiles)
Packit Service 21c75c
            else:
Packit Service 21c75c
                self._tempfile_persistor.tempfiles_to_add.update(
Packit Service 21c75c
                    self._trans_tempfiles)
Packit Service 21c75c
Packit Service 21c75c
        if self._tempfile_persistor.tempfiles_to_add:
Packit Service 21c75c
            logger.info(_("The downloaded packages were saved in cache "
Packit Service 21c75c
                          "until the next successful transaction."))
Packit Service 21c75c
            logger.info(_("You can remove cached packages by executing "
Packit Service 21c75c
                          "'%s'."), "{prog} clean packages".format(prog=dnf.util.MAIN_PROG))
Packit Service 21c75c
Packit Service 21c75c
        # Do not trigger the lazy creation:
Packit Service 21c75c
        if self._history is not None:
Packit Service 21c75c
            self.history.close()
Packit Service 21c75c
        self._store_persistent_data()
Packit Service 21c75c
        self._closeRpmDB()
Packit Service 21c75c
        self._trans_success = False
Packit Service 21c75c
Packit Service 21c75c
    def close(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Close all potential handles and clean cache.
Packit Service 21c75c
Packit Service 21c75c
        Typically the handles are to data sources and sinks.
Packit Service 21c75c
Packit Service 21c75c
        """
Packit Service 21c75c
Packit Service 21c75c
        if self._closed:
Packit Service 21c75c
            return
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, 'Cleaning up.')
Packit Service 21c75c
        self._closed = True
Packit Service 21c75c
        self._finalize_base()
Packit Service 21c75c
        self.reset(sack=True, repos=True, goal=True)
Packit Service 21c75c
Packit Service 21c75c
    def read_all_repos(self, opts=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Read repositories from the main conf file and from .repo files."""
Packit Service 21c75c
Packit Service 21c75c
        reader = dnf.conf.read.RepoReader(self.conf, opts)
Packit Service 21c75c
        for repo in reader:
Packit Service 21c75c
            try:
Packit Service 21c75c
                self.repos.add(repo)
Packit Service 21c75c
            except dnf.exceptions.ConfigError as e:
Packit Service 21c75c
                logger.warning(e)
Packit Service 21c75c
Packit Service 21c75c
    def reset(self, sack=False, repos=False, goal=False):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Make the Base object forget about various things."""
Packit Service 21c75c
        if sack:
Packit Service 21c75c
            self._sack = None
Packit Service 21c75c
        if repos:
Packit Service 21c75c
            self._repos = dnf.repodict.RepoDict()
Packit Service 21c75c
        if goal:
Packit Service 21c75c
            self._goal = None
Packit Service 21c75c
            if self._sack is not None:
Packit Service 21c75c
                self._goal = dnf.goal.Goal(self._sack)
Packit Service 21c75c
                self._goal.protect_running_kernel = self.conf.protect_running_kernel
Packit Service 21c75c
            if self._sack and self._moduleContainer:
Packit Service 21c75c
                # sack must be set to enable operations on moduleContainer
Packit Service 21c75c
                self._moduleContainer.rollback()
Packit Service 21c75c
            if self._history is not None:
Packit Service 21c75c
                self.history.close()
Packit Service 21c75c
            self._comps_trans = dnf.comps.TransactionBunch()
Packit Service 21c75c
            self._transaction = None
Packit Service 21c75c
Packit Service 21c75c
    def _closeRpmDB(self):
Packit Service 21c75c
        """Closes down the instances of rpmdb that could be open."""
Packit Service 21c75c
        del self._ts
Packit Service 21c75c
Packit Service 21c75c
    _TS_FLAGS_TO_RPM = {'noscripts': rpm.RPMTRANS_FLAG_NOSCRIPTS,
Packit Service 21c75c
                        'notriggers': rpm.RPMTRANS_FLAG_NOTRIGGERS,
Packit Service 21c75c
                        'nodocs': rpm.RPMTRANS_FLAG_NODOCS,
Packit Service 21c75c
                        'test': rpm.RPMTRANS_FLAG_TEST,
Packit Service 21c75c
                        'justdb': rpm.RPMTRANS_FLAG_JUSTDB,
Packit Service 21c75c
                        'nocontexts': rpm.RPMTRANS_FLAG_NOCONTEXTS,
Packit Service 21c75c
                        'nocrypto': rpm.RPMTRANS_FLAG_NOFILEDIGEST}
Packit Service 21c75c
    if hasattr(rpm, 'RPMTRANS_FLAG_NOCAPS'):
Packit Service 21c75c
        # Introduced in rpm-4.14
Packit Service 21c75c
        _TS_FLAGS_TO_RPM['nocaps'] = rpm.RPMTRANS_FLAG_NOCAPS
Packit Service 21c75c
Packit Service 21c75c
    _TS_VSFLAGS_TO_RPM = {'nocrypto': rpm._RPMVSF_NOSIGNATURES |
Packit Service 21c75c
                          rpm._RPMVSF_NODIGESTS}
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def goal(self):
Packit Service 21c75c
        return self._goal
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def _ts(self):
Packit Service 21c75c
        """Set up the RPM transaction set that will be used
Packit Service 21c75c
           for all the work."""
Packit Service 21c75c
        if self._priv_ts is not None:
Packit Service 21c75c
            return self._priv_ts
Packit Service 21c75c
        self._priv_ts = dnf.rpm.transaction.TransactionWrapper(
Packit Service 21c75c
            self.conf.installroot)
Packit Service 21c75c
        self._priv_ts.setFlags(0)  # reset everything.
Packit Service 21c75c
        for flag in self.conf.tsflags:
Packit Service 21c75c
            rpm_flag = self._TS_FLAGS_TO_RPM.get(flag)
Packit Service 21c75c
            if rpm_flag is None:
Packit Service 21c75c
                logger.critical(_('Invalid tsflag in config file: %s'), flag)
Packit Service 21c75c
                continue
Packit Service 21c75c
            self._priv_ts.addTsFlag(rpm_flag)
Packit Service 21c75c
            vs_flag = self._TS_VSFLAGS_TO_RPM.get(flag)
Packit Service 21c75c
            if vs_flag is not None:
Packit Service 21c75c
                self._priv_ts.pushVSFlags(vs_flag)
Packit Service 21c75c
Packit Service 21c75c
        if not self.conf.diskspacecheck:
Packit Service 21c75c
            self._rpm_probfilter.add(rpm.RPMPROB_FILTER_DISKSPACE)
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.ignorearch:
Packit Service 21c75c
            self._rpm_probfilter.add(rpm.RPMPROB_FILTER_IGNOREARCH)
Packit Service 21c75c
Packit Service 572e28
        probfilter = reduce(operator.or_, self._rpm_probfilter, 0)
Packit Service 21c75c
        self._priv_ts.setProbFilter(probfilter)
Packit Service 21c75c
        return self._priv_ts
Packit Service 21c75c
Packit Service 21c75c
    @_ts.deleter
Packit Service 21c75c
    def _ts(self):
Packit Service 21c75c
        """Releases the RPM transaction set. """
Packit Service 21c75c
        if self._priv_ts is None:
Packit Service 21c75c
            return
Packit Service 21c75c
        self._priv_ts.close()
Packit Service 21c75c
        del self._priv_ts
Packit Service 21c75c
        self._priv_ts = None
Packit Service 21c75c
Packit Service 21c75c
    def read_comps(self, arch_filter=False):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Create the groups object to access the comps metadata."""
Packit Service 21c75c
        timer = dnf.logging.Timer('loading comps')
Packit Service 21c75c
        self._comps = dnf.comps.Comps()
Packit Service 21c75c
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, 'Getting group metadata')
Packit Service 21c75c
        for repo in self.repos.iter_enabled():
Packit Service 21c75c
            if not repo.enablegroups:
Packit Service 21c75c
                continue
Packit Service 21c75c
            if not repo.metadata:
Packit Service 21c75c
                continue
Packit Service 21c75c
            comps_fn = repo._repo.getCompsFn()
Packit Service 21c75c
            if not comps_fn:
Packit Service 21c75c
                continue
Packit Service 21c75c
Packit Service 21c75c
            logger.log(dnf.logging.DDEBUG,
Packit Service 21c75c
                       'Adding group file from repository: %s', repo.id)
Packit Service 21c75c
            if repo._repo.getSyncStrategy() == dnf.repo.SYNC_ONLY_CACHE:
Packit Service 21c75c
                decompressed = misc.calculate_repo_gen_dest(comps_fn,
Packit Service 21c75c
                                                            'groups.xml')
Packit Service 21c75c
                if not os.path.exists(decompressed):
Packit Service 21c75c
                    # root privileges are needed for comps decompression
Packit Service 21c75c
                    continue
Packit Service 21c75c
            else:
Packit Service 21c75c
                decompressed = misc.repo_gen_decompress(comps_fn, 'groups.xml')
Packit Service 21c75c
Packit Service 21c75c
            try:
Packit Service 21c75c
                self._comps._add_from_xml_filename(decompressed)
Packit Service 21c75c
            except dnf.exceptions.CompsError as e:
Packit Service 21c75c
                msg = _('Failed to add groups file for repository: %s - %s')
Packit Service 21c75c
                logger.critical(msg, repo.id, e)
Packit Service 21c75c
Packit Service 21c75c
        if arch_filter:
Packit Service 21c75c
            self._comps._i.arch_filter(
Packit Service 21c75c
                [self._conf.substitutions['basearch']])
Packit Service 21c75c
        timer()
Packit Service 21c75c
        return self._comps
Packit Service 21c75c
Packit Service 21c75c
    def _getHistory(self):
Packit Service 21c75c
        """auto create the history object that to access/append the transaction
Packit Service 21c75c
           history information. """
Packit Service 21c75c
        if self._history is None:
Packit Service 21c75c
            releasever = self.conf.releasever
Packit Service 21c75c
            self._history = SwdbInterface(self.conf.persistdir, releasever=releasever)
Packit Service 21c75c
        return self._history
Packit Service 21c75c
Packit Service 21c75c
    history = property(fget=lambda self: self._getHistory(),
Packit Service 21c75c
                       fset=lambda self, value: setattr(
Packit Service 21c75c
                           self, "_history", value),
Packit Service 21c75c
                       fdel=lambda self: setattr(self, "_history", None),
Packit Service 21c75c
                       doc="DNF SWDB Interface Object")
Packit Service 21c75c
Packit Service 21c75c
    def _goal2transaction(self, goal):
Packit Service 21c75c
        ts = self.history.rpm
Packit Service 21c75c
        all_obsoleted = set(goal.list_obsoleted())
Packit Service 21c75c
        installonly_query = self._get_installonly_query()
Packit Service 21c75c
Packit Service 21c75c
        for pkg in goal.list_downgrades():
Packit Service 21c75c
            obs = goal.obsoleted_by_package(pkg)
Packit Service 21c75c
            downgraded = obs[0]
Packit Service 21c75c
            self._ds_callback.pkg_added(downgraded, 'dd')
Packit Service 21c75c
            self._ds_callback.pkg_added(pkg, 'd')
Packit Service 21c75c
            ts.add_downgrade(pkg, downgraded, obs[1:])
Packit Service 21c75c
        for pkg in goal.list_reinstalls():
Packit Service 21c75c
            self._ds_callback.pkg_added(pkg, 'r')
Packit Service 21c75c
            obs = goal.obsoleted_by_package(pkg)
Packit Service 21c75c
            nevra_pkg = str(pkg)
Packit Service 21c75c
            # reinstall could obsolete multiple packages with the same NEVRA or different NEVRA
Packit Service 21c75c
            # Set the package with the same NEVRA as reinstalled
Packit Service 21c75c
            obsoletes = []
Packit Service 21c75c
            for obs_pkg in obs:
Packit Service 21c75c
                if str(obs_pkg) == nevra_pkg:
Packit Service 21c75c
                    obsoletes.insert(0, obs_pkg)
Packit Service 21c75c
                else:
Packit Service 21c75c
                    obsoletes.append(obs_pkg)
Packit Service 21c75c
            reinstalled = obsoletes[0]
Packit Service 21c75c
            ts.add_reinstall(pkg, reinstalled, obsoletes[1:])
Packit Service 21c75c
        for pkg in goal.list_installs():
Packit Service 21c75c
            self._ds_callback.pkg_added(pkg, 'i')
Packit Service 21c75c
            obs = goal.obsoleted_by_package(pkg)
Packit Service 21c75c
            # Skip obsoleted packages that are not part of all_obsoleted,
Packit Service 21c75c
            # they are handled as upgrades/downgrades.
Packit Service 21c75c
            # Also keep RPMs with the same name - they're not always in all_obsoleted.
Packit Service 21c75c
            obs = [i for i in obs if i in all_obsoleted or i.name == pkg.name]
Packit Service 21c75c
Packit Service 21c75c
            reason = goal.get_reason(pkg)
Packit Service 21c75c
Packit Service 21c75c
            if pkg in installonly_query:
Packit Service 21c75c
                reason_installonly = ts.get_reason(pkg)
Packit Service 21c75c
                if libdnf.transaction.TransactionItemReasonCompare(
Packit Service 21c75c
                        reason, reason_installonly) == -1:
Packit Service 21c75c
                    reason = reason_installonly
Packit Service 21c75c
Packit Service 21c75c
            # inherit the best reason from obsoleted packages
Packit Service 21c75c
            for obsolete in obs:
Packit Service 21c75c
                reason_obsolete = ts.get_reason(obsolete)
Packit Service 21c75c
                if libdnf.transaction.TransactionItemReasonCompare(reason, reason_obsolete) == -1:
Packit Service 21c75c
                    reason = reason_obsolete
Packit Service 21c75c
Packit Service 21c75c
            ts.add_install(pkg, obs, reason)
Packit Service 21c75c
            cb = lambda pkg: self._ds_callback.pkg_added(pkg, 'od')
Packit Service 21c75c
            dnf.util.mapall(cb, obs)
Packit Service 21c75c
        for pkg in goal.list_upgrades():
Packit Service 21c75c
            obs = goal.obsoleted_by_package(pkg)
Packit Service 21c75c
            upgraded = None
Packit Service 21c75c
            for i in obs:
Packit Service 21c75c
                # try to find a package with matching name as the upgrade
Packit Service 21c75c
                if i.name == pkg.name:
Packit Service 21c75c
                    upgraded = i
Packit Service 21c75c
                    break
Packit Service 21c75c
            if upgraded is None:
Packit Service 21c75c
                # no matching name -> pick the first one
Packit Service 21c75c
                upgraded = obs.pop(0)
Packit Service 21c75c
            else:
Packit Service 21c75c
                obs.remove(upgraded)
Packit Service 21c75c
            # Skip obsoleted packages that are not part of all_obsoleted,
Packit Service 21c75c
            # they are handled as upgrades/downgrades.
Packit Service 21c75c
            # Also keep RPMs with the same name - they're not always in all_obsoleted.
Packit Service 21c75c
            obs = [i for i in obs if i in all_obsoleted or i.name == pkg.name]
Packit Service 21c75c
Packit Service 21c75c
            cb = lambda pkg: self._ds_callback.pkg_added(pkg, 'od')
Packit Service 21c75c
            dnf.util.mapall(cb, obs)
Packit Service 21c75c
            if pkg in installonly_query:
Packit Service 21c75c
                ts.add_install(pkg, obs)
Packit Service 21c75c
            else:
Packit Service 21c75c
                ts.add_upgrade(pkg, upgraded, obs)
Packit Service 21c75c
                self._ds_callback.pkg_added(upgraded, 'ud')
Packit Service 21c75c
            self._ds_callback.pkg_added(pkg, 'u')
Packit Service 21c75c
        for pkg in goal.list_erasures():
Packit Service 21c75c
            self._ds_callback.pkg_added(pkg, 'e')
Packit Service 21c75c
            reason = goal.get_reason(pkg)
Packit Service 21c75c
            ts.add_erase(pkg, reason)
Packit Service 21c75c
        return ts
Packit Service 21c75c
Packit Service 21c75c
    def _query_matches_installed(self, q):
Packit Service 21c75c
        """ See what packages in the query match packages (also in older
Packit Service 21c75c
            versions, but always same architecture) that are already installed.
Packit Service 21c75c
Packit Service 21c75c
            Unlike in case of _sltr_matches_installed(), it is practical here
Packit Service 21c75c
            to know even the packages in the original query that can still be
Packit Service 21c75c
            installed.
Packit Service 21c75c
        """
Packit Service 21c75c
        inst = q.installed()
Packit Service 21c75c
        inst_per_arch = inst._na_dict()
Packit Service 21c75c
        avail_per_arch = q.available()._na_dict()
Packit Service 21c75c
        avail_l = []
Packit Service 21c75c
        inst_l = []
Packit Service 21c75c
        for na in avail_per_arch:
Packit Service 21c75c
            if na in inst_per_arch:
Packit Service 21c75c
                inst_l.append(inst_per_arch[na][0])
Packit Service 21c75c
            else:
Packit Service 21c75c
                avail_l.append(avail_per_arch[na])
Packit Service 21c75c
        return inst_l, avail_l
Packit Service 21c75c
Packit Service 21c75c
    def _sltr_matches_installed(self, sltr):
Packit Service 21c75c
        """ See if sltr matches a patches that is (in older version or different
Packit Service 21c75c
            architecture perhaps) already installed.
Packit Service 21c75c
        """
Packit Service 21c75c
        inst = self.sack.query().installed().filterm(pkg=sltr.matches())
Packit Service 21c75c
        return list(inst)
Packit Service 21c75c
Packit Service 21c75c
    def iter_userinstalled(self):
Packit Service 21c75c
        """Get iterator over the packages installed by the user."""
Packit Service 21c75c
        return (pkg for pkg in self.sack.query().installed()
Packit Service 21c75c
                if self.history.user_installed(pkg))
Packit Service 21c75c
Packit Service 21c75c
    def _run_hawkey_goal(self, goal, allow_erasing):
Packit Service 21c75c
        ret = goal.run(
Packit Service 21c75c
            allow_uninstall=allow_erasing, force_best=self.conf.best,
Packit Service 21c75c
            ignore_weak_deps=(not self.conf.install_weak_deps))
Packit Service 21c75c
        if self.conf.debug_solver:
Packit Service 21c75c
            goal.write_debugdata('./debugdata/rpms')
Packit Service 21c75c
        return ret
Packit Service 21c75c
Packit Service 21c75c
    def resolve(self, allow_erasing=False):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Build the transaction set."""
Packit Service 21c75c
        exc = None
Packit Service 21c75c
        self._finalize_comps_trans()
Packit Service 21c75c
Packit Service 21c75c
        timer = dnf.logging.Timer('depsolve')
Packit Service 21c75c
        self._ds_callback.start()
Packit Service 21c75c
        goal = self._goal
Packit Service 21c75c
        if goal.req_has_erase():
Packit Service 21c75c
            goal.push_userinstalled(self.sack.query().installed(),
Packit Service 21c75c
                                    self.history)
Packit Service 21c75c
        elif not self.conf.upgrade_group_objects_upgrade:
Packit Service 21c75c
            # exclude packages installed from groups
Packit Service 21c75c
            # these packages will be marked to installation
Packit Service 21c75c
            # which could prevent them from upgrade, downgrade
Packit Service 21c75c
            # to prevent "conflicting job" error it's not applied
Packit Service 21c75c
            # to "remove" and "reinstall" commands
Packit Service 21c75c
Packit Service 21c75c
            solver = self._build_comps_solver()
Packit Service 21c75c
            solver._exclude_packages_from_installed_groups(self)
Packit Service 21c75c
Packit Service 21c75c
        goal.add_protected(self.sack.query().filterm(
Packit Service 21c75c
            name=self.conf.protected_packages))
Packit Service 21c75c
        if not self._run_hawkey_goal(goal, allow_erasing):
Packit Service 21c75c
            if self.conf.debuglevel >= 6:
Packit Service 21c75c
                goal.log_decisions()
Packit Service 21c75c
            msg = dnf.util._format_resolve_problems(goal.problem_rules())
Packit Service 21c75c
            exc = dnf.exceptions.DepsolveError(msg)
Packit Service 21c75c
        else:
Packit Service 21c75c
            self._transaction = self._goal2transaction(goal)
Packit Service 21c75c
Packit Service 21c75c
        self._ds_callback.end()
Packit Service 21c75c
        timer()
Packit Service 21c75c
Packit Service 21c75c
        got_transaction = self._transaction is not None and \
Packit Service 21c75c
            len(self._transaction) > 0
Packit Service 21c75c
        if got_transaction:
Packit Service 21c75c
            msg = self._transaction._rpm_limitations()
Packit Service 21c75c
            if msg:
Packit Service 21c75c
                exc = dnf.exceptions.Error(msg)
Packit Service 21c75c
Packit Service 21c75c
        if exc is not None:
Packit Service 21c75c
            raise exc
Packit Service 21c75c
Packit Service 21c75c
        self._plugins.run_resolved()
Packit Service 21c75c
Packit Service 21c75c
        # auto-enable module streams based on installed RPMs
Packit Service 21c75c
        new_pkgs = self._goal.list_installs()
Packit Service 21c75c
        new_pkgs += self._goal.list_upgrades()
Packit Service 21c75c
        new_pkgs += self._goal.list_downgrades()
Packit Service 21c75c
        new_pkgs += self._goal.list_reinstalls()
Packit Service 21c75c
        self.sack.set_modules_enabled_by_pkgset(self._moduleContainer, new_pkgs)
Packit Service 21c75c
Packit Service 21c75c
        return got_transaction
Packit Service 21c75c
Packit Service 21c75c
    def do_transaction(self, display=()):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        if not isinstance(display, Sequence):
Packit Service 21c75c
            display = [display]
Packit Service 21c75c
        display = \
Packit Service 21c75c
            [dnf.yum.rpmtrans.LoggingTransactionDisplay()] + list(display)
Packit Service 21c75c
Packit Service 21c75c
        if not self.transaction:
Packit Service 21c75c
            # packages are not changed, but comps and modules changes need to be committed
Packit Service 21c75c
            self._moduleContainer.save()
Packit Service 21c75c
            self._moduleContainer.updateFailSafeData()
Packit Service 21c75c
            if self._history and (self._history.group or self._history.env):
Packit Service 21c75c
                cmdline = None
Packit Service 21c75c
                if hasattr(self, 'args') and self.args:
Packit Service 21c75c
                    cmdline = ' '.join(self.args)
Packit Service 21c75c
                elif hasattr(self, 'cmds') and self.cmds:
Packit Service 21c75c
                    cmdline = ' '.join(self.cmds)
Packit Service 21c75c
                old = self.history.last()
Packit Service 21c75c
                if old is None:
Packit Service 21c75c
                    rpmdb_version = self.sack._rpmdb_version()
Packit Service 21c75c
                else:
Packit Service 21c75c
                    rpmdb_version = old.end_rpmdb_version
Packit Service 21c75c
Packit Service 21c75c
                self.history.beg(rpmdb_version, [], [], cmdline)
Packit Service 21c75c
                self.history.end(rpmdb_version)
Packit Service 21c75c
            self._plugins.run_pre_transaction()
Packit Service 21c75c
            self._plugins.run_transaction()
Packit Service 21c75c
            self._trans_success = True
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        tid = None
Packit Service 21c75c
        logger.info(_('Running transaction check'))
Packit Service 21c75c
        lock = dnf.lock.build_rpmdb_lock(self.conf.persistdir,
Packit Service 21c75c
                                         self.conf.exit_on_lock)
Packit Service 21c75c
        with lock:
Packit Service 21c75c
            self.transaction._populate_rpm_ts(self._ts)
Packit Service 21c75c
Packit Service 21c75c
            msgs = self._run_rpm_check()
Packit Service 21c75c
            if msgs:
Packit Service 21c75c
                msg = _('Error: transaction check vs depsolve:')
Packit Service 21c75c
                logger.error(msg)
Packit Service 21c75c
                for msg in msgs:
Packit Service 21c75c
                    logger.error(msg)
Packit Service 21c75c
                raise dnf.exceptions.TransactionCheckError(msg)
Packit Service 21c75c
Packit Service 21c75c
            logger.info(_('Transaction check succeeded.'))
Packit Service 21c75c
Packit Service 21c75c
            timer = dnf.logging.Timer('transaction test')
Packit Service 21c75c
            logger.info(_('Running transaction test'))
Packit Service 21c75c
Packit Service 21c75c
            self._ts.order()  # order the transaction
Packit Service 21c75c
            self._ts.clean()  # release memory not needed beyond this point
Packit Service 21c75c
Packit Service 21c75c
            testcb = dnf.yum.rpmtrans.RPMTransaction(self, test=True)
Packit Service 21c75c
            tserrors = self._ts.test(testcb)
Packit Service 21c75c
Packit Service 21c75c
            if len(tserrors) > 0:
Packit Service 21c75c
                for msg in testcb.messages():
Packit Service 21c75c
                    logger.critical(_('RPM: {}').format(msg))
Packit Service 21c75c
                errstring = _('Transaction test error:') + '\n'
Packit Service 21c75c
                for descr in tserrors:
Packit Service 21c75c
                    errstring += '  %s\n' % ucd(descr)
Packit Service 21c75c
Packit Service 21c75c
                summary = self._trans_error_summary(errstring)
Packit Service 21c75c
                if summary:
Packit Service 21c75c
                    errstring += '\n' + summary
Packit Service 21c75c
Packit Service 21c75c
                raise dnf.exceptions.Error(errstring)
Packit Service 21c75c
            del testcb
Packit Service 21c75c
Packit Service 21c75c
            logger.info(_('Transaction test succeeded.'))
Packit Service 21c75c
            #  With RPMTRANS_FLAG_TEST return just before anything is stored permanently
Packit Service 21c75c
            if self._ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST):
Packit Service 21c75c
                return
Packit Service 21c75c
            timer()
Packit Service 21c75c
Packit Service 21c75c
            # save module states on disk right before entering rpm transaction,
Packit Service 21c75c
            # because we want system in recoverable state if transaction gets interrupted
Packit Service 21c75c
            self._moduleContainer.save()
Packit Service 21c75c
            self._moduleContainer.updateFailSafeData()
Packit Service 21c75c
Packit Service 21c75c
            # unset the sigquit handler
Packit Service 21c75c
            timer = dnf.logging.Timer('transaction')
Packit Service 21c75c
            # setup our rpm ts callback
Packit Service 21c75c
            cb = dnf.yum.rpmtrans.RPMTransaction(self, displays=display)
Packit Service 21c75c
            if self.conf.debuglevel < 2:
Packit Service 21c75c
                for display_ in cb.displays:
Packit Service 21c75c
                    display_.output = False
Packit Service 21c75c
Packit Service 21c75c
            self._plugins.run_pre_transaction()
Packit Service 21c75c
Packit Service 21c75c
            logger.info(_('Running transaction'))
Packit Service 21c75c
            tid = self._run_transaction(cb=cb)
Packit Service 21c75c
        timer()
Packit Service 21c75c
        self._plugins.unload_removed_plugins(self.transaction)
Packit Service 21c75c
        self._plugins.run_transaction()
Packit Service 21c75c
Packit Service 21c75c
        return tid
Packit Service 21c75c
Packit Service 21c75c
    def _trans_error_summary(self, errstring):
Packit Service 21c75c
        """Parse the error string for 'interesting' errors which can
Packit Service 21c75c
        be grouped, such as disk space issues.
Packit Service 21c75c
Packit Service 21c75c
        :param errstring: the error string
Packit Service 21c75c
        :return: a string containing a summary of the errors
Packit Service 21c75c
        """
Packit Service 21c75c
        summary = ''
Packit Service 21c75c
        # do disk space report first
Packit Service 21c75c
        p = re.compile(r'needs (\d+)(K|M)B(?: more space)? on the (\S+) filesystem')
Packit Service 21c75c
        disk = {}
Packit Service 21c75c
        for m in p.finditer(errstring):
Packit Service 21c75c
            size_in_mb = int(m.group(1)) if m.group(2) == 'M' else math.ceil(
Packit Service 21c75c
                int(m.group(1)) / 1024.0)
Packit Service 21c75c
            if m.group(3) not in disk:
Packit Service 21c75c
                disk[m.group(3)] = size_in_mb
Packit Service 21c75c
            if disk[m.group(3)] < size_in_mb:
Packit Service 21c75c
                disk[m.group(3)] = size_in_mb
Packit Service 21c75c
Packit Service 21c75c
        if disk:
Packit Service 21c75c
            summary += _('Disk Requirements:') + "\n"
Packit Service 21c75c
            for k in disk:
Packit Service 21c75c
                summary += "   " + P_(
Packit Service 21c75c
                    'At least {0}MB more space needed on the {1} filesystem.',
Packit Service 21c75c
                    'At least {0}MB more space needed on the {1} filesystem.',
Packit Service 21c75c
                    disk[k]).format(disk[k], k) + '\n'
Packit Service 21c75c
Packit Service 21c75c
        if not summary:
Packit Service 21c75c
            return None
Packit Service 21c75c
Packit Service 21c75c
        summary = _('Error Summary') + '\n-------------\n' + summary
Packit Service 21c75c
Packit Service 21c75c
        return summary
Packit Service 21c75c
Packit Service 21c75c
    def _record_history(self):
Packit Service 21c75c
        return self.conf.history_record and \
Packit Service 21c75c
            not self._ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST)
Packit Service 21c75c
Packit Service 21c75c
    def _run_transaction(self, cb):
Packit Service 21c75c
        """
Packit Service 21c75c
        Perform the RPM transaction.
Packit Service 21c75c
Packit Service 21c75c
        :return: history database transaction ID or None
Packit Service 21c75c
        """
Packit Service 21c75c
Packit Service 21c75c
        tid = None
Packit Service 21c75c
        if self._record_history():
Packit Service 21c75c
            using_pkgs_pats = list(self.conf.history_record_packages)
Packit Service 21c75c
            installed_query = self.sack.query().installed()
Packit Service 21c75c
            using_pkgs = installed_query.filter(name=using_pkgs_pats).run()
Packit Service 21c75c
            rpmdbv = self.sack._rpmdb_version()
Packit Service 21c75c
            lastdbv = self.history.last()
Packit Service 21c75c
            if lastdbv is not None:
Packit Service 21c75c
                lastdbv = lastdbv.end_rpmdb_version
Packit Service 21c75c
Packit Service 21c75c
            if lastdbv is None or rpmdbv != lastdbv:
Packit Service 21c75c
                logger.debug(_("RPMDB altered outside of {prog}.").format(
Packit Service 21c75c
                    prog=dnf.util.MAIN_PROG_UPPER))
Packit Service 21c75c
Packit Service 21c75c
            cmdline = None
Packit Service 21c75c
            if hasattr(self, 'args') and self.args:
Packit Service 21c75c
                cmdline = ' '.join(self.args)
Packit Service 21c75c
            elif hasattr(self, 'cmds') and self.cmds:
Packit Service 21c75c
                cmdline = ' '.join(self.cmds)
Packit Service 21c75c
Packit Service 21c75c
            comment = self.conf.comment if self.conf.comment else ""
Packit Service 21c75c
            tid = self.history.beg(rpmdbv, using_pkgs, [], cmdline, comment)
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.reset_nice:
Packit Service 21c75c
            onice = os.nice(0)
Packit Service 21c75c
            if onice:
Packit Service 21c75c
                try:
Packit Service 21c75c
                    os.nice(-onice)
Packit Service 21c75c
                except:
Packit Service 21c75c
                    onice = 0
Packit Service 21c75c
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, 'RPM transaction start.')
Packit Service 21c75c
        errors = self._ts.run(cb.callback, '')
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, 'RPM transaction over.')
Packit Service 21c75c
        # ts.run() exit codes are, hmm, "creative": None means all ok, empty
Packit Service 21c75c
        # list means some errors happened in the transaction and non-empty
Packit Service 21c75c
        # list that there were errors preventing the ts from starting...
Packit Service 21c75c
        if self.conf.reset_nice:
Packit Service 21c75c
            try:
Packit Service 21c75c
                os.nice(onice)
Packit Service 21c75c
            except:
Packit Service 21c75c
                pass
Packit Service 21c75c
        dnf.util._sync_rpm_trans_with_swdb(self._ts, self._transaction)
Packit Service 21c75c
Packit Service 21c75c
        if errors is None:
Packit Service 21c75c
            pass
Packit Service 21c75c
        elif len(errors) == 0:
Packit Service 21c75c
            # If there is no failing element it means that some "global" error
Packit Service 21c75c
            # occurred (like rpm failed to obtain the transaction lock). Just pass
Packit Service 21c75c
            # the rpm logs on to the user and raise an Error.
Packit Service 21c75c
            # If there are failing elements the problem is related to those
Packit Service 21c75c
            # elements and the Error is raised later, after saving the failure
Packit Service 21c75c
            # to the history and printing out the transaction table to user.
Packit Service 21c75c
            failed = [el for el in self._ts if el.Failed()]
Packit Service 21c75c
            if not failed:
Packit Service 21c75c
                for msg in cb.messages():
Packit Service 21c75c
                    logger.critical(_('RPM: {}').format(msg))
Packit Service 21c75c
                msg = _('Could not run transaction.')
Packit Service 21c75c
                raise dnf.exceptions.Error(msg)
Packit Service 21c75c
        else:
Packit Service 21c75c
            logger.critical(_("Transaction couldn't start:"))
Packit Service 21c75c
            for e in errors:
Packit Service 21c75c
                logger.critical(ucd(e[0]))
Packit Service 21c75c
            if self._record_history() and not self._ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST):
Packit Service 21c75c
                self.history.end(rpmdbv)
Packit Service 21c75c
            msg = _("Could not run transaction.")
Packit Service 21c75c
            raise dnf.exceptions.Error(msg)
Packit Service 21c75c
Packit Service 21c75c
        for i in ('ts_all_fn', 'ts_done_fn'):
Packit Service 21c75c
            if hasattr(cb, i):
Packit Service 21c75c
                fn = getattr(cb, i)
Packit Service 21c75c
                try:
Packit Service 21c75c
                    misc.unlink_f(fn)
Packit Service 21c75c
                except (IOError, OSError):
Packit Service 21c75c
                    msg = _('Failed to remove transaction file %s')
Packit Service 21c75c
                    logger.critical(msg, fn)
Packit Service 21c75c
Packit Service 21c75c
        # keep install_set status because _verify_transaction will clean it
Packit Service 21c75c
        self._trans_install_set = bool(self._transaction.install_set)
Packit Service 21c75c
Packit Service 21c75c
        # sync up what just happened versus what is in the rpmdb
Packit Service 21c75c
        if not self._ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST):
Packit Service 21c75c
            self._verify_transaction(cb.verify_tsi_package)
Packit Service 21c75c
Packit Service 21c75c
        return tid
Packit Service 21c75c
Packit Service 21c75c
    def _verify_transaction(self, verify_pkg_cb=None):
Packit Service 21c75c
        transaction_items = [
Packit Service 21c75c
            tsi for tsi in self.transaction
Packit Service 21c75c
            if tsi.action != libdnf.transaction.TransactionItemAction_REASON_CHANGE]
Packit Service 21c75c
        total = len(transaction_items)
Packit Service 21c75c
Packit Service 21c75c
        def display_banner(pkg, count):
Packit Service 21c75c
            count += 1
Packit Service 21c75c
            if verify_pkg_cb is not None:
Packit Service 21c75c
                verify_pkg_cb(pkg, count, total)
Packit Service 21c75c
            return count
Packit Service 21c75c
Packit Service 21c75c
        timer = dnf.logging.Timer('verify transaction')
Packit Service 21c75c
        count = 0
Packit Service 21c75c
Packit Service 21c75c
        rpmdb_sack = dnf.sack.rpmdb_sack(self)
Packit Service 21c75c
Packit Service 21c75c
        # mark group packages that are installed on the system as installed in the db
Packit Service 21c75c
        q = rpmdb_sack.query().installed()
Packit Service 21c75c
        names = set([i.name for i in q])
Packit Service 21c75c
        for ti in self.history.group:
Packit Service 21c75c
            g = ti.getCompsGroupItem()
Packit Service 21c75c
            for p in g.getPackages():
Packit Service 21c75c
                if p.getName() in names:
Packit Service 21c75c
                    p.setInstalled(True)
Packit Service 21c75c
                    p.save()
Packit Service 21c75c
Packit Service 21c75c
        # TODO: installed groups in environments
Packit Service 21c75c
Packit Service 21c75c
        # Post-transaction verification is no longer needed,
Packit Service 21c75c
        # because DNF trusts error codes returned by RPM.
Packit Service 21c75c
        # Verification banner is displayed to preserve UX.
Packit Service 21c75c
        # TODO: drop in future DNF
Packit Service 21c75c
        for tsi in transaction_items:
Packit Service 21c75c
            count = display_banner(tsi.pkg, count)
Packit Service 21c75c
Packit Service 21c75c
        rpmdbv = rpmdb_sack._rpmdb_version()
Packit Service 21c75c
        self.history.end(rpmdbv)
Packit Service 21c75c
Packit Service 21c75c
        timer()
Packit Service 21c75c
        self._trans_success = True
Packit Service 21c75c
Packit Service 21c75c
    def _download_remote_payloads(self, payloads, drpm, progress, callback_total):
Packit Service 21c75c
        lock = dnf.lock.build_download_lock(self.conf.cachedir, self.conf.exit_on_lock)
Packit Service 21c75c
        with lock:
Packit Service 21c75c
            beg_download = time.time()
Packit Service 21c75c
            est_remote_size = sum(pload.download_size for pload in payloads)
Packit Service 21c75c
            total_drpm = len(
Packit Service 21c75c
                [payload for payload in payloads if isinstance(payload, dnf.drpm.DeltaPayload)])
Packit Service 21c75c
            # compatibility part for tools that do not accept total_drpms keyword
Packit Service 21c75c
            if progress.start.__code__.co_argcount == 4:
Packit Service 21c75c
                progress.start(len(payloads), est_remote_size, total_drpms=total_drpm)
Packit Service 21c75c
            else:
Packit Service 21c75c
                progress.start(len(payloads), est_remote_size)
Packit Service 21c75c
            errors = dnf.repo._download_payloads(payloads, drpm)
Packit Service 21c75c
Packit Service 21c75c
            if errors._irrecoverable:
Packit Service 21c75c
                raise dnf.exceptions.DownloadError(errors._irrecoverable)
Packit Service 21c75c
Packit Service 21c75c
            remote_size = sum(errors._bandwidth_used(pload)
Packit Service 21c75c
                              for pload in payloads)
Packit Service 21c75c
            saving = dnf.repo._update_saving((0, 0), payloads,
Packit Service 21c75c
                                             errors._recoverable)
Packit Service 21c75c
Packit Service 21c75c
            retries = self.conf.retries
Packit Service 21c75c
            forever = retries == 0
Packit Service 21c75c
            while errors._recoverable and (forever or retries > 0):
Packit Service 21c75c
                if retries > 0:
Packit Service 21c75c
                    retries -= 1
Packit Service 21c75c
Packit Service 21c75c
                msg = _("Some packages were not downloaded. Retrying.")
Packit Service 21c75c
                logger.info(msg)
Packit Service 21c75c
Packit Service 21c75c
                remaining_pkgs = [pkg for pkg in errors._recoverable]
Packit Service 21c75c
                payloads = \
Packit Service 21c75c
                    [dnf.repo._pkg2payload(pkg, progress, dnf.repo.RPMPayload)
Packit Service 21c75c
                     for pkg in remaining_pkgs]
Packit Service 21c75c
                est_remote_size = sum(pload.download_size
Packit Service 21c75c
                                      for pload in payloads)
Packit Service 21c75c
                progress.start(len(payloads), est_remote_size)
Packit Service 21c75c
                errors = dnf.repo._download_payloads(payloads, drpm)
Packit Service 21c75c
Packit Service 21c75c
                if errors._irrecoverable:
Packit Service 21c75c
                    raise dnf.exceptions.DownloadError(errors._irrecoverable)
Packit Service 21c75c
Packit Service 21c75c
                remote_size += \
Packit Service 21c75c
                    sum(errors._bandwidth_used(pload) for pload in payloads)
Packit Service 21c75c
                saving = dnf.repo._update_saving(saving, payloads, {})
Packit Service 21c75c
Packit Service 21c75c
            if errors._recoverable:
Packit Service 21c75c
                msg = dnf.exceptions.DownloadError.errmap2str(
Packit Service 21c75c
                    errors._recoverable)
Packit Service 21c75c
                logger.info(msg)
Packit Service 21c75c
Packit Service 21c75c
        if callback_total is not None:
Packit Service 21c75c
            callback_total(remote_size, beg_download)
Packit Service 21c75c
Packit Service 21c75c
        (real, full) = saving
Packit Service 21c75c
        if real != full:
Packit Service 21c75c
            if real < full:
Packit Service 21c75c
                msg = _("Delta RPMs reduced %.1f MB of updates to %.1f MB "
Packit Service 21c75c
                        "(%d.1%% saved)")
Packit Service 21c75c
            elif real > full:
Packit Service 21c75c
                msg = _("Failed Delta RPMs increased %.1f MB of updates to %.1f MB "
Packit Service 21c75c
                        "(%d.1%% wasted)")
Packit Service 21c75c
            percent = 100 - real / full * 100
Packit Service 21c75c
            logger.info(msg, full / 1024 ** 2, real / 1024 ** 2, percent)
Packit Service 21c75c
Packit Service 21c75c
    def download_packages(self, pkglist, progress=None, callback_total=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Download the packages specified by the given list of packages.
Packit Service 21c75c
Packit Service 21c75c
        `pkglist` is a list of packages to download, `progress` is an optional
Packit Service 21c75c
         DownloadProgress instance, `callback_total` an optional callback to
Packit Service 21c75c
         output messages about the download operation.
Packit Service 21c75c
Packit Service 21c75c
        """
Packit Service 21c75c
        remote_pkgs, local_pkgs = self._select_remote_pkgs(pkglist)
Packit Service 21c75c
        if remote_pkgs:
Packit Service 21c75c
            if progress is None:
Packit Service 21c75c
                progress = dnf.callback.NullDownloadProgress()
Packit Service 21c75c
            drpm = dnf.drpm.DeltaInfo(self.sack.query().installed(),
Packit Service 21c75c
                                      progress, self.conf.deltarpm_percentage)
Packit Service 21c75c
            self._add_tempfiles([pkg.localPkg() for pkg in remote_pkgs])
Packit Service 21c75c
            payloads = [dnf.repo._pkg2payload(pkg, progress, drpm.delta_factory,
Packit Service 21c75c
                                              dnf.repo.RPMPayload)
Packit Service 21c75c
                        for pkg in remote_pkgs]
Packit Service 21c75c
            self._download_remote_payloads(payloads, drpm, progress, callback_total)
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.destdir:
Packit Service 21c75c
            for pkg in local_pkgs:
Packit Service 21c75c
                if pkg.baseurl:
Packit Service 21c75c
                    location = os.path.join(pkg.get_local_baseurl(),
Packit Service 21c75c
                                            pkg.location.lstrip("/"))
Packit Service 21c75c
                else:
Packit Service 21c75c
                    location = os.path.join(pkg.repo.pkgdir, pkg.location.lstrip("/"))
Packit Service 21c75c
                shutil.copy(location, self.conf.destdir)
Packit Service 21c75c
Packit Service 21c75c
    def add_remote_rpms(self, path_list, strict=True, progress=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        pkgs = []
Packit Service 21c75c
        if not path_list:
Packit Service 21c75c
            return pkgs
Packit Service 21c75c
        if self._goal.req_length():
Packit Service 21c75c
            raise dnf.exceptions.Error(
Packit Service 21c75c
                _("Cannot add local packages, because transaction job already exists"))
Packit Service 21c75c
        pkgs_error = []
Packit Service 21c75c
        for path in path_list:
Packit Service 21c75c
            if not os.path.exists(path) and '://' in path:
Packit Service 21c75c
                # download remote rpm to a tempfile
Packit Service 21c75c
                path = dnf.util._urlopen_progress(path, self.conf, progress)
Packit Service 21c75c
                self._add_tempfiles([path])
Packit Service 21c75c
            try:
Packit Service 21c75c
                pkgs.append(self.sack.add_cmdline_package(path))
Packit Service 21c75c
            except IOError as e:
Packit Service 21c75c
                logger.warning(e)
Packit Service 21c75c
                pkgs_error.append(path)
Packit Service 21c75c
        self._setup_excludes_includes(only_main=True)
Packit Service 21c75c
        if pkgs_error and strict:
Packit Service 21c75c
            raise IOError(_("Could not open: {}").format(' '.join(pkgs_error)))
Packit Service 21c75c
        return pkgs
Packit Service 21c75c
Packit Service 21c75c
    def _sig_check_pkg(self, po):
Packit Service 21c75c
        """Verify the GPG signature of the given package object.
Packit Service 21c75c
Packit Service 21c75c
        :param po: the package object to verify the signature of
Packit Service 21c75c
        :return: (result, error_string)
Packit Service 21c75c
           where result is::
Packit Service 21c75c
Packit Service 21c75c
              0 = GPG signature verifies ok or verification is not required.
Packit Service 21c75c
              1 = GPG verification failed but installation of the right GPG key
Packit Service 21c75c
                    might help.
Packit Service 21c75c
              2 = Fatal GPG verification error, give up.
Packit Service 21c75c
        """
Packit Service 21c75c
        if po._from_cmdline:
Packit Service 21c75c
            check = self.conf.localpkg_gpgcheck
Packit Service 21c75c
            hasgpgkey = 0
Packit Service 21c75c
        else:
Packit Service 21c75c
            repo = self.repos[po.repoid]
Packit Service 21c75c
            check = repo.gpgcheck
Packit Service 21c75c
            hasgpgkey = not not repo.gpgkey
Packit Service 21c75c
Packit Service 21c75c
        if check:
Packit Service 21c75c
            root = self.conf.installroot
Packit Service 21c75c
            ts = dnf.rpm.transaction.initReadOnlyTransaction(root)
Packit Service 21c75c
            sigresult = dnf.rpm.miscutils.checkSig(ts, po.localPkg())
Packit Service 21c75c
            localfn = os.path.basename(po.localPkg())
Packit Service 21c75c
            del ts
Packit Service 21c75c
            if sigresult == 0:
Packit Service 21c75c
                result = 0
Packit Service 21c75c
                msg = ''
Packit Service 21c75c
Packit Service 21c75c
            elif sigresult == 1:
Packit Service 21c75c
                if hasgpgkey:
Packit Service 21c75c
                    result = 1
Packit Service 21c75c
                else:
Packit Service 21c75c
                    result = 2
Packit Service 21c75c
                msg = _('Public key for %s is not installed') % localfn
Packit Service 21c75c
Packit Service 21c75c
            elif sigresult == 2:
Packit Service 21c75c
                result = 2
Packit Service 21c75c
                msg = _('Problem opening package %s') % localfn
Packit Service 21c75c
Packit Service 21c75c
            elif sigresult == 3:
Packit Service 21c75c
                if hasgpgkey:
Packit Service 21c75c
                    result = 1
Packit Service 21c75c
                else:
Packit Service 21c75c
                    result = 2
Packit Service 21c75c
                result = 1
Packit Service 21c75c
                msg = _('Public key for %s is not trusted') % localfn
Packit Service 21c75c
Packit Service 21c75c
            elif sigresult == 4:
Packit Service 21c75c
                result = 2
Packit Service 21c75c
                msg = _('Package %s is not signed') % localfn
Packit Service 21c75c
Packit Service 21c75c
        else:
Packit Service 21c75c
            result = 0
Packit Service 21c75c
            msg = ''
Packit Service 21c75c
Packit Service 21c75c
        return result, msg
Packit Service 21c75c
Packit Service 21c75c
    def package_signature_check(self, pkg):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Verify the GPG signature of the given package object.
Packit Service 21c75c
Packit Service 21c75c
        :param pkg: the package object to verify the signature of
Packit Service 21c75c
        :return: (result, error_string)
Packit Service 21c75c
           where result is::
Packit Service 21c75c
Packit Service 21c75c
              0 = GPG signature verifies ok or verification is not required.
Packit Service 21c75c
              1 = GPG verification failed but installation of the right GPG key
Packit Service 21c75c
                    might help.
Packit Service 21c75c
              2 = Fatal GPG verification error, give up.
Packit Service 21c75c
        """
Packit Service 21c75c
        return self._sig_check_pkg(pkg)
Packit Service 21c75c
Packit Service 21c75c
    def _clean_packages(self, packages):
Packit Service 21c75c
        for fn in packages:
Packit Service 21c75c
            if not os.path.exists(fn):
Packit Service 21c75c
                continue
Packit Service 21c75c
            try:
Packit Service 21c75c
                misc.unlink_f(fn)
Packit Service 21c75c
            except OSError:
Packit Service 21c75c
                logger.warning(_('Cannot remove %s'), fn)
Packit Service 21c75c
                continue
Packit Service 21c75c
            else:
Packit Service 21c75c
                logger.log(dnf.logging.DDEBUG,
Packit Service 21c75c
                           _('%s removed'), fn)
Packit Service 21c75c
Packit Service 21c75c
    def _do_package_lists(self, pkgnarrow='all', patterns=None, showdups=None,
Packit Service 21c75c
                       ignore_case=False, reponame=None):
Packit Service 21c75c
        """Return a :class:`misc.GenericHolder` containing
Packit Service 21c75c
        lists of package objects.  The contents of the lists are
Packit Service 21c75c
        specified in various ways by the arguments.
Packit Service 21c75c
Packit Service 21c75c
        :param pkgnarrow: a string specifying which types of packages
Packit Service 21c75c
           lists to produces, such as updates, installed, available,
Packit Service 21c75c
           etc.
Packit Service 21c75c
        :param patterns: a list of names or wildcards specifying
Packit Service 21c75c
           packages to list
Packit Service 21c75c
        :param showdups: whether to include duplicate packages in the
Packit Service 21c75c
           lists
Packit Service 21c75c
        :param ignore_case: whether to ignore case when searching by
Packit Service 21c75c
           package names
Packit Service 21c75c
        :param reponame: limit packages list to the given repository
Packit Service 21c75c
        :return: a :class:`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
        if showdups is None:
Packit Service 21c75c
            showdups = self.conf.showdupesfromrepos
Packit Service 21c75c
        if patterns is None:
Packit Service 21c75c
            return self._list_pattern(
Packit Service 21c75c
                pkgnarrow, patterns, showdups, ignore_case, reponame)
Packit Service 21c75c
Packit Service 21c75c
        assert not dnf.util.is_string_type(patterns)
Packit Service 21c75c
        list_fn = functools.partial(
Packit Service 21c75c
            self._list_pattern, pkgnarrow, showdups=showdups,
Packit Service 21c75c
            ignore_case=ignore_case, reponame=reponame)
Packit Service 21c75c
        if patterns is None or len(patterns) == 0:
Packit Service 21c75c
            return list_fn(None)
Packit Service 21c75c
        yghs = map(list_fn, patterns)
Packit Service 572e28
        return reduce(lambda a, b: a.merge_lists(b), yghs)
Packit Service 21c75c
Packit Service 21c75c
    def _list_pattern(self, pkgnarrow, pattern, showdups, ignore_case,
Packit Service 21c75c
                      reponame=None):
Packit Service 21c75c
        def is_from_repo(package):
Packit Service 21c75c
            """Test whether given package originates from the repository."""
Packit Service 21c75c
            if reponame is None:
Packit Service 21c75c
                return True
Packit Service 21c75c
            return self.history.repo(package) == reponame
Packit Service 21c75c
Packit Service 21c75c
        def pkgs_from_repo(packages):
Packit Service 21c75c
            """Filter out the packages which do not originate from the repo."""
Packit Service 21c75c
            return (package for package in packages if is_from_repo(package))
Packit Service 21c75c
Packit Service 21c75c
        def query_for_repo(query):
Packit Service 21c75c
            """Filter out the packages which do not originate from the repo."""
Packit Service 21c75c
            if reponame is None:
Packit Service 21c75c
                return query
Packit Service 21c75c
            return query.filter(reponame=reponame)
Packit Service 21c75c
Packit Service 21c75c
        ygh = misc.GenericHolder(iter=pkgnarrow)
Packit Service 21c75c
Packit Service 21c75c
        installed = []
Packit Service 21c75c
        available = []
Packit Service 21c75c
        reinstall_available = []
Packit Service 21c75c
        old_available = []
Packit Service 21c75c
        updates = []
Packit Service 21c75c
        obsoletes = []
Packit Service 21c75c
        obsoletesTuples = []
Packit Service 21c75c
        recent = []
Packit Service 21c75c
        extras = []
Packit Service 21c75c
        autoremove = []
Packit Service 21c75c
Packit Service 21c75c
        # do the initial pre-selection
Packit Service 21c75c
        ic = ignore_case
Packit Service 21c75c
        q = self.sack.query()
Packit Service 21c75c
        if pattern is not None:
Packit Service 21c75c
            subj = dnf.subject.Subject(pattern, ignore_case=ic)
Packit Service 21c75c
            q = subj.get_best_query(self.sack, with_provides=False)
Packit Service 21c75c
Packit Service 21c75c
        # list all packages - those installed and available:
Packit Service 21c75c
        if pkgnarrow == 'all':
Packit Service 21c75c
            dinst = {}
Packit Service 21c75c
            ndinst = {}  # Newest versions by name.arch
Packit Service 21c75c
            for po in q.installed():
Packit Service 21c75c
                dinst[po.pkgtup] = po
Packit Service 21c75c
                if showdups:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                key = (po.name, po.arch)
Packit Service 21c75c
                if key not in ndinst or po > ndinst[key]:
Packit Service 21c75c
                    ndinst[key] = po
Packit Service 21c75c
            installed = list(pkgs_from_repo(dinst.values()))
Packit Service 21c75c
Packit Service 21c75c
            avail = query_for_repo(q.available())
Packit Service 21c75c
            if not showdups:
Packit Service 21c75c
                avail = avail.filterm(latest_per_arch_by_priority=True)
Packit Service 21c75c
            for pkg in avail:
Packit Service 21c75c
                if showdups:
Packit Service 21c75c
                    if pkg.pkgtup in dinst:
Packit Service 21c75c
                        reinstall_available.append(pkg)
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        available.append(pkg)
Packit Service 21c75c
                else:
Packit Service 21c75c
                    key = (pkg.name, pkg.arch)
Packit Service 21c75c
                    if pkg.pkgtup in dinst:
Packit Service 21c75c
                        reinstall_available.append(pkg)
Packit Service 21c75c
                    elif key not in ndinst or pkg.evr_gt(ndinst[key]):
Packit Service 21c75c
                        available.append(pkg)
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        old_available.append(pkg)
Packit Service 21c75c
Packit Service 21c75c
        # produce the updates list of tuples
Packit Service 21c75c
        elif pkgnarrow == 'upgrades':
Packit Service 21c75c
            updates = query_for_repo(q).filterm(upgrades_by_priority=True)
Packit Service 21c75c
            # reduce a query to security upgrades if they are specified
Packit Service 21c75c
            updates = self._merge_update_filters(updates)
Packit Service 21c75c
            # reduce a query to latest packages
Packit Service 21c75c
            updates = updates.latest().run()
Packit Service 21c75c
Packit Service 21c75c
        # installed only
Packit Service 21c75c
        elif pkgnarrow == 'installed':
Packit Service 21c75c
            installed = list(pkgs_from_repo(q.installed()))
Packit Service 21c75c
Packit Service 21c75c
        # available in a repository
Packit Service 21c75c
        elif pkgnarrow == 'available':
Packit Service 21c75c
            if showdups:
Packit Service 21c75c
                avail = query_for_repo(q).available()
Packit Service 21c75c
                installed_dict = q.installed()._na_dict()
Packit Service 21c75c
                for avail_pkg in avail:
Packit Service 21c75c
                    key = (avail_pkg.name, avail_pkg.arch)
Packit Service 21c75c
                    installed_pkgs = installed_dict.get(key, [])
Packit Service 21c75c
                    same_ver = [pkg for pkg in installed_pkgs
Packit Service 21c75c
                                if pkg.evr == avail_pkg.evr]
Packit Service 21c75c
                    if len(same_ver) > 0:
Packit Service 21c75c
                        reinstall_available.append(avail_pkg)
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        available.append(avail_pkg)
Packit Service 21c75c
            else:
Packit Service 21c75c
                # we will only look at the latest versions of packages:
Packit Service 21c75c
                available_dict = query_for_repo(
Packit Service 21c75c
                    q).available().filterm(latest_per_arch_by_priority=True)._na_dict()
Packit Service 21c75c
                installed_dict = q.installed().latest()._na_dict()
Packit Service 21c75c
                for (name, arch) in available_dict:
Packit Service 21c75c
                    avail_pkg = available_dict[(name, arch)][0]
Packit Service 21c75c
                    inst_pkg = installed_dict.get((name, arch), [None])[0]
Packit Service 21c75c
                    if not inst_pkg or avail_pkg.evr_gt(inst_pkg):
Packit Service 21c75c
                        available.append(avail_pkg)
Packit Service 21c75c
                    elif avail_pkg.evr_eq(inst_pkg):
Packit Service 21c75c
                        reinstall_available.append(avail_pkg)
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        old_available.append(avail_pkg)
Packit Service 21c75c
Packit Service 21c75c
        # packages to be removed by autoremove
Packit Service 21c75c
        elif pkgnarrow == 'autoremove':
Packit Service 21c75c
            autoremove_q = query_for_repo(q)._unneeded(self.history.swdb)
Packit Service 21c75c
            autoremove = autoremove_q.run()
Packit Service 21c75c
Packit Service 21c75c
        # not in a repo but installed
Packit Service 21c75c
        elif pkgnarrow == 'extras':
Packit Service 21c75c
            extras = [pkg for pkg in q.extras() if is_from_repo(pkg)]
Packit Service 21c75c
Packit Service 21c75c
        # obsoleting packages (and what they obsolete)
Packit Service 21c75c
        elif pkgnarrow == 'obsoletes':
Packit Service 21c75c
            inst = q.installed()
Packit Service 21c75c
            obsoletes = query_for_repo(
Packit Service 21c75c
                self.sack.query()).filter(obsoletes_by_priority=inst)
Packit Service 21c75c
            # reduce a query to security upgrades if they are specified
Packit Service 21c75c
            obsoletes = self._merge_update_filters(obsoletes, warning=False)
Packit Service 21c75c
            obsoletesTuples = []
Packit Service 21c75c
            for new in obsoletes:
Packit Service 21c75c
                obsoleted_reldeps = new.obsoletes
Packit Service 21c75c
                obsoletesTuples.extend(
Packit Service 21c75c
                    [(new, old) for old in
Packit Service 21c75c
                     inst.filter(provides=obsoleted_reldeps)])
Packit Service 21c75c
Packit Service 21c75c
        # packages recently added to the repositories
Packit Service 21c75c
        elif pkgnarrow == 'recent':
Packit Service 21c75c
            avail = q.available()
Packit Service 21c75c
            if not showdups:
Packit Service 21c75c
                avail = avail.filterm(latest_per_arch_by_priority=True)
Packit Service 21c75c
            recent = query_for_repo(avail)._recent(self.conf.recent)
Packit Service 21c75c
Packit Service 21c75c
        ygh.installed = installed
Packit Service 21c75c
        ygh.available = available
Packit Service 21c75c
        ygh.reinstall_available = reinstall_available
Packit Service 21c75c
        ygh.old_available = old_available
Packit Service 21c75c
        ygh.updates = updates
Packit Service 21c75c
        ygh.obsoletes = obsoletes
Packit Service 21c75c
        ygh.obsoletesTuples = obsoletesTuples
Packit Service 21c75c
        ygh.recent = recent
Packit Service 21c75c
        ygh.extras = extras
Packit Service 21c75c
        ygh.autoremove = autoremove
Packit Service 21c75c
Packit Service 21c75c
        return ygh
Packit Service 21c75c
Packit Service 21c75c
    def _add_comps_trans(self, trans):
Packit Service 21c75c
        self._comps_trans += trans
Packit Service 21c75c
        return len(trans)
Packit Service 21c75c
Packit Service 21c75c
    def _remove_if_unneeded(self, query):
Packit Service 21c75c
        """
Packit Service 21c75c
        Mark to remove packages that are not required by any user installed package (reason group
Packit Service 21c75c
        or user)
Packit Service 21c75c
        :param query: dnf.query.Query() object
Packit Service 21c75c
        """
Packit Service 21c75c
        query = query.installed()
Packit Service 21c75c
        if not query:
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        unneeded_pkgs = query._safe_to_remove(self.history.swdb, debug_solver=False)
Packit Service 21c75c
        unneeded_pkgs_history = query.filter(
Packit Service 21c75c
            pkg=[i for i in query if self.history.group.is_removable_pkg(i.name)])
Packit Service 21c75c
        pkg_with_dependent_pkgs = unneeded_pkgs_history.difference(unneeded_pkgs)
Packit Service 21c75c
Packit Service 21c75c
        # mark packages with dependent packages as a dependency to allow removal with dependent
Packit Service 21c75c
        # package
Packit Service 21c75c
        for pkg in pkg_with_dependent_pkgs:
Packit Service 21c75c
            self.history.set_reason(pkg, libdnf.transaction.TransactionItemReason_DEPENDENCY)
Packit Service 21c75c
        unneeded_pkgs = unneeded_pkgs.intersection(unneeded_pkgs_history)
Packit Service 21c75c
Packit Service 21c75c
        remove_packages = query.intersection(unneeded_pkgs)
Packit Service 21c75c
        if remove_packages:
Packit Service 21c75c
            for pkg in remove_packages:
Packit Service 21c75c
                self._goal.erase(pkg, clean_deps=self.conf.clean_requirements_on_remove)
Packit Service 21c75c
Packit Service 21c75c
    def _finalize_comps_trans(self):
Packit Service 21c75c
        trans = self._comps_trans
Packit Service 21c75c
        basearch = self.conf.substitutions['basearch']
Packit Service 21c75c
Packit Service 21c75c
        def trans_upgrade(query, remove_query, comps_pkg):
Packit Service 21c75c
            sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
            sltr.set(pkg=query)
Packit Service 21c75c
            self._goal.upgrade(select=sltr)
Packit Service 21c75c
            return remove_query
Packit Service 21c75c
Packit Service 21c75c
        def trans_install(query, remove_query, comps_pkg, strict):
Packit Service 21c75c
            if self.conf.multilib_policy == "all":
Packit Service 21c75c
                if not comps_pkg.requires:
Packit Service 21c75c
                    self._install_multiarch(query, strict=strict)
Packit Service 21c75c
                else:
Packit Service 21c75c
                    # it installs only one arch for conditional packages
Packit Service 21c75c
                    installed_query = query.installed().apply()
Packit Service 21c75c
                    self._report_already_installed(installed_query)
Packit Service 21c75c
                    sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
                    sltr.set(provides="({} if {})".format(comps_pkg.name, comps_pkg.requires))
Packit Service 21c75c
                    self._goal.install(select=sltr, optional=not strict)
Packit Service 21c75c
Packit Service 21c75c
            else:
Packit Service 21c75c
                sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
                if comps_pkg.requires:
Packit Service 21c75c
                    sltr.set(provides="({} if {})".format(comps_pkg.name, comps_pkg.requires))
Packit Service 21c75c
                else:
Packit Service 21c75c
                    if self.conf.obsoletes:
Packit Service 21c75c
                        query = query.union(self.sack.query().filterm(obsoletes=query))
Packit Service 21c75c
                    sltr.set(pkg=query)
Packit Service 21c75c
                self._goal.install(select=sltr, optional=not strict)
Packit Service 21c75c
            return remove_query
Packit Service 21c75c
Packit Service 21c75c
        def trans_remove(query, remove_query, comps_pkg):
Packit Service 21c75c
            remove_query = remove_query.union(query)
Packit Service 21c75c
            return remove_query
Packit Service 21c75c
Packit Service 21c75c
        remove_query = self.sack.query().filterm(empty=True)
Packit Service 21c75c
        attr_fn = ((trans.install, functools.partial(trans_install, strict=True)),
Packit Service 21c75c
                   (trans.install_opt, functools.partial(trans_install, strict=False)),
Packit Service 21c75c
                   (trans.upgrade, trans_upgrade),
Packit Service 21c75c
                   (trans.remove, trans_remove))
Packit Service 21c75c
Packit Service 21c75c
        for (attr, fn) in attr_fn:
Packit Service 21c75c
            for comps_pkg in attr:
Packit Service 21c75c
                query_args = {'name': comps_pkg.name}
Packit Service 21c75c
                if (comps_pkg.basearchonly):
Packit Service 21c75c
                    query_args.update({'arch': basearch})
Packit Service 21c75c
                q = self.sack.query().filterm(**query_args).apply()
Packit Service 21c75c
                q.filterm(arch__neq="src")
Packit Service 21c75c
                if not q:
Packit Service 21c75c
                    package_string = comps_pkg.name
Packit Service 21c75c
                    if comps_pkg.basearchonly:
Packit Service 21c75c
                        package_string += '.' + basearch
Packit Service 21c75c
                    logger.warning(_('No match for group package "{}"').format(package_string))
Packit Service 21c75c
                    continue
Packit Service 21c75c
                remove_query = fn(q, remove_query, comps_pkg)
Packit Service 21c75c
                self._goal.group_members.add(comps_pkg.name)
Packit Service 21c75c
Packit Service 21c75c
        self._remove_if_unneeded(remove_query)
Packit Service 21c75c
Packit Service 21c75c
    def _build_comps_solver(self):
Packit Service 21c75c
        def reason_fn(pkgname):
Packit Service 21c75c
            q = self.sack.query().installed().filterm(name=pkgname)
Packit Service 21c75c
            if not q:
Packit Service 21c75c
                return None
Packit Service 21c75c
            try:
Packit Service 21c75c
                return self.history.rpm.get_reason(q[0])
Packit Service 21c75c
            except AttributeError:
Packit Service 21c75c
                return libdnf.transaction.TransactionItemReason_UNKNOWN
Packit Service 21c75c
Packit Service 21c75c
        return dnf.comps.Solver(self.history, self._comps, reason_fn)
Packit Service 21c75c
Packit Service 21c75c
    def environment_install(self, env_id, types, exclude=None, strict=True, exclude_groups=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Installs packages of environment group identified by env_id.
Packit Service 21c75c
        :param types: Types of packages to install. Either an integer as a
Packit Service 21c75c
            logical conjunction of CompsPackageType ids or a list of string
Packit Service 21c75c
            package type ids (conditional, default, mandatory, optional).
Packit Service 21c75c
        """
Packit Service 21c75c
        assert dnf.util.is_string_type(env_id)
Packit Service 21c75c
        solver = self._build_comps_solver()
Packit Service 21c75c
Packit Service 21c75c
        if not isinstance(types, int):
Packit Service 21c75c
            types = libdnf.transaction.listToCompsPackageType(types)
Packit Service 21c75c
Packit Service 21c75c
        trans = dnf.comps.install_or_skip(solver._environment_install,
Packit Service 21c75c
                                          env_id, types, exclude or set(),
Packit Service 21c75c
                                          strict, exclude_groups)
Packit Service 21c75c
        if not trans:
Packit Service 21c75c
            return 0
Packit Service 21c75c
        return self._add_comps_trans(trans)
Packit Service 21c75c
Packit Service 21c75c
    def environment_remove(self, env_id):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        assert dnf.util.is_string_type(env_id)
Packit Service 21c75c
        solver = self._build_comps_solver()
Packit Service 21c75c
        trans = solver._environment_remove(env_id)
Packit Service 21c75c
        return self._add_comps_trans(trans)
Packit Service 21c75c
Packit Service 21c75c
    def group_install(self, grp_id, pkg_types, exclude=None, strict=True):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Installs packages of selected group
Packit Service 21c75c
        :param pkg_types: Types of packages to install. Either an integer as a
Packit Service 21c75c
            logical conjunction of CompsPackageType ids or a list of string
Packit Service 21c75c
            package type ids (conditional, default, mandatory, optional).
Packit Service 21c75c
        :param exclude: list of package name glob patterns
Packit Service 21c75c
            that will be excluded from install set
Packit Service 21c75c
        :param strict: boolean indicating whether group packages that
Packit Service 21c75c
            exist but are non-installable due to e.g. dependency
Packit Service 21c75c
            issues should be skipped (False) or cause transaction to
Packit Service 21c75c
            fail to resolve (True)
Packit Service 21c75c
        """
Packit Service 21c75c
        def _pattern_to_pkgname(pattern):
Packit Service 21c75c
            if dnf.util.is_glob_pattern(pattern):
Packit Service 21c75c
                q = self.sack.query().filterm(name__glob=pattern)
Packit Service 21c75c
                return map(lambda p: p.name, q)
Packit Service 21c75c
            else:
Packit Service 21c75c
                return (pattern,)
Packit Service 21c75c
Packit Service 21c75c
        assert dnf.util.is_string_type(grp_id)
Packit Service 21c75c
        exclude_pkgnames = None
Packit Service 21c75c
        if exclude:
Packit Service 21c75c
            nested_excludes = [_pattern_to_pkgname(p) for p in exclude]
Packit Service 21c75c
            exclude_pkgnames = itertools.chain.from_iterable(nested_excludes)
Packit Service 21c75c
Packit Service 21c75c
        solver = self._build_comps_solver()
Packit Service 21c75c
Packit Service 21c75c
        if not isinstance(pkg_types, int):
Packit Service 21c75c
            pkg_types = libdnf.transaction.listToCompsPackageType(pkg_types)
Packit Service 21c75c
Packit Service 21c75c
        trans = dnf.comps.install_or_skip(solver._group_install,
Packit Service 21c75c
                                          grp_id, pkg_types, exclude_pkgnames,
Packit Service 21c75c
                                          strict)
Packit Service 21c75c
        if not trans:
Packit Service 21c75c
            return 0
Packit Service 21c75c
        if strict:
Packit Service 21c75c
            instlog = trans.install
Packit Service 21c75c
        else:
Packit Service 21c75c
            instlog = trans.install_opt
Packit Service 21c75c
        logger.debug(_("Adding packages from group '%s': %s"),
Packit Service 21c75c
                     grp_id, instlog)
Packit Service 21c75c
        return self._add_comps_trans(trans)
Packit Service 21c75c
Packit Service 21c75c
    def env_group_install(self, patterns, types, strict=True, exclude=None, exclude_groups=None):
Packit Service 21c75c
        q = CompsQuery(self.comps, self.history, CompsQuery.ENVIRONMENTS | CompsQuery.GROUPS,
Packit Service 21c75c
                       CompsQuery.AVAILABLE)
Packit Service 21c75c
        cnt = 0
Packit Service 21c75c
        done = True
Packit Service 21c75c
        for pattern in patterns:
Packit Service 21c75c
            try:
Packit Service 21c75c
                res = q.get(pattern)
Packit Service 21c75c
            except dnf.exceptions.CompsError as err:
Packit Service 21c75c
                logger.error(ucd(err))
Packit Service 21c75c
                done = False
Packit Service 21c75c
                continue
Packit Service 21c75c
            for group_id in res.groups:
Packit Service 21c75c
                if not exclude_groups or group_id not in exclude_groups:
Packit Service 21c75c
                    cnt += self.group_install(group_id, types, exclude=exclude, strict=strict)
Packit Service 21c75c
            for env_id in res.environments:
Packit Service 21c75c
                cnt += self.environment_install(env_id, types, exclude=exclude, strict=strict,
Packit Service 21c75c
                                                exclude_groups=exclude_groups)
Packit Service 21c75c
        if not done and strict:
Packit Service 21c75c
            raise dnf.exceptions.Error(_('Nothing to do.'))
Packit Service 21c75c
        return cnt
Packit Service 21c75c
Packit Service 21c75c
    def group_remove(self, grp_id):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        assert dnf.util.is_string_type(grp_id)
Packit Service 21c75c
        solver = self._build_comps_solver()
Packit Service 21c75c
        trans = solver._group_remove(grp_id)
Packit Service 21c75c
        return self._add_comps_trans(trans)
Packit Service 21c75c
Packit Service 21c75c
    def env_group_remove(self, patterns):
Packit Service 21c75c
        q = CompsQuery(self.comps, self.history,
Packit Service 21c75c
                       CompsQuery.ENVIRONMENTS | CompsQuery.GROUPS,
Packit Service 21c75c
                       CompsQuery.INSTALLED)
Packit Service 21c75c
        try:
Packit Service 21c75c
            res = q.get(*patterns)
Packit Service 21c75c
        except dnf.exceptions.CompsError as err:
Packit Service 21c75c
            logger.error("Warning: %s", ucd(err))
Packit Service 21c75c
            raise dnf.exceptions.Error(_('No groups marked for removal.'))
Packit Service 21c75c
        cnt = 0
Packit Service 21c75c
        for env in res.environments:
Packit Service 21c75c
            cnt += self.environment_remove(env)
Packit Service 21c75c
        for grp in res.groups:
Packit Service 21c75c
            cnt += self.group_remove(grp)
Packit Service 21c75c
        return cnt
Packit Service 21c75c
Packit Service 21c75c
    def env_group_upgrade(self, patterns):
Packit Service 21c75c
        q = CompsQuery(self.comps, self.history,
Packit Service 21c75c
                       CompsQuery.GROUPS | CompsQuery.ENVIRONMENTS,
Packit Service 21c75c
                       CompsQuery.INSTALLED)
Packit Service 21c75c
        group_upgraded = False
Packit Service 21c75c
        for pattern in patterns:
Packit Service 21c75c
            try:
Packit Service 21c75c
                res = q.get(pattern)
Packit Service 21c75c
            except dnf.exceptions.CompsError as err:
Packit Service 21c75c
                logger.error(ucd(err))
Packit Service 21c75c
                continue
Packit Service 21c75c
            for env in res.environments:
Packit Service 21c75c
                try:
Packit Service 21c75c
                    self.environment_upgrade(env)
Packit Service 21c75c
                    group_upgraded = True
Packit Service 21c75c
                except dnf.exceptions.CompsError as err:
Packit Service 21c75c
                    logger.error(ucd(err))
Packit Service 21c75c
                    continue
Packit Service 21c75c
            for grp in res.groups:
Packit Service 21c75c
                try:
Packit Service 21c75c
                    self.group_upgrade(grp)
Packit Service 21c75c
                    group_upgraded = True
Packit Service 21c75c
                except dnf.exceptions.CompsError as err:
Packit Service 21c75c
                    logger.error(ucd(err))
Packit Service 21c75c
                    continue
Packit Service 21c75c
        if not group_upgraded:
Packit Service 21c75c
            msg = _('No group marked for upgrade.')
Packit Service 21c75c
            raise dnf.cli.CliError(msg)
Packit Service 21c75c
Packit Service 21c75c
    def environment_upgrade(self, env_id):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        assert dnf.util.is_string_type(env_id)
Packit Service 21c75c
        solver = self._build_comps_solver()
Packit Service 21c75c
        trans = solver._environment_upgrade(env_id)
Packit Service 21c75c
        return self._add_comps_trans(trans)
Packit Service 21c75c
Packit Service 21c75c
    def group_upgrade(self, grp_id):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        assert dnf.util.is_string_type(grp_id)
Packit Service 21c75c
        solver = self._build_comps_solver()
Packit Service 21c75c
        trans = solver._group_upgrade(grp_id)
Packit Service 21c75c
        return self._add_comps_trans(trans)
Packit Service 21c75c
Packit Service 21c75c
    def _gpg_key_check(self):
Packit Service 21c75c
        """Checks for the presence of GPG keys in the rpmdb.
Packit Service 21c75c
Packit Service 21c75c
        :return: 0 if there are no GPG keys in the rpmdb, and 1 if
Packit Service 21c75c
           there are keys
Packit Service 21c75c
        """
Packit Service 21c75c
        gpgkeyschecked = self.conf.cachedir + '/.gpgkeyschecked.yum'
Packit Service 21c75c
        if os.path.exists(gpgkeyschecked):
Packit Service 21c75c
            return 1
Packit Service 21c75c
Packit Service 21c75c
        installroot = self.conf.installroot
Packit Service 21c75c
        myts = dnf.rpm.transaction.initReadOnlyTransaction(root=installroot)
Packit Service 21c75c
        myts.pushVSFlags(~(rpm._RPMVSF_NOSIGNATURES | rpm._RPMVSF_NODIGESTS))
Packit Service 21c75c
        idx = myts.dbMatch('name', 'gpg-pubkey')
Packit Service 21c75c
        keys = len(idx)
Packit Service 21c75c
        del idx
Packit Service 21c75c
        del myts
Packit Service 21c75c
Packit Service 21c75c
        if keys == 0:
Packit Service 21c75c
            return 0
Packit Service 21c75c
        else:
Packit Service 21c75c
            mydir = os.path.dirname(gpgkeyschecked)
Packit Service 21c75c
            if not os.path.exists(mydir):
Packit Service 21c75c
                os.makedirs(mydir)
Packit Service 21c75c
Packit Service 21c75c
            fo = open(gpgkeyschecked, 'w')
Packit Service 21c75c
            fo.close()
Packit Service 21c75c
            del fo
Packit Service 21c75c
            return 1
Packit Service 21c75c
Packit Service 21c75c
    def _install_multiarch(self, query, reponame=None, strict=True):
Packit Service 21c75c
        already_inst, available = self._query_matches_installed(query)
Packit Service 21c75c
        self._report_already_installed(already_inst)
Packit Service 21c75c
        for packages in available:
Packit Service 21c75c
            sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
            q = self.sack.query().filterm(pkg=packages)
Packit Service 21c75c
            if self.conf.obsoletes:
Packit Service 21c75c
                q = q.union(self.sack.query().filterm(obsoletes=q))
Packit Service 21c75c
            sltr = sltr.set(pkg=q)
Packit Service 21c75c
            if reponame is not None:
Packit Service 21c75c
                sltr = sltr.set(reponame=reponame)
Packit Service 21c75c
            self._goal.install(select=sltr, optional=(not strict))
Packit Service 21c75c
        return len(available)
Packit Service 21c75c
Packit Service 21c75c
    def _categorize_specs(self, install, exclude):
Packit Service 21c75c
        """
Packit Service 21c75c
        Categorize :param install and :param exclude list into two groups each (packages and groups)
Packit Service 21c75c
Packit Service 21c75c
        :param install: list of specs, whether packages ('foo') or groups/modules ('@bar')
Packit Service 21c75c
        :param exclude: list of specs, whether packages ('foo') or groups/modules ('@bar')
Packit Service 21c75c
        :return: categorized install and exclude specs (stored in argparse.Namespace class)
Packit Service 21c75c
Packit Service 21c75c
        To access packages use: specs.pkg_specs,
Packit Service 21c75c
        to access groups use: specs.grp_specs
Packit Service 21c75c
        """
Packit Service 21c75c
        install_specs = argparse.Namespace()
Packit Service 21c75c
        exclude_specs = argparse.Namespace()
Packit Service 21c75c
        _parse_specs(install_specs, install)
Packit Service 21c75c
        _parse_specs(exclude_specs, exclude)
Packit Service 21c75c
Packit Service 21c75c
        return install_specs, exclude_specs
Packit Service 21c75c
Packit Service 21c75c
    def _exclude_package_specs(self, exclude_specs):
Packit Service 21c75c
        glob_excludes = [exclude for exclude in exclude_specs.pkg_specs
Packit Service 21c75c
                         if dnf.util.is_glob_pattern(exclude)]
Packit Service 21c75c
        excludes = [exclude for exclude in exclude_specs.pkg_specs
Packit Service 21c75c
                    if exclude not in glob_excludes]
Packit Service 21c75c
Packit Service 21c75c
        exclude_query = self.sack.query().filter(name=excludes)
Packit Service 21c75c
        glob_exclude_query = self.sack.query().filter(name__glob=glob_excludes)
Packit Service 21c75c
Packit Service 21c75c
        self.sack.add_excludes(exclude_query)
Packit Service 21c75c
        self.sack.add_excludes(glob_exclude_query)
Packit Service 21c75c
Packit Service 21c75c
    def _expand_groups(self, group_specs):
Packit Service 21c75c
        groups = set()
Packit Service 21c75c
        q = CompsQuery(self.comps, self.history,
Packit Service 21c75c
                       CompsQuery.ENVIRONMENTS | CompsQuery.GROUPS,
Packit Service 21c75c
                       CompsQuery.AVAILABLE | CompsQuery.INSTALLED)
Packit Service 21c75c
Packit Service 21c75c
        for pattern in group_specs:
Packit Service 21c75c
            try:
Packit Service 21c75c
                res = q.get(pattern)
Packit Service 21c75c
            except dnf.exceptions.CompsError as err:
Packit Service 21c75c
                logger.error("Warning: Module or %s", ucd(err))
Packit Service 21c75c
                continue
Packit Service 21c75c
Packit Service 21c75c
            groups.update(res.groups)
Packit Service 21c75c
            groups.update(res.environments)
Packit Service 21c75c
Packit Service 21c75c
            for environment_id in res.environments:
Packit Service 21c75c
                environment = self.comps._environment_by_id(environment_id)
Packit Service 21c75c
                for group in environment.groups_iter():
Packit Service 21c75c
                    groups.add(group.id)
Packit Service 21c75c
Packit Service 21c75c
        return list(groups)
Packit Service 21c75c
Packit Service 21c75c
    def _install_groups(self, group_specs, excludes, skipped, strict=True):
Packit Service 21c75c
        for group_spec in group_specs:
Packit Service 21c75c
            try:
Packit Service 21c75c
                types = self.conf.group_package_types
Packit Service 21c75c
Packit Service 21c75c
                if '/' in group_spec:
Packit Service 21c75c
                    split = group_spec.split('/')
Packit Service 21c75c
                    group_spec = split[0]
Packit Service 21c75c
                    types = split[1].split(',')
Packit Service 21c75c
Packit Service 21c75c
                self.env_group_install([group_spec], types, strict, excludes.pkg_specs,
Packit Service 21c75c
                                       excludes.grp_specs)
Packit Service 21c75c
            except dnf.exceptions.Error:
Packit Service 21c75c
                skipped.append("@" + group_spec)
Packit Service 21c75c
Packit Service 21c75c
    def install_specs(self, install, exclude=None, reponame=None, strict=True, forms=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        if exclude is None:
Packit Service 21c75c
            exclude = []
Packit Service 21c75c
        no_match_group_specs = []
Packit Service 21c75c
        error_group_specs = []
Packit Service 21c75c
        no_match_pkg_specs = []
Packit Service 21c75c
        error_pkg_specs = []
Packit Service 21c75c
        install_specs, exclude_specs = self._categorize_specs(install, exclude)
Packit Service 21c75c
Packit Service 21c75c
        self._exclude_package_specs(exclude_specs)
Packit Service 21c75c
        for spec in install_specs.pkg_specs:
Packit Service 21c75c
            try:
Packit Service 21c75c
                self.install(spec, reponame=reponame, strict=strict, forms=forms)
Packit Service 21c75c
            except dnf.exceptions.MarkingError as e:
Packit Service 21c75c
                logger.error(str(e))
Packit Service 21c75c
                no_match_pkg_specs.append(spec)
Packit Service 21c75c
        no_match_module_specs = []
Packit Service 21c75c
        module_depsolv_errors = ()
Packit Service 21c75c
        if WITH_MODULES and install_specs.grp_specs:
Packit Service 21c75c
            try:
Packit Service 21c75c
                module_base = dnf.module.module_base.ModuleBase(self)
Packit Service 21c75c
                module_base.install(install_specs.grp_specs, strict)
Packit Service 21c75c
            except dnf.exceptions.MarkingErrors as e:
Packit Service 21c75c
                if e.no_match_group_specs:
Packit Service 21c75c
                    for e_spec in e.no_match_group_specs:
Packit Service 21c75c
                        no_match_module_specs.append(e_spec)
Packit Service 21c75c
                if e.error_group_specs:
Packit Service 21c75c
                    for e_spec in e.error_group_specs:
Packit Service 21c75c
                        error_group_specs.append("@" + e_spec)
Packit Service 21c75c
                module_depsolv_errors = e.module_depsolv_errors
Packit Service 21c75c
Packit Service 21c75c
        else:
Packit Service 21c75c
            no_match_module_specs = install_specs.grp_specs
Packit Service 21c75c
Packit Service 21c75c
        if no_match_module_specs:
Packit Service 21c75c
            self.read_comps(arch_filter=True)
Packit Service 21c75c
            exclude_specs.grp_specs = self._expand_groups(exclude_specs.grp_specs)
Packit Service 21c75c
            self._install_groups(no_match_module_specs, exclude_specs, no_match_group_specs, strict)
Packit Service 21c75c
Packit Service 21c75c
        if no_match_group_specs or error_group_specs or no_match_pkg_specs or error_pkg_specs \
Packit Service 21c75c
                or module_depsolv_errors:
Packit Service 21c75c
            raise dnf.exceptions.MarkingErrors(no_match_group_specs=no_match_group_specs,
Packit Service 21c75c
                                               error_group_specs=error_group_specs,
Packit Service 21c75c
                                               no_match_pkg_specs=no_match_pkg_specs,
Packit Service 21c75c
                                               error_pkg_specs=error_pkg_specs,
Packit Service 21c75c
                                               module_depsolv_errors=module_depsolv_errors)
Packit Service 21c75c
Packit Service 21c75c
    def install(self, pkg_spec, reponame=None, strict=True, forms=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Mark package(s) given by pkg_spec and reponame for installation."""
Packit Service 21c75c
Packit Service 21c75c
        subj = dnf.subject.Subject(pkg_spec)
Packit Service 21c75c
        solution = subj.get_best_solution(self.sack, forms=forms, with_src=False)
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.multilib_policy == "all" or subj._is_arch_specified(solution):
Packit Service 21c75c
            q = solution['query']
Packit Service 21c75c
            if reponame is not None:
Packit Service 21c75c
                q.filterm(reponame=reponame)
Packit Service 21c75c
            if not q:
Packit Service 21c75c
                self._raise_package_not_found_error(pkg_spec, forms, reponame)
Packit Service 21c75c
            return self._install_multiarch(q, reponame=reponame, strict=strict)
Packit Service 21c75c
Packit Service 21c75c
        elif self.conf.multilib_policy == "best":
Packit Service 21c75c
            sltrs = subj._get_best_selectors(self,
Packit Service 21c75c
                                             forms=forms,
Packit Service 21c75c
                                             obsoletes=self.conf.obsoletes,
Packit Service 21c75c
                                             reponame=reponame,
Packit Service 21c75c
                                             reports=True,
Packit Service 21c75c
                                             solution=solution)
Packit Service 21c75c
            if not sltrs:
Packit Service 21c75c
                self._raise_package_not_found_error(pkg_spec, forms, reponame)
Packit Service 21c75c
Packit Service 21c75c
            for sltr in sltrs:
Packit Service 21c75c
                self._goal.install(select=sltr, optional=(not strict))
Packit Service 21c75c
            return 1
Packit Service 21c75c
        return 0
Packit Service 21c75c
Packit Service 21c75c
    def package_downgrade(self, pkg, strict=False):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        if pkg._from_system:
Packit Service 21c75c
            msg = 'downgrade_package() for an installed package.'
Packit Service 21c75c
            raise NotImplementedError(msg)
Packit Service 21c75c
Packit Service 21c75c
        q = self.sack.query().installed().filterm(name=pkg.name, arch=[pkg.arch, "noarch"])
Packit Service 21c75c
        if not q:
Packit Service 21c75c
            msg = _("Package %s not installed, cannot downgrade it.")
Packit Service 21c75c
            logger.warning(msg, pkg.name)
Packit Service 21c75c
            raise dnf.exceptions.MarkingError(_('No match for argument: %s') % pkg.location, pkg.name)
Packit Service 21c75c
        elif sorted(q)[0] > pkg:
Packit Service 21c75c
            sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
            sltr.set(pkg=[pkg])
Packit Service 21c75c
            self._goal.install(select=sltr, optional=(not strict))
Packit Service 21c75c
            return 1
Packit Service 21c75c
        else:
Packit Service 21c75c
            msg = _("Package %s of lower version already installed, "
Packit Service 21c75c
                    "cannot downgrade it.")
Packit Service 21c75c
            logger.warning(msg, pkg.name)
Packit Service 21c75c
            return 0
Packit Service 21c75c
Packit Service 21c75c
    def package_install(self, pkg, strict=True):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        q = self.sack.query()._nevra(pkg.name, pkg.evr, pkg.arch)
Packit Service 21c75c
        already_inst, available = self._query_matches_installed(q)
Packit Service 21c75c
        if pkg in already_inst:
Packit Service 21c75c
            self._report_already_installed([pkg])
Packit Service 21c75c
        elif pkg not in itertools.chain.from_iterable(available):
Packit Service 21c75c
            raise dnf.exceptions.PackageNotFoundError(_('No match for argument: %s'), pkg.location)
Packit Service 21c75c
        else:
Packit Service 21c75c
            sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
            sltr.set(pkg=[pkg])
Packit Service 21c75c
            self._goal.install(select=sltr, optional=(not strict))
Packit Service 21c75c
        return 1
Packit Service 21c75c
Packit Service 21c75c
    def package_reinstall(self, pkg):
Packit Service 21c75c
        if self.sack.query().installed().filterm(name=pkg.name, evr=pkg.evr, arch=pkg.arch):
Packit Service 21c75c
            self._goal.install(pkg)
Packit Service 21c75c
            return 1
Packit Service 21c75c
        msg = _("Package %s not installed, cannot reinstall it.")
Packit Service 21c75c
        logger.warning(msg, str(pkg))
Packit Service 21c75c
        raise dnf.exceptions.MarkingError(_('No match for argument: %s') % pkg.location, pkg.name)
Packit Service 21c75c
Packit Service 21c75c
    def package_remove(self, pkg):
Packit Service 21c75c
        self._goal.erase(pkg)
Packit Service 21c75c
        return 1
Packit Service 21c75c
Packit Service 21c75c
    def package_upgrade(self, pkg):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        if pkg._from_system:
Packit Service 21c75c
            msg = 'upgrade_package() for an installed package.'
Packit Service 21c75c
            raise NotImplementedError(msg)
Packit Service 21c75c
Packit Service 21c75c
        if pkg.arch == 'src':
Packit Service 21c75c
            msg = _("File %s is a source package and cannot be updated, ignoring.")
Packit Service 21c75c
            logger.info(msg, pkg.location)
Packit Service 21c75c
            return 0
Packit Service 21c75c
Packit Service 21c75c
        q = self.sack.query().installed().filterm(name=pkg.name, arch=[pkg.arch, "noarch"])
Packit Service 21c75c
        if not q:
Packit Service 21c75c
            msg = _("Package %s not installed, cannot update it.")
Packit Service 21c75c
            logger.warning(msg, pkg.name)
Packit Service 21c75c
            raise dnf.exceptions.MarkingError(_('No match for argument: %s') % pkg.location, pkg.name)
Packit Service 21c75c
        elif sorted(q)[-1] < pkg:
Packit Service 21c75c
            sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
            sltr.set(pkg=[pkg])
Packit Service 21c75c
            self._goal.upgrade(select=sltr)
Packit Service 21c75c
            return 1
Packit Service 21c75c
        else:
Packit Service 21c75c
            msg = _("The same or higher version of %s is already installed, "
Packit Service 21c75c
                    "cannot update it.")
Packit Service 21c75c
            logger.warning(msg, pkg.name)
Packit Service 21c75c
            return 0
Packit Service 21c75c
Packit Service 21c75c
    def _upgrade_internal(self, query, obsoletes, reponame, pkg_spec=None):
Packit Service 21c75c
        installed_all = self.sack.query().installed()
Packit Service 21c75c
        q = query.intersection(self.sack.query().filterm(name=[pkg.name for pkg in installed_all]))
Packit Service 21c75c
        installed_query = q.installed()
Packit Service 21c75c
        if obsoletes:
Packit Service 21c75c
            obsoletes = self.sack.query().available().filterm(
Packit Service 21c75c
                obsoletes=installed_query.union(q.upgrades()))
Packit Service 21c75c
            # add obsoletes into transaction
Packit Service 21c75c
            q = q.union(obsoletes)
Packit Service 21c75c
        if reponame is not None:
Packit Service 21c75c
            q.filterm(reponame=reponame)
Packit Service 21c75c
        q = self._merge_update_filters(q, pkg_spec=pkg_spec)
Packit Service 21c75c
        if q:
Packit Service 21c75c
            q = q.available().union(installed_query.latest())
Packit Service 21c75c
            sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
            sltr.set(pkg=q)
Packit Service 21c75c
            self._goal.upgrade(select=sltr)
Packit Service 21c75c
        return 1
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
    def upgrade(self, pkg_spec, reponame=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        subj = dnf.subject.Subject(pkg_spec)
Packit Service 21c75c
        solution = subj.get_best_solution(self.sack)
Packit Service 21c75c
        q = solution["query"]
Packit Service 21c75c
        if q:
Packit Service 21c75c
            wildcard = dnf.util.is_glob_pattern(pkg_spec)
Packit Service 21c75c
            # wildcard shouldn't print not installed packages
Packit Service 21c75c
            # only solution with nevra.name provide packages with same name
Packit Service 21c75c
            if not wildcard and solution['nevra'] and solution['nevra'].name:
Packit Service 21c75c
                installed = self.sack.query().installed()
Packit Service 21c75c
                pkg_name = solution['nevra'].name
Packit Service 21c75c
                installed.filterm(name=pkg_name).apply()
Packit Service 21c75c
                if not installed:
Packit Service 21c75c
                    msg = _('Package %s available, but not installed.')
Packit Service 21c75c
                    logger.warning(msg, pkg_name)
Packit Service 21c75c
                    raise dnf.exceptions.PackagesNotInstalledError(
Packit Service 21c75c
                        _('No match for argument: %s') % pkg_spec, pkg_spec)
Packit Service 21c75c
                if solution['nevra'].arch and not dnf.util.is_glob_pattern(solution['nevra'].arch):
Packit Service 21c75c
                    if not installed.filter(arch=solution['nevra'].arch):
Packit Service 21c75c
                        msg = _('Package %s available, but installed for different architecture.')
Packit Service 21c75c
                        logger.warning(msg, "{}.{}".format(pkg_name, solution['nevra'].arch))
Packit Service 21c75c
            obsoletes = self.conf.obsoletes and solution['nevra'] \
Packit Service 21c75c
                        and solution['nevra'].has_just_name()
Packit Service 21c75c
            return self._upgrade_internal(q, obsoletes, reponame, pkg_spec)
Packit Service 21c75c
        raise dnf.exceptions.MarkingError(_('No match for argument: %s') % pkg_spec, pkg_spec)
Packit Service 21c75c
Packit Service 21c75c
    def upgrade_all(self, reponame=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        # provide only available packages to solver to trigger targeted upgrade
Packit Service 21c75c
        # possibilities will be ignored
Packit Service 21c75c
        # usage of selected packages will unify dnf behavior with other upgrade functions
Packit Service 21c75c
        return self._upgrade_internal(
Packit Service 21c75c
            self.sack.query(), self.conf.obsoletes, reponame, pkg_spec=None)
Packit Service 21c75c
Packit Service 21c75c
    def distro_sync(self, pkg_spec=None):
Packit Service 21c75c
        if pkg_spec is None:
Packit Service 21c75c
            self._goal.distupgrade_all()
Packit Service 21c75c
        else:
Packit Service 21c75c
            subject = dnf.subject.Subject(pkg_spec)
Packit Service 21c75c
            solution = subject.get_best_solution(self.sack, with_src=False)
Packit Service 21c75c
            solution["query"].filterm(reponame__neq=hawkey.SYSTEM_REPO_NAME)
Packit Service 21c75c
            sltrs = subject._get_best_selectors(self, solution=solution,
Packit Service 21c75c
                                                obsoletes=self.conf.obsoletes, reports=True)
Packit Service 21c75c
            if not sltrs:
Packit Service 21c75c
                logger.info(_('No package %s installed.'), pkg_spec)
Packit Service 21c75c
                return 0
Packit Service 21c75c
            for sltr in sltrs:
Packit Service 21c75c
                self._goal.distupgrade(select=sltr)
Packit Service 21c75c
        return 1
Packit Service 21c75c
Packit Service 21c75c
    def autoremove(self, forms=None, pkg_specs=None, grp_specs=None, filenames=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Removes all 'leaf' packages from the system that were originally
Packit Service 21c75c
        installed as dependencies of user-installed packages but which are
Packit Service 21c75c
        no longer required by any such package."""
Packit Service 21c75c
Packit Service 21c75c
        if any([grp_specs, pkg_specs, filenames]):
Packit Service 21c75c
            pkg_specs += filenames
Packit Service 21c75c
            done = False
Packit Service 21c75c
            # Remove groups.
Packit Service 21c75c
            if grp_specs and forms:
Packit Service 21c75c
                for grp_spec in grp_specs:
Packit Service 21c75c
                    msg = _('Not a valid form: %s')
Packit Service 21c75c
                    logger.warning(msg, grp_spec)
Packit Service 21c75c
            elif grp_specs:
Packit Service 21c75c
                self.read_comps(arch_filter=True)
Packit Service 21c75c
                if self.env_group_remove(grp_specs):
Packit Service 21c75c
                    done = True
Packit Service 21c75c
Packit Service 21c75c
            for pkg_spec in pkg_specs:
Packit Service 21c75c
                try:
Packit Service 21c75c
                    self.remove(pkg_spec, forms=forms)
Packit Service 21c75c
                except dnf.exceptions.MarkingError as e:
Packit Service 21c75c
                    logger.info(str(e))
Packit Service 21c75c
                else:
Packit Service 21c75c
                    done = True
Packit Service 21c75c
Packit Service 21c75c
            if not done:
Packit Service 21c75c
                logger.warning(_('No packages marked for removal.'))
Packit Service 21c75c
Packit Service 21c75c
        else:
Packit Service 21c75c
            pkgs = self.sack.query()._unneeded(self.history.swdb,
Packit Service 21c75c
                                               debug_solver=self.conf.debug_solver)
Packit Service 21c75c
            for pkg in pkgs:
Packit Service 21c75c
                self.package_remove(pkg)
Packit Service 21c75c
Packit Service 21c75c
    def remove(self, pkg_spec, reponame=None, forms=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Mark the specified package for removal."""
Packit Service 21c75c
Packit Service 21c75c
        matches = dnf.subject.Subject(pkg_spec).get_best_query(self.sack, forms=forms)
Packit Service 21c75c
        installed = [
Packit Service 21c75c
            pkg for pkg in matches.installed()
Packit Service 21c75c
            if reponame is None or
Packit Service 21c75c
            self.history.repo(pkg) == reponame]
Packit Service 21c75c
        if not installed:
Packit Service 21c75c
            self._raise_package_not_installed_error(pkg_spec, forms, reponame)
Packit Service 21c75c
Packit Service 21c75c
        clean_deps = self.conf.clean_requirements_on_remove
Packit Service 21c75c
        for pkg in installed:
Packit Service 21c75c
            self._goal.erase(pkg, clean_deps=clean_deps)
Packit Service 21c75c
        return len(installed)
Packit Service 21c75c
Packit Service 21c75c
    def reinstall(self, pkg_spec, old_reponame=None, new_reponame=None,
Packit Service 21c75c
                  new_reponame_neq=None, remove_na=False):
Packit Service 21c75c
        subj = dnf.subject.Subject(pkg_spec)
Packit Service 21c75c
        q = subj.get_best_query(self.sack)
Packit Service 21c75c
        installed_pkgs = [
Packit Service 21c75c
            pkg for pkg in q.installed()
Packit Service 21c75c
            if old_reponame is None or
Packit Service 21c75c
            self.history.repo(pkg) == old_reponame]
Packit Service 21c75c
Packit Service 21c75c
        available_q = q.available()
Packit Service 21c75c
        if new_reponame is not None:
Packit Service 21c75c
            available_q.filterm(reponame=new_reponame)
Packit Service 21c75c
        if new_reponame_neq is not None:
Packit Service 21c75c
            available_q.filterm(reponame__neq=new_reponame_neq)
Packit Service 21c75c
        available_nevra2pkg = dnf.query._per_nevra_dict(available_q)
Packit Service 21c75c
Packit Service 21c75c
        if not installed_pkgs:
Packit Service 21c75c
            raise dnf.exceptions.PackagesNotInstalledError(
Packit Service 21c75c
                'no package matched', pkg_spec, available_nevra2pkg.values())
Packit Service 21c75c
Packit Service 21c75c
        cnt = 0
Packit Service 21c75c
        clean_deps = self.conf.clean_requirements_on_remove
Packit Service 21c75c
        for installed_pkg in installed_pkgs:
Packit Service 21c75c
            try:
Packit Service 21c75c
                available_pkg = available_nevra2pkg[ucd(installed_pkg)]
Packit Service 21c75c
            except KeyError:
Packit Service 21c75c
                if not remove_na:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                self._goal.erase(installed_pkg, clean_deps=clean_deps)
Packit Service 21c75c
            else:
Packit Service 21c75c
                self._goal.install(available_pkg)
Packit Service 21c75c
            cnt += 1
Packit Service 21c75c
Packit Service 21c75c
        if cnt == 0:
Packit Service 21c75c
            raise dnf.exceptions.PackagesNotAvailableError(
Packit Service 21c75c
                'no package matched', pkg_spec, installed_pkgs)
Packit Service 21c75c
Packit Service 21c75c
        return cnt
Packit Service 21c75c
Packit Service 21c75c
    def downgrade(self, pkg_spec):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Mark a package to be downgraded.
Packit Service 21c75c
Packit Service 21c75c
        This is equivalent to first removing the currently installed package,
Packit Service 21c75c
        and then installing an older version.
Packit Service 21c75c
Packit Service 21c75c
        """
Packit Service 21c75c
        return self.downgrade_to(pkg_spec)
Packit Service 21c75c
Packit Service 21c75c
    def downgrade_to(self, pkg_spec, strict=False):
Packit Service 21c75c
        """Downgrade to specific version if specified otherwise downgrades
Packit Service 21c75c
        to one version lower than the package installed.
Packit Service 21c75c
        """
Packit Service 21c75c
        subj = dnf.subject.Subject(pkg_spec)
Packit Service 21c75c
        q = subj.get_best_query(self.sack)
Packit Service 21c75c
        if not q:
Packit Service 21c75c
            msg = _('No match for argument: %s') % pkg_spec
Packit Service 21c75c
            raise dnf.exceptions.PackageNotFoundError(msg, pkg_spec)
Packit Service 21c75c
        done = 0
Packit Service 21c75c
        available_pkgs = q.available()
Packit Service 21c75c
        available_pkg_names = list(available_pkgs._name_dict().keys())
Packit Service 21c75c
        q_installed = self.sack.query().installed().filterm(name=available_pkg_names)
Packit Service 21c75c
        if len(q_installed) == 0:
Packit Service 21c75c
            msg = _('Packages for argument %s available, but not installed.') % pkg_spec
Packit Service 21c75c
            raise dnf.exceptions.PackagesNotInstalledError(msg, pkg_spec, available_pkgs)
Packit Service 21c75c
        for pkg_name in q_installed._name_dict().keys():
Packit Service 21c75c
            downgrade_pkgs = available_pkgs.downgrades().filter(name=pkg_name)
Packit Service 21c75c
            if not downgrade_pkgs:
Packit Service 21c75c
                msg = _("Package %s of lowest version already installed, cannot downgrade it.")
Packit Service 21c75c
                logger.warning(msg, pkg_name)
Packit Service 21c75c
                continue
Packit Service 21c75c
            sltr = dnf.selector.Selector(self.sack)
Packit Service 21c75c
            sltr.set(pkg=downgrade_pkgs)
Packit Service 21c75c
            self._goal.install(select=sltr, optional=(not strict))
Packit Service 21c75c
            done = 1
Packit Service 21c75c
        return done
Packit Service 21c75c
Packit Service 21c75c
    def provides(self, provides_spec):
Packit Service 21c75c
        providers = self.sack.query().filterm(file__glob=provides_spec)
Packit Service 21c75c
        if providers:
Packit Service 21c75c
            return providers, [provides_spec]
Packit Service 21c75c
        providers = dnf.query._by_provides(self.sack, provides_spec)
Packit Service 21c75c
        if providers:
Packit Service 21c75c
            return providers, [provides_spec]
Packit Service 21c75c
        if provides_spec.startswith('/bin/') or provides_spec.startswith('/sbin/'):
Packit Service 21c75c
            # compatibility for packages that didn't do UsrMove
Packit Service 21c75c
            binary_provides = ['/usr' + provides_spec]
Packit Service 21c75c
        elif provides_spec.startswith('/'):
Packit Service 21c75c
            # provides_spec is a file path
Packit Service 21c75c
            return providers, [provides_spec]
Packit Service 21c75c
        else:
Packit Service 21c75c
            # suppose that provides_spec is a command, search in /usr/sbin/
Packit Service 21c75c
            binary_provides = [prefix + provides_spec
Packit Service 21c75c
                               for prefix in ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/']]
Packit Service 21c75c
        return self.sack.query().filterm(file__glob=binary_provides), binary_provides
Packit Service 21c75c
Packit Service 21c75c
    def _history_undo_operations(self, operations, first_trans, rollback=False, strict=True):
Packit Service 21c75c
        """Undo the operations on packages by their NEVRAs.
Packit Service 21c75c
Packit Service 21c75c
        :param operations: a NEVRAOperations to be undone
Packit Service 21c75c
        :param first_trans: first transaction id being undone
Packit Service 21c75c
        :param rollback: True if transaction is performing a rollback
Packit Service 21c75c
        :param strict: if True, raise an exception on any errors
Packit Service 21c75c
        """
Packit Service 21c75c
Packit Service 21c75c
        # map actions to their opposites
Packit Service 21c75c
        action_map = {
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_DOWNGRADE: None,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_DOWNGRADED: libdnf.transaction.TransactionItemAction_UPGRADE,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_INSTALL: libdnf.transaction.TransactionItemAction_REMOVE,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_OBSOLETE: None,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_OBSOLETED: libdnf.transaction.TransactionItemAction_INSTALL,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_REINSTALL: None,
Packit Service 21c75c
            # reinstalls are skipped as they are considered as no-operation from history perspective
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_REINSTALLED: None,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_REMOVE: libdnf.transaction.TransactionItemAction_INSTALL,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_UPGRADE: None,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_UPGRADED: libdnf.transaction.TransactionItemAction_DOWNGRADE,
Packit Service 21c75c
            libdnf.transaction.TransactionItemAction_REASON_CHANGE: None,
Packit Service 21c75c
        }
Packit Service 21c75c
Packit Service 21c75c
        failed = False
Packit Service 21c75c
        for ti in operations.packages():
Packit Service 21c75c
            try:
Packit Service 21c75c
                action = action_map[ti.action]
Packit Service 21c75c
            except KeyError:
Packit Service 21c75c
                raise RuntimeError(_("Action not handled: {}".format(action)))
Packit Service 21c75c
Packit Service 21c75c
            if action is None:
Packit Service 21c75c
                continue
Packit Service 21c75c
Packit Service 21c75c
            if action == libdnf.transaction.TransactionItemAction_REMOVE:
Packit Service 21c75c
                query = self.sack.query().installed().filterm(nevra_strict=str(ti))
Packit Service 21c75c
                if not query:
Packit Service 21c75c
                    logger.error(_('No package %s installed.'), ucd(str(ti)))
Packit Service 21c75c
                    failed = True
Packit Service 21c75c
                    continue
Packit Service 21c75c
            else:
Packit Service 21c75c
                query = self.sack.query().filterm(nevra_strict=str(ti))
Packit Service 21c75c
                if not query:
Packit Service 21c75c
                    logger.error(_('No package %s available.'), ucd(str(ti)))
Packit Service 21c75c
                    failed = True
Packit Service 21c75c
                    continue
Packit Service 21c75c
Packit Service 21c75c
            if action == libdnf.transaction.TransactionItemAction_REMOVE:
Packit Service 21c75c
                for pkg in query:
Packit Service 21c75c
                    self._goal.erase(pkg)
Packit Service 21c75c
            else:
Packit Service 21c75c
                selector = dnf.selector.Selector(self.sack)
Packit Service 21c75c
                selector.set(pkg=query)
Packit Service 21c75c
                self._goal.install(select=selector, optional=(not strict))
Packit Service 21c75c
Packit Service 21c75c
        if strict and failed:
Packit Service 21c75c
            raise dnf.exceptions.PackageNotFoundError(_('no package matched'))
Packit Service 21c75c
Packit Service 21c75c
    def _merge_update_filters(self, q, pkg_spec=None, warning=True):
Packit Service 21c75c
        """
Packit Service 21c75c
        Merge Queries in _update_filters and return intersection with q Query
Packit Service 21c75c
        @param q: Query
Packit Service 21c75c
        @return: Query
Packit Service 21c75c
        """
Packit Service 21c75c
        if not self._update_security_filters or not q:
Packit Service 21c75c
            return q
Packit Service 21c75c
        merged_queries = self._update_security_filters[0]
Packit Service 21c75c
        for query in self._update_security_filters[1:]:
Packit Service 21c75c
            merged_queries = merged_queries.union(query)
Packit Service 21c75c
Packit Service 21c75c
        self._update_security_filters = [merged_queries]
Packit Service 21c75c
        merged_queries = q.intersection(merged_queries)
Packit Service 21c75c
        if not merged_queries:
Packit Service 21c75c
            if warning:
Packit Service 21c75c
                q = q.upgrades()
Packit Service 21c75c
                count = len(q._name_dict().keys())
Packit Service 21c75c
                if pkg_spec is None:
Packit Service 21c75c
                    msg1 = _("No security updates needed, but {} update "
Packit Service 21c75c
                             "available").format(count)
Packit Service 21c75c
                    msg2 = _("No security updates needed, but {} updates "
Packit Service 21c75c
                             "available").format(count)
Packit Service 21c75c
                    logger.warning(P_(msg1, msg2, count))
Packit Service 21c75c
                else:
Packit Service 21c75c
                    msg1 = _('No security updates needed for "{}", but {} '
Packit Service 21c75c
                             'update available').format(pkg_spec, count)
Packit Service 21c75c
                    msg2 = _('No security updates needed for "{}", but {} '
Packit Service 21c75c
                             'updates available').format(pkg_spec, count)
Packit Service 21c75c
                    logger.warning(P_(msg1, msg2, count))
Packit Service 21c75c
        return merged_queries
Packit Service 21c75c
Packit Service 21c75c
    def _get_key_for_package(self, po, askcb=None, fullaskcb=None):
Packit Service 21c75c
        """Retrieve a key for a package. If needed, use the given
Packit Service 21c75c
        callback to prompt whether the key should be imported.
Packit Service 21c75c
Packit Service 21c75c
        :param po: the package object to retrieve the key of
Packit Service 21c75c
        :param askcb: Callback function to use to ask permission to
Packit Service 21c75c
           import a key.  The arguments *askcb* should take are the
Packit Service 21c75c
           package object, the userid of the key, and the keyid
Packit Service 21c75c
        :param fullaskcb: Callback function to use to ask permission to
Packit Service 21c75c
           import a key.  This differs from *askcb* in that it gets
Packit Service 21c75c
           passed a dictionary so that we can expand the values passed.
Packit Service 21c75c
        :raises: :class:`dnf.exceptions.Error` if there are errors
Packit Service 21c75c
           retrieving the keys
Packit Service 21c75c
        """
Packit Service 21c75c
        if po._from_cmdline:
Packit Service 21c75c
            # raise an exception, because po.repoid is not in self.repos
Packit Service 21c75c
            msg = _('Unable to retrieve a key for a commandline package: %s')
Packit Service 21c75c
            raise ValueError(msg % po)
Packit Service 21c75c
Packit Service 21c75c
        repo = self.repos[po.repoid]
Packit Service 21c75c
        key_installed = repo.id in self._repo_set_imported_gpg_keys
Packit Service 21c75c
        keyurls = [] if key_installed else repo.gpgkey
Packit Service 21c75c
Packit Service 21c75c
        def _prov_key_data(msg):
Packit Service 21c75c
            msg += _('. Failing package is: %s') % (po) + '\n '
Packit Service 21c75c
            msg += _('GPG Keys are configured as: %s') % \
Packit Service 21c75c
                    (', '.join(repo.gpgkey))
Packit Service 21c75c
            return msg
Packit Service 21c75c
Packit Service 21c75c
        user_cb_fail = False
Packit Service 21c75c
        self._repo_set_imported_gpg_keys.add(repo.id)
Packit Service 21c75c
        for keyurl in keyurls:
Packit Service 21c75c
            keys = dnf.crypto.retrieve(keyurl, repo)
Packit Service 21c75c
Packit Service 21c75c
            for info in keys:
Packit Service 21c75c
                # Check if key is already installed
Packit Service 21c75c
                if misc.keyInstalled(self._ts, info.rpm_id, info.timestamp) >= 0:
Packit Service 21c75c
                    msg = _('GPG key at %s (0x%s) is already installed')
Packit Service 21c75c
                    logger.info(msg, keyurl, info.short_id)
Packit Service 21c75c
                    continue
Packit Service 21c75c
Packit Service 21c75c
                # DNS Extension: create a key object, pass it to the verification class
Packit Service 21c75c
                # and print its result as an advice to the user.
Packit Service 21c75c
                if self.conf.gpgkey_dns_verification:
Packit Service 21c75c
                    dns_input_key = dnf.dnssec.KeyInfo.from_rpm_key_object(info.userid,
Packit Service 21c75c
                                                                           info.raw_key)
Packit Service 21c75c
                    dns_result = dnf.dnssec.DNSSECKeyVerification.verify(dns_input_key)
Packit Service 21c75c
                    logger.info(dnf.dnssec.nice_user_msg(dns_input_key, dns_result))
Packit Service 21c75c
Packit Service 21c75c
                # Try installing/updating GPG key
Packit Service 21c75c
                info.url = keyurl
Packit Service 21c75c
                dnf.crypto.log_key_import(info)
Packit Service 21c75c
                rc = False
Packit Service 21c75c
                if self.conf.assumeno:
Packit Service 21c75c
                    rc = False
Packit Service 21c75c
                elif self.conf.assumeyes:
Packit Service 21c75c
                    # DNS Extension: We assume, that the key is trusted in case it is valid,
Packit Service 21c75c
                    # its existence is explicitly denied or in case the domain is not signed
Packit Service 21c75c
                    # and therefore there is no way to know for sure (this is mainly for
Packit Service 21c75c
                    # backward compatibility)
Packit Service 21c75c
                    # FAQ:
Packit Service 21c75c
                    # * What is PROVEN_NONEXISTENCE?
Packit Service 21c75c
                    #    In DNSSEC, your domain does not need to be signed, but this state
Packit Service 21c75c
                    #    (not signed) has to be proven by the upper domain. e.g. when example.com.
Packit Service 21c75c
                    #    is not signed, com. servers have to sign the message, that example.com.
Packit Service 21c75c
                    #    does not have any signing key (KSK to be more precise).
Packit Service 21c75c
                    if self.conf.gpgkey_dns_verification:
Packit Service 21c75c
                        if dns_result in (dnf.dnssec.Validity.VALID,
Packit Service 21c75c
                                          dnf.dnssec.Validity.PROVEN_NONEXISTENCE):
Packit Service 21c75c
                            rc = True
Packit Service 21c75c
                            logger.info(dnf.dnssec.any_msg(_("The key has been approved.")))
Packit Service 21c75c
                        else:
Packit Service 21c75c
                            rc = False
Packit Service 21c75c
                            logger.info(dnf.dnssec.any_msg(_("The key has been rejected.")))
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        rc = True
Packit Service 21c75c
Packit Service 21c75c
                # grab the .sig/.asc for the keyurl, if it exists if it
Packit Service 21c75c
                # does check the signature on the key if it is signed by
Packit Service 21c75c
                # one of our ca-keys for this repo or the global one then
Packit Service 21c75c
                # rc = True else ask as normal.
Packit Service 21c75c
Packit Service 21c75c
                elif fullaskcb:
Packit Service 21c75c
                    rc = fullaskcb({"po": po, "userid": info.userid,
Packit Service 21c75c
                                    "hexkeyid": info.short_id,
Packit Service 21c75c
                                    "keyurl": keyurl,
Packit Service 21c75c
                                    "fingerprint": info.fingerprint,
Packit Service 21c75c
                                    "timestamp": info.timestamp})
Packit Service 21c75c
                elif askcb:
Packit Service 21c75c
                    rc = askcb(po, info.userid, info.short_id)
Packit Service 21c75c
Packit Service 21c75c
                if not rc:
Packit Service 21c75c
                    user_cb_fail = True
Packit Service 21c75c
                    continue
Packit Service 21c75c
Packit Service 21c75c
                # Import the key
Packit Service 21c75c
                # If rpm.RPMTRANS_FLAG_TEST in self._ts, gpg keys cannot be imported successfully
Packit Service 21c75c
                # therefore the flag was removed for import operation
Packit Service 21c75c
                test_flag = self._ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST)
Packit Service 21c75c
                if test_flag:
Packit Service 21c75c
                    orig_flags = self._ts.getTsFlags()
Packit Service 21c75c
                    self._ts.setFlags(orig_flags - rpm.RPMTRANS_FLAG_TEST)
Packit Service 21c75c
                result = self._ts.pgpImportPubkey(misc.procgpgkey(info.raw_key))
Packit Service 21c75c
                if test_flag:
Packit Service 21c75c
                    self._ts.setFlags(orig_flags)
Packit Service 21c75c
                if result != 0:
Packit Service 21c75c
                    msg = _('Key import failed (code %d)') % result
Packit Service 21c75c
                    raise dnf.exceptions.Error(_prov_key_data(msg))
Packit Service 21c75c
                logger.info(_('Key imported successfully'))
Packit Service 21c75c
                key_installed = True
Packit Service 21c75c
Packit Service 21c75c
        if not key_installed and user_cb_fail:
Packit Service 21c75c
            raise dnf.exceptions.Error(_("Didn't install any keys"))
Packit Service 21c75c
Packit Service 21c75c
        if not key_installed:
Packit Service 21c75c
            msg = _('The GPG keys listed for the "%s" repository are '
Packit Service 21c75c
                    'already installed but they are not correct for this '
Packit Service 21c75c
                    'package.\n'
Packit Service 21c75c
                    'Check that the correct key URLs are configured for '
Packit Service 21c75c
                    'this repository.') % repo.name
Packit Service 21c75c
            raise dnf.exceptions.Error(_prov_key_data(msg))
Packit Service 21c75c
Packit Service 21c75c
        # Check if the newly installed keys helped
Packit Service 21c75c
        result, errmsg = self._sig_check_pkg(po)
Packit Service 21c75c
        if result != 0:
Packit Service 21c75c
            if keyurls:
Packit Service 21c75c
                msg = _("Import of key(s) didn't help, wrong key(s)?")
Packit Service 21c75c
                logger.info(msg)
Packit Service 21c75c
            errmsg = ucd(errmsg)
Packit Service 21c75c
            raise dnf.exceptions.Error(_prov_key_data(errmsg))
Packit Service 21c75c
Packit Service 21c75c
    def package_import_key(self, pkg, askcb=None, fullaskcb=None):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """Retrieve a key for a package. If needed, use the given
Packit Service 21c75c
        callback to prompt whether the key should be imported.
Packit Service 21c75c
Packit Service 21c75c
        :param pkg: the package object to retrieve the key of
Packit Service 21c75c
        :param askcb: Callback function to use to ask permission to
Packit Service 21c75c
           import a key.  The arguments *askcb* should take are the
Packit Service 21c75c
           package object, the userid of the key, and the keyid
Packit Service 21c75c
        :param fullaskcb: Callback function to use to ask permission to
Packit Service 21c75c
           import a key.  This differs from *askcb* in that it gets
Packit Service 21c75c
           passed a dictionary so that we can expand the values passed.
Packit Service 21c75c
        :raises: :class:`dnf.exceptions.Error` if there are errors
Packit Service 21c75c
           retrieving the keys
Packit Service 21c75c
        """
Packit Service 21c75c
        self._get_key_for_package(pkg, askcb, fullaskcb)
Packit Service 21c75c
Packit Service 21c75c
    def _run_rpm_check(self):
Packit Service 21c75c
        results = []
Packit Service 21c75c
        self._ts.check()
Packit Service 21c75c
        for prob in self._ts.problems():
Packit Service 21c75c
            #  Newer rpm (4.8.0+) has problem objects, older have just strings.
Packit Service 21c75c
            #  Should probably move to using the new objects, when we can. For
Packit Service 21c75c
            # now just be compatible.
Packit Service 21c75c
            results.append(ucd(prob))
Packit Service 21c75c
Packit Service 21c75c
        return results
Packit Service 21c75c
Packit Service 21c75c
    def urlopen(self, url, repo=None, mode='w+b', **kwargs):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """
Packit Service 21c75c
        Open the specified absolute url, return a file object
Packit Service 21c75c
        which respects proxy setting even for non-repo downloads
Packit Service 21c75c
        """
Packit Service 21c75c
        return dnf.util._urlopen(url, self.conf, repo, mode, **kwargs)
Packit Service 21c75c
Packit Service 21c75c
    def _get_installonly_query(self, q=None):
Packit Service 21c75c
        if q is None:
Packit Service 21c75c
            q = self._sack.query()
Packit Service 21c75c
        installonly = q.filter(provides=self.conf.installonlypkgs)
Packit Service 21c75c
        return installonly
Packit Service 21c75c
Packit Service 21c75c
    def _report_icase_hint(self, pkg_spec):
Packit Service 21c75c
        subj = dnf.subject.Subject(pkg_spec, ignore_case=True)
Packit Service 21c75c
        solution = subj.get_best_solution(self.sack, with_nevra=True,
Packit Service 21c75c
                                          with_provides=False, with_filenames=False)
Packit Service 21c75c
        if solution['query'] and solution['nevra'] and solution['nevra'].name and \
Packit Service 21c75c
                pkg_spec != solution['query'][0].name:
Packit Service 21c75c
            logger.info(_("  * Maybe you meant: {}").format(solution['query'][0].name))
Packit Service 21c75c
Packit Service 21c75c
    def _select_remote_pkgs(self, install_pkgs):
Packit Service 21c75c
        """ Check checksum of packages from local repositories and returns list packages from remote
Packit Service 21c75c
        repositories that will be downloaded. Packages from commandline are skipped.
Packit Service 21c75c
Packit Service 21c75c
        :param install_pkgs: list of packages
Packit Service 21c75c
        :return: list of remote pkgs
Packit Service 21c75c
        """
Packit Service 21c75c
        def _verification_of_packages(pkg_list, logger_msg):
Packit Service 21c75c
            all_packages_verified = True
Packit Service 21c75c
            for pkg in pkg_list:
Packit Service 21c75c
                pkg_successfully_verified = False
Packit Service 21c75c
                try:
Packit Service 21c75c
                    pkg_successfully_verified = pkg.verifyLocalPkg()
Packit Service 21c75c
                except Exception as e:
Packit Service 21c75c
                    logger.critical(str(e))
Packit Service 21c75c
                if pkg_successfully_verified is not True:
Packit Service 21c75c
                    logger.critical(logger_msg.format(pkg, pkg.reponame))
Packit Service 21c75c
                    all_packages_verified = False
Packit Service 21c75c
Packit Service 21c75c
            return all_packages_verified
Packit Service 21c75c
Packit Service 21c75c
        remote_pkgs = []
Packit Service 21c75c
        local_repository_pkgs = []
Packit Service 21c75c
        for pkg in install_pkgs:
Packit Service 21c75c
            if pkg._is_local_pkg():
Packit Service 21c75c
                if pkg.reponame != hawkey.CMDLINE_REPO_NAME:
Packit Service 21c75c
                    local_repository_pkgs.append(pkg)
Packit Service 21c75c
            else:
Packit Service 21c75c
                remote_pkgs.append(pkg)
Packit Service 21c75c
Packit Service 21c75c
        msg = _('Package "{}" from local repository "{}" has incorrect checksum')
Packit Service 21c75c
        if not _verification_of_packages(local_repository_pkgs, msg):
Packit Service 21c75c
            raise dnf.exceptions.Error(
Packit Service 21c75c
                _("Some packages from local repository have incorrect checksum"))
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.cacheonly:
Packit Service 21c75c
            msg = _('Package "{}" from repository "{}" has incorrect checksum')
Packit Service 21c75c
            if not _verification_of_packages(remote_pkgs, msg):
Packit Service 21c75c
                raise dnf.exceptions.Error(
Packit Service 21c75c
                    _('Some packages have invalid cache, but cannot be downloaded due to '
Packit Service 21c75c
                      '"--cacheonly" option'))
Packit Service 21c75c
            remote_pkgs = []
Packit Service 21c75c
Packit Service 21c75c
        return remote_pkgs, local_repository_pkgs
Packit Service 21c75c
Packit Service 21c75c
    def _report_already_installed(self, packages):
Packit Service 21c75c
        for pkg in packages:
Packit Service 21c75c
            _msg_installed(pkg)
Packit Service 21c75c
Packit Service 21c75c
    def _raise_package_not_found_error(self, pkg_spec, forms, reponame):
Packit Service 21c75c
        all_query = self.sack.query(flags=hawkey.IGNORE_EXCLUDES)
Packit Service 21c75c
        subject = dnf.subject.Subject(pkg_spec)
Packit Service 21c75c
        solution = subject.get_best_solution(
Packit Service 21c75c
            self.sack, forms=forms, with_src=False, query=all_query)
Packit Service 21c75c
        if reponame is not None:
Packit Service 21c75c
            solution['query'].filterm(reponame=reponame)
Packit Service 21c75c
        if not solution['query']:
Packit Service 21c75c
            raise dnf.exceptions.PackageNotFoundError(_('No match for argument'), pkg_spec)
Packit Service 21c75c
        else:
Packit Service 21c75c
            with_regular_query = self.sack.query(flags=hawkey.IGNORE_REGULAR_EXCLUDES)
Packit Service 21c75c
            with_regular_query = solution['query'].intersection(with_regular_query)
Packit Service 21c75c
            # Modular filtering is applied on a package set that already has regular excludes
Packit Service 21c75c
            # filtered out. So if a package wasn't filtered out by regular excludes, it must have
Packit Service 21c75c
            # been filtered out by modularity.
Packit Service 21c75c
            if with_regular_query:
Packit Service 21c75c
                msg = _('All matches were filtered out by exclude filtering for argument')
Packit Service 21c75c
            else:
Packit Service 21c75c
                msg = _('All matches were filtered out by modular filtering for argument')
Packit Service 21c75c
            raise dnf.exceptions.PackageNotFoundError(msg, pkg_spec)
Packit Service 21c75c
Packit Service 21c75c
    def _raise_package_not_installed_error(self, pkg_spec, forms, reponame):
Packit Service 21c75c
        all_query = self.sack.query(flags=hawkey.IGNORE_EXCLUDES).installed()
Packit Service 21c75c
        subject = dnf.subject.Subject(pkg_spec)
Packit Service 21c75c
        solution = subject.get_best_solution(
Packit Service 21c75c
            self.sack, forms=forms, with_src=False, query=all_query)
Packit Service 21c75c
Packit Service 21c75c
        if not solution['query']:
Packit Service 21c75c
            raise dnf.exceptions.PackagesNotInstalledError(_('No match for argument'), pkg_spec)
Packit Service 21c75c
        if reponame is not None:
Packit Service 21c75c
            installed = [pkg for pkg in solution['query'] if self.history.repo(pkg) == reponame]
Packit Service 21c75c
        else:
Packit Service 21c75c
            installed = solution['query']
Packit Service 21c75c
        if not installed:
Packit Service 21c75c
            msg = _('All matches were installed from a different repository for argument')
Packit Service 21c75c
        else:
Packit Service 21c75c
            msg = _('All matches were filtered out by exclude filtering for argument')
Packit Service 21c75c
        raise dnf.exceptions.PackagesNotInstalledError(msg, pkg_spec)
Packit Service 21c75c
Packit Service 21c75c
    def setup_loggers(self):
Packit Service 21c75c
        # :api
Packit Service 21c75c
        """
Packit Service 21c75c
        Setup DNF file loggers based on given configuration file. The loggers are set the same
Packit Service 21c75c
        way as if DNF was run from CLI.
Packit Service 21c75c
        """
Packit Service 21c75c
        self._logging._setup_from_dnf_conf(self.conf, file_loggers_only=True)
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _msg_installed(pkg):
Packit Service 21c75c
    name = ucd(pkg)
Packit Service 21c75c
    msg = _('Package %s is already installed.')
Packit Service 21c75c
    logger.info(msg, name)