|
Packit |
6f3914 |
# Copyright 2006 Duke University
|
|
Packit |
6f3914 |
# Copyright (C) 2012-2016 Red Hat, Inc.
|
|
Packit |
6f3914 |
#
|
|
Packit |
6f3914 |
# This program is free software; you can redistribute it and/or modify
|
|
Packit |
6f3914 |
# it under the terms of the GNU General Public License as published by
|
|
Packit |
6f3914 |
# the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
6f3914 |
# (at your option) any later version.
|
|
Packit |
6f3914 |
#
|
|
Packit |
6f3914 |
# This program is distributed in the hope that it will be useful,
|
|
Packit |
6f3914 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6f3914 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
6f3914 |
# GNU Library General Public License for more details.
|
|
Packit |
6f3914 |
#
|
|
Packit |
6f3914 |
# You should have received a copy of the GNU General Public License
|
|
Packit |
6f3914 |
# along with this program; if not, write to the Free Software
|
|
Packit |
6f3914 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
6f3914 |
#
|
|
Packit |
6f3914 |
# Written by Seth Vidal
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
Classes for subcommands of the yum command line interface.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
from __future__ import print_function
|
|
Packit |
6f3914 |
from __future__ import unicode_literals
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
import libdnf
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
from dnf.cli.option_parser import OptionParser
|
|
Packit |
6f3914 |
from dnf.i18n import _, ucd
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
import argparse
|
|
Packit |
6f3914 |
import dnf.cli
|
|
Packit |
6f3914 |
import dnf.cli.demand
|
|
Packit |
6f3914 |
import dnf.const
|
|
Packit |
6f3914 |
import dnf.exceptions
|
|
Packit |
6f3914 |
import dnf.i18n
|
|
Packit |
6f3914 |
import dnf.pycomp
|
|
Packit |
6f3914 |
import dnf.transaction
|
|
Packit |
6f3914 |
import dnf.util
|
|
Packit |
6f3914 |
import functools
|
|
Packit |
6f3914 |
import logging
|
|
Packit |
6f3914 |
import operator
|
|
Packit |
6f3914 |
import os
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
logger = logging.getLogger('dnf')
|
|
Packit |
6f3914 |
_RPM_VERIFY = _("To diagnose the problem, try running: '%s'.") % \
|
|
Packit |
6f3914 |
'rpm -Va --nofiles --nodigest'
|
|
Packit |
6f3914 |
_RPM_REBUILDDB = _("You probably have corrupted RPMDB, running '%s'"
|
|
Packit |
6f3914 |
" might fix the issue.") % 'rpm --rebuilddb'
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
gpg_msg = \
|
|
Packit |
6f3914 |
_("""You have enabled checking of packages via GPG keys. This is a good thing.
|
|
Packit |
6f3914 |
However, you do not have any GPG public keys installed. You need to download
|
|
Packit |
6f3914 |
the keys for packages you wish to install and install them.
|
|
Packit |
6f3914 |
You can do that by running the command:
|
|
Packit |
6f3914 |
rpm --import public.gpg.key
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
Alternatively you can specify the url to the key you would like to use
|
|
Packit |
6f3914 |
for a repository in the 'gpgkey' option in a repository section and {prog}
|
|
Packit |
6f3914 |
will install it for you.
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
For more information contact your distribution or package provider.""")
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _checkGPGKey(base, cli):
|
|
Packit |
6f3914 |
"""Verify that there are gpg keys for the enabled repositories in the
|
|
Packit |
6f3914 |
rpm database.
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
:param base: a :class:`dnf.Base` object.
|
|
Packit |
6f3914 |
:raises: :class:`cli.CliError`
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
if not base.conf.gpgcheck:
|
|
Packit |
6f3914 |
return
|
|
Packit |
6f3914 |
if not base._gpg_key_check():
|
|
Packit |
6f3914 |
for repo in base.repos.iter_enabled():
|
|
Packit |
6f3914 |
if (repo.gpgcheck or repo.repo_gpgcheck) and not repo.gpgkey:
|
|
Packit |
6f3914 |
logger.critical("\n%s\n", gpg_msg.format(prog=dnf.util.MAIN_PROG_UPPER))
|
|
Packit |
6f3914 |
logger.critical(_("Problem repository: %s"), repo)
|
|
Packit |
6f3914 |
raise dnf.cli.CliError
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _checkEnabledRepo(base, possible_local_files=()):
|
|
Packit |
6f3914 |
"""Verify that there is at least one enabled repo.
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
:param base: a :class:`dnf.Base` object.
|
|
Packit |
6f3914 |
:param possible_local_files: the list of strings that could be a local rpms
|
|
Packit |
6f3914 |
:raises: :class:`cli.CliError`:
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
if base.repos._any_enabled():
|
|
Packit |
6f3914 |
return
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
for lfile in possible_local_files:
|
|
Packit |
6f3914 |
if lfile.endswith(".rpm") and os.path.exists(lfile):
|
|
Packit |
6f3914 |
return
|
|
Packit |
6f3914 |
scheme = dnf.pycomp.urlparse.urlparse(lfile)[0]
|
|
Packit |
6f3914 |
if scheme in ('http', 'ftp', 'file', 'https'):
|
|
Packit |
6f3914 |
return
|
|
Packit |
6f3914 |
msg = _('There are no enabled repositories in "{}".').format('", "'.join(base.conf.reposdir))
|
|
Packit |
6f3914 |
raise dnf.cli.CliError(msg)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class Command(object):
|
|
Packit |
6f3914 |
"""Abstract base class for CLI commands."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = [] # :api
|
|
Packit |
6f3914 |
summary = "" # :api
|
|
Packit |
6f3914 |
opts = None
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def __init__(self, cli):
|
|
Packit |
6f3914 |
# :api
|
|
Packit |
6f3914 |
self.cli = cli
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@property
|
|
Packit |
6f3914 |
def base(self):
|
|
Packit |
6f3914 |
# :api
|
|
Packit |
6f3914 |
return self.cli.base
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@property
|
|
Packit |
6f3914 |
def _basecmd(self):
|
|
Packit |
6f3914 |
return self.aliases[0]
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@property
|
|
Packit |
6f3914 |
def output(self):
|
|
Packit |
6f3914 |
return self.cli.base.output
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def set_argparser(self, parser):
|
|
Packit |
6f3914 |
"""Define command specific options and arguments. #:api"""
|
|
Packit |
6f3914 |
pass
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def pre_configure(self):
|
|
Packit |
6f3914 |
# :api
|
|
Packit |
6f3914 |
"""Do any command-specific pre-configuration."""
|
|
Packit |
6f3914 |
pass
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
# :api
|
|
Packit |
6f3914 |
"""Do any command-specific configuration."""
|
|
Packit |
6f3914 |
pass
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def get_error_output(self, error):
|
|
Packit |
6f3914 |
"""Get suggestions for resolving the given error."""
|
|
Packit |
6f3914 |
if isinstance(error, dnf.exceptions.TransactionCheckError):
|
|
Packit |
6f3914 |
return (_RPM_VERIFY, _RPM_REBUILDDB)
|
|
Packit |
6f3914 |
raise NotImplementedError('error not supported yet: %s' % error)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
# :api
|
|
Packit |
6f3914 |
"""Execute the command."""
|
|
Packit |
6f3914 |
pass
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_transaction(self):
|
|
Packit |
6f3914 |
"""Finalize operations post-transaction."""
|
|
Packit |
6f3914 |
pass
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class InfoCommand(Command):
|
|
Packit |
6f3914 |
"""A class containing methods needed by the cli to execute the
|
|
Packit |
6f3914 |
info command.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('info',)
|
|
Packit |
6f3914 |
summary = _('display details about a package or group of packages')
|
|
Packit |
6f3914 |
DEFAULT_PKGNARROW = 'all'
|
|
Packit |
6f3914 |
pkgnarrows = {'available', 'installed', 'extras', 'updates', 'upgrades',
|
|
Packit |
6f3914 |
'autoremove', 'recent', 'obsoletes', DEFAULT_PKGNARROW}
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@classmethod
|
|
Packit |
6f3914 |
def set_argparser(cls, parser):
|
|
Packit |
6f3914 |
narrows = parser.add_mutually_exclusive_group()
|
|
Packit |
6f3914 |
narrows.add_argument('--all', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='all', default=None,
|
|
Packit |
6f3914 |
help=_("show all packages (default)"))
|
|
Packit |
6f3914 |
narrows.add_argument('--available', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='available',
|
|
Packit |
6f3914 |
help=_("show only available packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--installed', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='installed',
|
|
Packit |
6f3914 |
help=_("show only installed packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--extras', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='extras',
|
|
Packit |
6f3914 |
help=_("show only extras packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--updates', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='upgrades',
|
|
Packit |
6f3914 |
help=_("show only upgrades packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--upgrades', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='upgrades',
|
|
Packit |
6f3914 |
help=_("show only upgrades packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--autoremove', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='autoremove',
|
|
Packit |
6f3914 |
help=_("show only autoremove packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--recent', dest='_packages_action',
|
|
Packit |
6f3914 |
action='store_const', const='recent',
|
|
Packit |
6f3914 |
help=_("show only recently changed packages"))
|
|
Packit |
6f3914 |
parser.add_argument('packages', nargs='*', metavar=_('PACKAGE'),
|
|
Packit |
6f3914 |
choices=cls.pkgnarrows, default=cls.DEFAULT_PKGNARROW,
|
|
Packit |
6f3914 |
action=OptionParser.PkgNarrowCallback,
|
|
Packit |
6f3914 |
help=_("Package name specification"))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
if self.opts._packages_action:
|
|
Packit |
6f3914 |
self.opts.packages_action = self.opts._packages_action
|
|
Packit |
6f3914 |
if self.opts.packages_action != 'installed':
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
if self.opts.obsoletes:
|
|
Packit |
6f3914 |
if self.opts._packages_action:
|
|
Packit |
6f3914 |
self.cli._option_conflict("--obsoletes", "--" + self.opts._packages_action)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
self.opts.packages_action = 'obsoletes'
|
|
Packit |
6f3914 |
if self.opts.packages_action == 'updates':
|
|
Packit |
6f3914 |
self.opts.packages_action = 'upgrades'
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
self.cli._populate_update_security_filter(self.opts, self.base.sack.query())
|
|
Packit |
6f3914 |
return self.base.output_packages('info', self.opts.packages_action,
|
|
Packit |
6f3914 |
self.opts.packages)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class ListCommand(InfoCommand):
|
|
Packit |
6f3914 |
"""A class containing methods needed by the cli to execute the
|
|
Packit |
6f3914 |
list command.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('list',)
|
|
Packit |
6f3914 |
summary = _('list a package or groups of packages')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
self.cli._populate_update_security_filter(self.opts, self.base.sack.query())
|
|
Packit |
6f3914 |
return self.base.output_packages('list', self.opts.packages_action,
|
|
Packit |
6f3914 |
self.opts.packages)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class ProvidesCommand(Command):
|
|
Packit |
6f3914 |
"""A class containing methods needed by the cli to execute the
|
|
Packit |
6f3914 |
provides command.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('provides', 'whatprovides', 'prov')
|
|
Packit |
6f3914 |
summary = _('find what package provides the given value')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@staticmethod
|
|
Packit |
6f3914 |
def set_argparser(parser):
|
|
Packit |
6f3914 |
parser.add_argument('dependency', nargs='+', metavar=_('PROVIDE'),
|
|
Packit |
6f3914 |
help=_("Provide specification to search for"))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.fresh_metadata = False
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
logger.debug(_("Searching Packages: "))
|
|
Packit |
6f3914 |
return self.base.provides(self.opts.dependency)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class CheckUpdateCommand(Command):
|
|
Packit |
6f3914 |
"""A class containing methods needed by the cli to execute the
|
|
Packit |
6f3914 |
check-update command.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('check-update', 'check-upgrade')
|
|
Packit |
6f3914 |
summary = _('check for available package upgrades')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@staticmethod
|
|
Packit |
6f3914 |
def set_argparser(parser):
|
|
Packit |
6f3914 |
parser.add_argument('--changelogs', dest='changelogs',
|
|
Packit |
6f3914 |
default=False, action='store_true',
|
|
Packit |
6f3914 |
help=_('show changelogs before update'))
|
|
Packit |
6f3914 |
parser.add_argument('packages', nargs='*', metavar=_('PACKAGE'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.plugin_filtering_enabled = True
|
|
Packit |
6f3914 |
if self.opts.changelogs:
|
|
Packit |
6f3914 |
demands.changelogs = True
|
|
Packit |
6f3914 |
_checkEnabledRepo(self.base)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit Service |
e4a73a |
query = self.base.sack.query().upgrades()
|
|
Packit |
6f3914 |
if self.base.conf.obsoletes:
|
|
Packit |
6f3914 |
obsoleted = query.union(self.base.sack.query().installed())
|
|
Packit |
6f3914 |
obsoletes = self.base.sack.query().filter(obsoletes=obsoleted)
|
|
Packit |
6f3914 |
query = query.union(obsoletes)
|
|
Packit |
6f3914 |
self.cli._populate_update_security_filter(self.opts, query, cmp_type="gte")
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
found = self.base.check_updates(self.opts.packages, print_=True,
|
|
Packit |
6f3914 |
changelogs=self.opts.changelogs)
|
|
Packit |
6f3914 |
if found:
|
|
Packit |
6f3914 |
self.cli.demands.success_exit_status = 100
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if self.base.conf.autocheck_running_kernel:
|
|
Packit |
6f3914 |
self.cli._check_running_kernel()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class RepoPkgsCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the repository-packages command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class CheckUpdateSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the info sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('check-update',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
found = self.base.check_updates(self.opts.pkg_specs,
|
|
Packit |
6f3914 |
self.reponame, print_=True)
|
|
Packit |
6f3914 |
if found:
|
|
Packit |
6f3914 |
self.cli.demands.success_exit_status = 100
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class InfoSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the info sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('info',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
if self.opts._pkg_specs_action:
|
|
Packit |
6f3914 |
self.opts.pkg_specs_action = self.opts._pkg_specs_action
|
|
Packit |
6f3914 |
if self.opts.pkg_specs_action != 'installed':
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
if self.opts.obsoletes:
|
|
Packit |
6f3914 |
if self.opts._pkg_specs_action:
|
|
Packit |
6f3914 |
self.cli._option_conflict("--obsoletes", "--" + self.opts._pkg_specs_action)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
self.opts.pkg_specs_action = 'obsoletes'
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
self.cli._populate_update_security_filter(self.opts, self.base.sack.query())
|
|
Packit |
6f3914 |
self.base.output_packages('info', self.opts.pkg_specs_action,
|
|
Packit |
6f3914 |
self.opts.pkg_specs, self.reponame)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class InstallSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the install sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('install',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.resolving = True
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
self.cli._populate_update_security_filter(self.opts, self.base.sack.query())
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
done = False
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not self.opts.pkg_specs:
|
|
Packit |
6f3914 |
# Install all packages.
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.install('*', self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
logger.info(_('No package available.'))
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# Install packages.
|
|
Packit |
6f3914 |
for pkg_spec in self.opts.pkg_specs:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.install(pkg_spec, self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError as e:
|
|
Packit |
6f3914 |
msg = '{}: {}'.format(e.value, self.base.output.term.bold(pkg_spec))
|
|
Packit |
6f3914 |
logger.info(msg)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not done:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(_('No packages marked for install.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class ListSubCommand(InfoSubCommand):
|
|
Packit |
6f3914 |
"""Implementation of the list sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('list',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
self.cli._populate_update_security_filter(self.opts, self.base.sack.query())
|
|
Packit |
6f3914 |
self.base.output_packages('list', self.opts.pkg_specs_action,
|
|
Packit |
6f3914 |
self.opts.pkg_specs, self.reponame)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class MoveToSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the move-to sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('move-to',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.resolving = True
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
done = False
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not self.opts.pkg_specs:
|
|
Packit |
6f3914 |
# Reinstall all packages.
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.reinstall('*', new_reponame=self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
logger.info(_('No package installed.'))
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotAvailableError:
|
|
Packit |
6f3914 |
logger.info(_('No package available.'))
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
assert False, 'Only the above marking errors are expected.'
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# Reinstall packages.
|
|
Packit |
6f3914 |
for pkg_spec in self.opts.pkg_specs:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.reinstall(pkg_spec, new_reponame=self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
msg = _('No match for argument: %s')
|
|
Packit |
6f3914 |
logger.info(msg, pkg_spec)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotAvailableError as err:
|
|
Packit |
6f3914 |
for pkg in err.packages:
|
|
Packit |
6f3914 |
xmsg = ''
|
|
Packit |
6f3914 |
pkgrepo = self.base.history.repo(pkg)
|
|
Packit |
6f3914 |
if pkgrepo:
|
|
Packit |
6f3914 |
xmsg = _(' (from %s)') % pkgrepo
|
|
Packit |
6f3914 |
msg = _('Installed package %s%s not available.')
|
|
Packit |
6f3914 |
logger.info(msg, self.output.term.bold(pkg), xmsg)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
assert False, \
|
|
Packit |
6f3914 |
'Only the above marking errors are expected.'
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not done:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(_('Nothing to do.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class ReinstallOldSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the reinstall-old sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('reinstall-old',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.resolving = True
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
done = False
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not self.opts.pkg_specs:
|
|
Packit |
6f3914 |
# Reinstall all packages.
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.reinstall('*', self.reponame, self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
msg = _('No package installed from the repository.')
|
|
Packit |
6f3914 |
logger.info(msg)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotAvailableError:
|
|
Packit |
6f3914 |
logger.info(_('No package available.'))
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
assert False, 'Only the above marking errors are expected.'
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# Reinstall packages.
|
|
Packit |
6f3914 |
for pkg_spec in self.opts.pkg_specs:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.reinstall(pkg_spec, self.reponame,
|
|
Packit |
6f3914 |
self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
msg = _('No match for argument: %s')
|
|
Packit |
6f3914 |
logger.info(msg, pkg_spec)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotAvailableError as err:
|
|
Packit |
6f3914 |
for pkg in err.packages:
|
|
Packit |
6f3914 |
xmsg = ''
|
|
Packit |
6f3914 |
pkgrepo = self.base.history.repo(pkg)
|
|
Packit |
6f3914 |
if pkgrepo:
|
|
Packit |
6f3914 |
xmsg = _(' (from %s)') % pkgrepo
|
|
Packit |
6f3914 |
msg = _('Installed package %s%s not available.')
|
|
Packit |
6f3914 |
logger.info(msg, self.output.term.bold(pkg), xmsg)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
assert False, \
|
|
Packit |
6f3914 |
'Only the above marking errors are expected.'
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not done:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(_('Nothing to do.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class ReinstallSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the reinstall sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('reinstall',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def __init__(self, cli):
|
|
Packit |
6f3914 |
"""Initialize the command."""
|
|
Packit |
6f3914 |
super(RepoPkgsCommand.ReinstallSubCommand, self).__init__(cli)
|
|
Packit |
6f3914 |
self.wrapped_commands = (RepoPkgsCommand.ReinstallOldSubCommand(cli),
|
|
Packit |
6f3914 |
RepoPkgsCommand.MoveToSubCommand(cli))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
self.cli.demands.available_repos = True
|
|
Packit |
6f3914 |
for command in self.wrapped_commands:
|
|
Packit |
6f3914 |
command.opts = self.opts
|
|
Packit |
6f3914 |
command.reponame = self.reponame
|
|
Packit |
6f3914 |
command.configure()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
for command in self.wrapped_commands:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
command.run_on_repo()
|
|
Packit |
6f3914 |
except dnf.exceptions.Error:
|
|
Packit |
6f3914 |
continue
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
break
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(_('No packages marked for reinstall.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class RemoveOrDistroSyncSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the remove-or-distro-sync sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('remove-or-distro-sync',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.resolving = True
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _replace(self, pkg_spec, reponame):
|
|
Packit |
6f3914 |
"""Synchronize a package with another repository or remove it."""
|
|
Packit |
6f3914 |
self.cli.base.sack.disable_repo(reponame)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
subject = dnf.subject.Subject(pkg_spec)
|
|
Packit |
6f3914 |
matches = subject.get_best_query(self.cli.base.sack)
|
|
Packit |
6f3914 |
history = self.cli.base.history
|
|
Packit |
6f3914 |
installed = [
|
|
Packit |
6f3914 |
pkg for pkg in matches.installed()
|
|
Packit |
6f3914 |
if history.repo(pkg) == reponame]
|
|
Packit |
6f3914 |
if not installed:
|
|
Packit |
6f3914 |
raise dnf.exceptions.PackagesNotInstalledError(
|
|
Packit |
6f3914 |
'no package matched', pkg_spec)
|
|
Packit |
6f3914 |
available = matches.available()
|
|
Packit |
6f3914 |
clean_deps = self.cli.base.conf.clean_requirements_on_remove
|
|
Packit |
6f3914 |
for package in installed:
|
|
Packit |
6f3914 |
if available.filter(name=package.name, arch=package.arch):
|
|
Packit |
6f3914 |
self.cli.base._goal.distupgrade(package)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
self.cli.base._goal.erase(package, clean_deps=clean_deps)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
done = False
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not self.opts.pkg_specs:
|
|
Packit |
6f3914 |
# Sync all packages.
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self._replace('*', self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
msg = _('No package installed from the repository.')
|
|
Packit |
6f3914 |
logger.info(msg)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# Reinstall packages.
|
|
Packit |
6f3914 |
for pkg_spec in self.opts.pkg_specs:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self._replace(pkg_spec, self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
msg = _('No match for argument: %s')
|
|
Packit |
6f3914 |
logger.info(msg, pkg_spec)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not done:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(_('Nothing to do.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class RemoveOrReinstallSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the remove-or-reinstall sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('remove-or-reinstall',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.resolving = True
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
done = False
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not self.opts.pkg_specs:
|
|
Packit |
6f3914 |
# Reinstall all packages.
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.reinstall('*', old_reponame=self.reponame,
|
|
Packit |
6f3914 |
new_reponame_neq=self.reponame,
|
|
Packit |
6f3914 |
remove_na=True)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
msg = _('No package installed from the repository.')
|
|
Packit |
6f3914 |
logger.info(msg)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
assert False, 'Only the above marking error is expected.'
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# Reinstall packages.
|
|
Packit |
6f3914 |
for pkg_spec in self.opts.pkg_specs:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.reinstall(
|
|
Packit |
6f3914 |
pkg_spec, old_reponame=self.reponame,
|
|
Packit |
6f3914 |
new_reponame_neq=self.reponame, remove_na=True)
|
|
Packit |
6f3914 |
except dnf.exceptions.PackagesNotInstalledError:
|
|
Packit |
6f3914 |
msg = _('No match for argument: %s')
|
|
Packit |
6f3914 |
logger.info(msg, pkg_spec)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
assert False, 'Only the above marking error is expected.'
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not done:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(_('Nothing to do.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class RemoveSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the remove sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('remove',)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.allow_erasing = True
|
|
Packit |
6f3914 |
demands.available_repos = False
|
|
Packit |
6f3914 |
demands.resolving = True
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
done = False
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not self.opts.pkg_specs:
|
|
Packit |
6f3914 |
# Remove all packages.
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.remove('*', self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
msg = _('No package installed from the repository.')
|
|
Packit |
6f3914 |
logger.info(msg)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# Remove packages.
|
|
Packit |
6f3914 |
for pkg_spec in self.opts.pkg_specs:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.remove(pkg_spec, self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError as e:
|
|
Packit |
6f3914 |
logger.info(str(e))
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not done:
|
|
Packit |
6f3914 |
logger.warning(_('No packages marked for removal.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class UpgradeSubCommand(Command):
|
|
Packit |
6f3914 |
"""Implementation of the upgrade sub-command."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('upgrade', 'upgrade-to')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.resolving = True
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run_on_repo(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *cli_args*."""
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
done = False
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not self.opts.pkg_specs:
|
|
Packit |
6f3914 |
# Update all packages.
|
|
Packit |
6f3914 |
self.base.upgrade_all(self.reponame)
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# Update packages.
|
|
Packit |
6f3914 |
for pkg_spec in self.opts.pkg_specs:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.base.upgrade(pkg_spec, self.reponame)
|
|
Packit |
6f3914 |
except dnf.exceptions.MarkingError:
|
|
Packit |
6f3914 |
logger.info(_('No match for argument: %s'), pkg_spec)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
done = True
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if not done:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(_('No packages marked for upgrade.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
SUBCMDS = {CheckUpdateSubCommand, InfoSubCommand, InstallSubCommand,
|
|
Packit |
6f3914 |
ListSubCommand, MoveToSubCommand, ReinstallOldSubCommand,
|
|
Packit |
6f3914 |
ReinstallSubCommand, RemoveOrDistroSyncSubCommand,
|
|
Packit |
6f3914 |
RemoveOrReinstallSubCommand, RemoveSubCommand,
|
|
Packit |
6f3914 |
UpgradeSubCommand}
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('repository-packages',
|
|
Packit |
6f3914 |
'repo-pkgs', 'repo-packages', 'repository-pkgs')
|
|
Packit |
6f3914 |
summary = _('run commands on top of all packages in given repository')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def __init__(self, cli):
|
|
Packit |
6f3914 |
"""Initialize the command."""
|
|
Packit |
6f3914 |
super(RepoPkgsCommand, self).__init__(cli)
|
|
Packit |
6f3914 |
subcmd_objs = (subcmd(cli) for subcmd in self.SUBCMDS)
|
|
Packit |
6f3914 |
self.subcmd = None
|
|
Packit |
6f3914 |
self._subcmd_name2obj = {
|
|
Packit |
6f3914 |
alias: subcmd for subcmd in subcmd_objs for alias in subcmd.aliases}
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def set_argparser(self, parser):
|
|
Packit |
6f3914 |
narrows = parser.add_mutually_exclusive_group()
|
|
Packit |
6f3914 |
narrows.add_argument('--all', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='all', default=None,
|
|
Packit |
6f3914 |
help=_("show all packages (default)"))
|
|
Packit |
6f3914 |
narrows.add_argument('--available', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='available',
|
|
Packit |
6f3914 |
help=_("show only available packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--installed', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='installed',
|
|
Packit |
6f3914 |
help=_("show only installed packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--extras', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='extras',
|
|
Packit |
6f3914 |
help=_("show only extras packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--updates', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='upgrades',
|
|
Packit |
6f3914 |
help=_("show only upgrades packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--upgrades', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='upgrades',
|
|
Packit |
6f3914 |
help=_("show only upgrades packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--autoremove', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='autoremove',
|
|
Packit |
6f3914 |
help=_("show only autoremove packages"))
|
|
Packit |
6f3914 |
narrows.add_argument('--recent', dest='_pkg_specs_action',
|
|
Packit |
6f3914 |
action='store_const', const='recent',
|
|
Packit |
6f3914 |
help=_("show only recently changed packages"))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
parser.add_argument(
|
|
Packit |
6f3914 |
'reponame', nargs=1, action=OptionParser._RepoCallbackEnable,
|
|
Packit |
6f3914 |
metavar=_('REPOID'), help=_("Repository ID"))
|
|
Packit |
6f3914 |
subcommand_choices = [subcmd.aliases[0] for subcmd in self.SUBCMDS]
|
|
Packit |
6f3914 |
parser.add_argument('subcmd', nargs=1, metavar="SUBCOMMAND",
|
|
Packit |
6f3914 |
choices=subcommand_choices, help=", ".join(subcommand_choices))
|
|
Packit |
6f3914 |
DEFAULT_PKGNARROW = 'all'
|
|
Packit |
6f3914 |
pkgnarrows = {DEFAULT_PKGNARROW, 'installed', 'available',
|
|
Packit |
6f3914 |
'autoremove', 'extras', 'obsoletes', 'recent',
|
|
Packit |
6f3914 |
'upgrades'}
|
|
Packit |
6f3914 |
parser.add_argument('pkg_specs', nargs='*', metavar=_('PACKAGE'),
|
|
Packit |
6f3914 |
choices=pkgnarrows, default=DEFAULT_PKGNARROW,
|
|
Packit |
6f3914 |
action=OptionParser.PkgNarrowCallback,
|
|
Packit |
6f3914 |
help=_("Package specification"))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
"""Verify whether the command can run with given arguments."""
|
|
Packit |
6f3914 |
# Check sub-command.
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
self.subcmd = self._subcmd_name2obj[self.opts.subcmd[0]]
|
|
Packit |
6f3914 |
except (dnf.cli.CliError, KeyError) as e:
|
|
Packit |
6f3914 |
self.cli.optparser.print_usage()
|
|
Packit |
6f3914 |
raise dnf.cli.CliError
|
|
Packit |
6f3914 |
self.subcmd.opts = self.opts
|
|
Packit |
6f3914 |
self.subcmd.reponame = self.opts.reponame[0]
|
|
Packit |
6f3914 |
self.subcmd.configure()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
"""Execute the command with respect to given arguments *extcmds*."""
|
|
Packit |
6f3914 |
self.subcmd.run_on_repo()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class HelpCommand(Command):
|
|
Packit |
6f3914 |
"""A class containing methods needed by the cli to execute the
|
|
Packit |
6f3914 |
help command.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('help',)
|
|
Packit |
6f3914 |
summary = _('display a helpful usage message')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@staticmethod
|
|
Packit |
6f3914 |
def set_argparser(parser):
|
|
Packit |
6f3914 |
parser.add_argument('cmd', nargs='?', metavar=_('COMMAND'),
|
|
Packit |
6f3914 |
help=_("{prog} command to get help for").format(
|
|
Packit |
6f3914 |
prog=dnf.util.MAIN_PROG_UPPER))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
if (not self.opts.cmd
|
|
Packit |
6f3914 |
or self.opts.cmd not in self.cli.cli_commands):
|
|
Packit |
6f3914 |
self.cli.optparser.print_help()
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
command = self.cli.cli_commands[self.opts.cmd]
|
|
Packit |
6f3914 |
self.cli.optparser.print_help(command(self))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class HistoryCommand(Command):
|
|
Packit |
6f3914 |
"""A class containing methods needed by the cli to execute the
|
|
Packit |
6f3914 |
history command.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('history', 'hist')
|
|
Packit |
6f3914 |
summary = _('display, or use, the transaction history')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
_CMDS = ['list', 'info', 'redo', 'undo', 'rollback', 'userinstalled']
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
transaction_ids = set()
|
|
Packit |
6f3914 |
merged_transaction_ids = set()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@staticmethod
|
|
Packit |
6f3914 |
def set_argparser(parser):
|
|
Packit |
6f3914 |
parser.add_argument('transactions_action', nargs='?', metavar="COMMAND",
|
|
Packit |
6f3914 |
help="Available commands: {} (default), {}".format(
|
|
Packit |
6f3914 |
HistoryCommand._CMDS[0],
|
|
Packit |
6f3914 |
", ".join(HistoryCommand._CMDS[1:])))
|
|
Packit |
6f3914 |
parser.add_argument('transactions', nargs='*', metavar="TRANSACTION",
|
|
Packit |
6f3914 |
help="Transaction ID (<number>, 'last' or 'last-<number>' "
|
|
Packit |
6f3914 |
"for one transaction, <transaction-id>..<transaction-id> "
|
|
Packit |
6f3914 |
"for range)")
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit |
6f3914 |
if not self.opts.transactions_action:
|
|
Packit |
6f3914 |
# no positional argument given
|
|
Packit |
6f3914 |
self.opts.transactions_action = self._CMDS[0]
|
|
Packit |
6f3914 |
elif self.opts.transactions_action not in self._CMDS:
|
|
Packit |
6f3914 |
# first positional argument is not a command
|
|
Packit |
6f3914 |
self.opts.transactions.insert(0, self.opts.transactions_action)
|
|
Packit |
6f3914 |
self.opts.transactions_action = self._CMDS[0]
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
require_one_transaction_id = False
|
|
Packit |
6f3914 |
require_one_transaction_id_msg = _("Found more than one transaction ID.\n"
|
|
Packit |
6f3914 |
"'{}' requires one transaction ID or package name."
|
|
Packit |
6f3914 |
).format(self.opts.transactions_action)
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
if self.opts.transactions_action in ['redo', 'undo', 'rollback']:
|
|
Packit |
6f3914 |
demands.root_user = True
|
|
Packit |
6f3914 |
require_one_transaction_id = True
|
|
Packit |
6f3914 |
if not self.opts.transactions:
|
|
Packit |
6f3914 |
msg = _('No transaction ID or package name given.')
|
|
Packit |
6f3914 |
logger.critical(msg)
|
|
Packit |
6f3914 |
raise dnf.cli.CliError(msg)
|
|
Packit |
6f3914 |
elif len(self.opts.transactions) > 1:
|
|
Packit |
6f3914 |
logger.critical(require_one_transaction_id_msg)
|
|
Packit |
6f3914 |
raise dnf.cli.CliError(require_one_transaction_id_msg)
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
_checkGPGKey(self.base, self.cli)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
demands.fresh_metadata = False
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
if not os.access(self.base.history.path, os.R_OK):
|
|
Packit |
6f3914 |
msg = _("You don't have access to the history DB.")
|
|
Packit |
6f3914 |
logger.critical(msg)
|
|
Packit |
6f3914 |
raise dnf.cli.CliError(msg)
|
|
Packit |
6f3914 |
self.transaction_ids = self._args2transaction_ids(self.merged_transaction_ids,
|
|
Packit |
6f3914 |
require_one_transaction_id,
|
|
Packit |
6f3914 |
require_one_transaction_id_msg)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def get_error_output(self, error):
|
|
Packit |
6f3914 |
"""Get suggestions for resolving the given error."""
|
|
Packit |
6f3914 |
if isinstance(error, dnf.exceptions.TransactionCheckError):
|
|
Packit |
6f3914 |
if self.opts.transactions_action == 'undo':
|
|
Packit |
6f3914 |
id_, = self.opts.transactions
|
|
Packit |
6f3914 |
return (_('Cannot undo transaction %s, doing so would result '
|
|
Packit |
6f3914 |
'in an inconsistent package database.') % id_,)
|
|
Packit |
6f3914 |
elif self.opts.transactions_action == 'rollback':
|
|
Packit |
6f3914 |
id_, = (self.opts.transactions if self.opts.transactions[0] != 'force'
|
|
Packit |
6f3914 |
else self.opts.transactions[1:])
|
|
Packit |
6f3914 |
return (_('Cannot rollback transaction %s, doing so would '
|
|
Packit |
6f3914 |
'result in an inconsistent package database.') % id_,)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
return Command.get_error_output(self, error)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _hcmd_redo(self, extcmds):
|
|
Packit |
6f3914 |
old = self.base.history_get_transaction(extcmds)
|
|
Packit |
6f3914 |
if old is None:
|
|
Packit |
6f3914 |
return 1, ['Failed history redo']
|
|
Packit |
6f3914 |
tm = dnf.util.normalize_time(old.beg_timestamp)
|
|
Packit |
6f3914 |
print('Repeating transaction %u, from %s' % (old.tid, tm))
|
|
Packit |
6f3914 |
self.output.historyInfoCmdPkgsAltered(old)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
for i in old.packages():
|
|
Packit |
6f3914 |
pkgs = list(self.base.sack.query().filter(nevra=str(i), reponame=i.from_repo))
|
|
Packit |
6f3914 |
if i.action in dnf.transaction.FORWARD_ACTIONS:
|
|
Packit |
6f3914 |
if not pkgs:
|
|
Packit |
6f3914 |
logger.info(_('No package %s available.'),
|
|
Packit |
6f3914 |
self.output.term.bold(ucd(str(i))))
|
|
Packit |
6f3914 |
return 1, ['An operation cannot be redone']
|
|
Packit |
6f3914 |
pkg = pkgs[0]
|
|
Packit |
6f3914 |
self.base.install(str(pkg))
|
|
Packit |
6f3914 |
elif i.action == libdnf.transaction.TransactionItemAction_REMOVE:
|
|
Packit |
6f3914 |
if not pkgs:
|
|
Packit |
6f3914 |
# package was removed already, we can skip removing it again
|
|
Packit |
6f3914 |
continue
|
|
Packit |
6f3914 |
pkg = pkgs[0]
|
|
Packit |
6f3914 |
self.base.remove(str(pkg))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
self.base.resolve()
|
|
Packit |
6f3914 |
self.base.do_transaction()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _hcmd_undo(self, extcmds):
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
return self.base.history_undo_transaction(extcmds[0])
|
|
Packit |
6f3914 |
except dnf.exceptions.Error as err:
|
|
Packit |
6f3914 |
return 1, [str(err)]
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _hcmd_rollback(self, extcmds):
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
return self.base.history_rollback_transaction(extcmds[0])
|
|
Packit |
6f3914 |
except dnf.exceptions.Error as err:
|
|
Packit |
6f3914 |
return 1, [str(err)]
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _hcmd_userinstalled(self):
|
|
Packit |
6f3914 |
"""Execute history userinstalled command."""
|
|
Packit |
6f3914 |
pkgs = tuple(self.base.iter_userinstalled())
|
|
Packit |
6f3914 |
return self.output.listPkgs(pkgs, 'Packages installed by user', 'nevra')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _args2transaction_ids(self, merged_ids=set(),
|
|
Packit |
6f3914 |
require_one_trans_id=False, require_one_trans_id_msg=''):
|
|
Packit |
6f3914 |
"""Convert commandline arguments to transaction ids"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def str2transaction_id(s):
|
|
Packit |
6f3914 |
if s == 'last':
|
|
Packit |
6f3914 |
s = '0'
|
|
Packit |
6f3914 |
elif s.startswith('last-'):
|
|
Packit |
6f3914 |
s = s[4:]
|
|
Packit |
6f3914 |
transaction_id = int(s)
|
|
Packit |
6f3914 |
if transaction_id <= 0:
|
|
Packit |
6f3914 |
transaction_id += self.output.history.last().tid
|
|
Packit |
6f3914 |
return transaction_id
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
transaction_ids = set()
|
|
Packit |
6f3914 |
for t in self.opts.transactions:
|
|
Packit |
6f3914 |
if '..' in t:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
begin_transaction_id, end_transaction_id = t.split('..', 2)
|
|
Packit |
6f3914 |
except ValueError:
|
|
Packit |
6f3914 |
logger.critical(
|
|
Packit |
6f3914 |
_("Invalid transaction ID range definition '{}'.\n"
|
|
Packit |
6f3914 |
"Use '<transaction-id>..<transaction-id>'."
|
|
Packit |
6f3914 |
).format(t))
|
|
Packit |
6f3914 |
raise dnf.cli.CliError
|
|
Packit |
6f3914 |
cant_convert_msg = _("Can't convert '{}' to transaction ID.\n"
|
|
Packit |
6f3914 |
"Use '<number>', 'last', 'last-<number>'.")
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
begin_transaction_id = str2transaction_id(begin_transaction_id)
|
|
Packit |
6f3914 |
except ValueError:
|
|
Packit |
6f3914 |
logger.critical(_(cant_convert_msg).format(begin_transaction_id))
|
|
Packit |
6f3914 |
raise dnf.cli.CliError
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
end_transaction_id = str2transaction_id(end_transaction_id)
|
|
Packit |
6f3914 |
except ValueError:
|
|
Packit |
6f3914 |
logger.critical(_(cant_convert_msg).format(end_transaction_id))
|
|
Packit |
6f3914 |
raise dnf.cli.CliError
|
|
Packit |
6f3914 |
if require_one_trans_id and begin_transaction_id != end_transaction_id:
|
|
Packit |
6f3914 |
logger.critical(require_one_trans_id_msg)
|
|
Packit |
6f3914 |
raise dnf.cli.CliError
|
|
Packit |
6f3914 |
if begin_transaction_id > end_transaction_id:
|
|
Packit |
6f3914 |
begin_transaction_id, end_transaction_id = \
|
|
Packit |
6f3914 |
end_transaction_id, begin_transaction_id
|
|
Packit |
6f3914 |
merged_ids.add((begin_transaction_id, end_transaction_id))
|
|
Packit |
6f3914 |
transaction_ids.update(range(begin_transaction_id, end_transaction_id + 1))
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
transaction_ids.add(str2transaction_id(t))
|
|
Packit |
6f3914 |
except ValueError:
|
|
Packit |
6f3914 |
# not a transaction id, assume it's package name
|
|
Packit |
6f3914 |
transact_ids_from_pkgname = self.output.history.search([t])
|
|
Packit |
6f3914 |
if transact_ids_from_pkgname:
|
|
Packit |
6f3914 |
transaction_ids.update(transact_ids_from_pkgname)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
msg = _("No transaction which manipulates package '{}' was found."
|
|
Packit |
6f3914 |
).format(t)
|
|
Packit |
6f3914 |
if require_one_trans_id:
|
|
Packit |
6f3914 |
logger.critical(msg)
|
|
Packit |
6f3914 |
raise dnf.cli.CliError
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
logger.info(msg)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
return sorted(transaction_ids, reverse=True)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
vcmd = self.opts.transactions_action
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
ret = None
|
|
Packit |
6f3914 |
if vcmd == 'list' and (self.transaction_ids or not self.opts.transactions):
|
|
Packit |
6f3914 |
ret = self.output.historyListCmd(self.transaction_ids)
|
|
Packit |
6f3914 |
elif vcmd == 'info' and (self.transaction_ids or not self.opts.transactions):
|
|
Packit |
6f3914 |
ret = self.output.historyInfoCmd(self.transaction_ids, self.opts.transactions,
|
|
Packit |
6f3914 |
self.merged_transaction_ids)
|
|
Packit |
6f3914 |
elif vcmd == 'undo':
|
|
Packit |
6f3914 |
ret = self._hcmd_undo(self.transaction_ids)
|
|
Packit |
6f3914 |
elif vcmd == 'redo':
|
|
Packit |
6f3914 |
ret = self._hcmd_redo(self.transaction_ids)
|
|
Packit |
6f3914 |
elif vcmd == 'rollback':
|
|
Packit |
6f3914 |
ret = self._hcmd_rollback(self.transaction_ids)
|
|
Packit |
6f3914 |
elif vcmd == 'userinstalled':
|
|
Packit |
6f3914 |
ret = self._hcmd_userinstalled()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if ret is None:
|
|
Packit |
6f3914 |
return
|
|
Packit |
6f3914 |
(code, strs) = ret
|
|
Packit |
6f3914 |
if code == 2:
|
|
Packit |
6f3914 |
self.cli.demands.resolving = True
|
|
Packit |
6f3914 |
elif code != 0:
|
|
Packit |
6f3914 |
raise dnf.exceptions.Error(strs[0])
|