|
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 |
350571 |
from copy import deepcopy
|
|
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 |
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 |
350571 |
probfilter = functools.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 |
350571 |
# log post transaction summary
|
|
Packit Service |
350571 |
def _pto_callback(action, tsis):
|
|
Packit Service |
350571 |
msgs = []
|
|
Packit Service |
350571 |
for tsi in tsis:
|
|
Packit Service |
350571 |
msgs.append('{}: {}'.format(action, str(tsi)))
|
|
Packit Service |
350571 |
return msgs
|
|
Packit Service |
350571 |
for msg in dnf.util._post_transaction_output(self, self.transaction, _pto_callback):
|
|
Packit Service |
350571 |
logger.debug(msg)
|
|
Packit Service |
350571 |
|
|
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 |
350571 |
return functools.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 |
c8eb20 |
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 |
c8eb20 |
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 |
c8eb20 |
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 |
c8eb20 |
def _history_undo_operations(self, operations, first_trans, rollback=False, strict=True):
|
|
Packit Service |
c8eb20 |
"""Undo the operations on packages by their NEVRAs.
|
|
Packit Service |
c8eb20 |
|
|
Packit Service |
c8eb20 |
:param operations: a NEVRAOperations to be undone
|
|
Packit Service |
c8eb20 |
:param first_trans: first transaction id being undone
|
|
Packit Service |
c8eb20 |
:param rollback: True if transaction is performing a rollback
|
|
Packit Service |
c8eb20 |
:param strict: if True, raise an exception on any errors
|
|
Packit Service |
c8eb20 |
"""
|
|
Packit Service |
c8eb20 |
|
|
Packit Service |
c8eb20 |
# map actions to their opposites
|
|
Packit Service |
c8eb20 |
action_map = {
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_DOWNGRADE: None,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_DOWNGRADED: libdnf.transaction.TransactionItemAction_UPGRADE,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_INSTALL: libdnf.transaction.TransactionItemAction_REMOVE,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_OBSOLETE: None,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_OBSOLETED: libdnf.transaction.TransactionItemAction_INSTALL,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_REINSTALL: None,
|
|
Packit Service |
c8eb20 |
# reinstalls are skipped as they are considered as no-operation from history perspective
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_REINSTALLED: None,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_REMOVE: libdnf.transaction.TransactionItemAction_INSTALL,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_UPGRADE: None,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_UPGRADED: libdnf.transaction.TransactionItemAction_DOWNGRADE,
|
|
Packit Service |
c8eb20 |
libdnf.transaction.TransactionItemAction_REASON_CHANGE: None,
|
|
Packit Service |
c8eb20 |
}
|
|
Packit Service |
c8eb20 |
|
|
Packit Service |
c8eb20 |
failed = False
|
|
Packit Service |
c8eb20 |
for ti in operations.packages():
|
|
Packit Service |
c8eb20 |
try:
|
|
Packit Service |
c8eb20 |
action = action_map[ti.action]
|
|
Packit Service |
c8eb20 |
except KeyError:
|
|
Packit Service |
c8eb20 |
raise RuntimeError(_("Action not handled: {}".format(action)))
|
|
Packit Service |
c8eb20 |
|
|
Packit Service |
c8eb20 |
if action is None:
|
|
Packit Service |
c8eb20 |
continue
|
|
Packit Service |
c8eb20 |
|
|
Packit Service |
c8eb20 |
if action == libdnf.transaction.TransactionItemAction_REMOVE:
|
|
Packit Service |
c8eb20 |
query = self.sack.query().installed().filterm(nevra_strict=str(ti))
|
|
Packit Service |
c8eb20 |
if not query:
|
|
Packit Service |
c8eb20 |
logger.error(_('No package %s installed.'), ucd(str(ti)))
|
|
Packit Service |
c8eb20 |
failed = True
|
|
Packit Service |
c8eb20 |
continue
|
|
Packit Service |
c8eb20 |
else:
|
|
Packit Service |
c8eb20 |
query = self.sack.query().filterm(nevra_strict=str(ti))
|
|
Packit Service |
c8eb20 |
if not query:
|
|
Packit Service |
c8eb20 |
logger.error(_('No package %s available.'), ucd(str(ti)))
|
|
Packit Service |
c8eb20 |
failed = True
|
|
Packit Service |
c8eb20 |
continue
|
|
Packit Service |
c8eb20 |
|
|
Packit Service |
c8eb20 |
if action == libdnf.transaction.TransactionItemAction_REMOVE:
|
|
Packit Service |
c8eb20 |
for pkg in query:
|
|
Packit Service |
c8eb20 |
self._goal.erase(pkg)
|
|
Packit Service |
c8eb20 |
else:
|
|
Packit Service |
c8eb20 |
selector = dnf.selector.Selector(self.sack)
|
|
Packit Service |
c8eb20 |
selector.set(pkg=query)
|
|
Packit Service |
c8eb20 |
self._goal.install(select=selector, optional=(not strict))
|
|
Packit Service |
c8eb20 |
|
|
Packit Service |
c8eb20 |
if strict and failed:
|
|
Packit Service |
c8eb20 |
raise dnf.exceptions.PackageNotFoundError(_('no package matched'))
|
|
Packit Service |
c8eb20 |
|
|
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 |
350571 |
def _skipped_packages(self, report_problems, transaction):
|
|
Packit Service |
350571 |
"""returns set of conflicting packages and set of packages with broken dependency that would
|
|
Packit Service |
350571 |
be additionally installed when --best and --allowerasing"""
|
|
Packit Service |
350571 |
if self._goal.actions & (hawkey.INSTALL | hawkey.UPGRADE | hawkey.UPGRADE_ALL):
|
|
Packit Service |
350571 |
best = True
|
|
Packit Service |
350571 |
else:
|
|
Packit Service |
350571 |
best = False
|
|
Packit Service |
350571 |
ng = deepcopy(self._goal)
|
|
Packit Service |
350571 |
params = {"allow_uninstall": self._allow_erasing,
|
|
Packit Service |
350571 |
"force_best": best,
|
|
Packit Service |
350571 |
"ignore_weak": True}
|
|
Packit Service |
350571 |
ret = ng.run(**params)
|
|
Packit Service |
350571 |
if not ret and report_problems:
|
|
Packit Service |
350571 |
msg = dnf.util._format_resolve_problems(ng.problem_rules())
|
|
Packit Service |
350571 |
logger.warning(msg)
|
|
Packit Service |
350571 |
problem_conflicts = set(ng.problem_conflicts(available=True))
|
|
Packit Service |
350571 |
problem_dependency = set(ng.problem_broken_dependency(available=True)) - problem_conflicts
|
|
Packit Service |
350571 |
|
|
Packit Service |
350571 |
def _nevra(item):
|
|
Packit Service |
350571 |
return hawkey.NEVRA(name=item.name, epoch=item.epoch, version=item.version,
|
|
Packit Service |
350571 |
release=item.release, arch=item.arch)
|
|
Packit Service |
350571 |
|
|
Packit Service |
350571 |
# Sometimes, pkg is not in transaction item, therefore, comparing by nevra
|
|
Packit Service |
350571 |
transaction_nevras = [_nevra(tsi) for tsi in transaction]
|
|
Packit Service |
350571 |
skipped_conflicts = set(
|
|
Packit Service |
350571 |
[pkg for pkg in problem_conflicts if _nevra(pkg) not in transaction_nevras])
|
|
Packit Service |
350571 |
skipped_dependency = set(
|
|
Packit Service |
350571 |
[pkg for pkg in problem_dependency if _nevra(pkg) not in transaction_nevras])
|
|
Packit Service |
350571 |
|
|
Packit Service |
350571 |
return skipped_conflicts, skipped_dependency
|
|
Packit Service |
350571 |
|
|
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)
|