Beispiel #1
0
    def _parse_commands(self):
        """Read :attr:`self.cmds` and parse them out to make sure that
        the requested base command and argument makes any sense at
        all.  This function will also set :attr:`self.base.basecmd` and
        :attr:`self.extcmds`.
        """
        self.logger.debug('dnf version: %s', dnf.const.VERSION)
        self.logger.log(dnf.logging.SUBDEBUG,
                        'Command: %s', self.cmdstring)
        self.logger.log(dnf.logging.SUBDEBUG,
                        'Installroot: %s', self.base.conf.installroot)
        if len(self.base.conf.commands) == 0 and len(self.base.cmds) < 1:
            self.base.cmds = self.base.conf.commands
        else:
            self.base.conf.commands = self.base.cmds
        if len(self.base.cmds) < 1:
            self.logger.critical(_('You need to give some command'))
            self.print_usage()
            raise CliError

        basecmd = self.base.cmds[0] # our base command
        command_cls = self.cli_commands.get(basecmd)
        if command_cls is None:
            self.logger.critical(_('No such command: %s. Please use %s --help'),
                                  basecmd, sys.argv[0])
            raise CliError
        self.command = command_cls(self)

        (base, ext) = self.command.canonical(self.base.cmds)
        self.base.basecmd, self.base.extcmds = (base, ext)
        self.logger.log(dnf.logging.SUBDEBUG, 'Base command: %s', base)
        self.logger.log(dnf.logging.SUBDEBUG, 'Extra commands: %s', ext)
Beispiel #2
0
    def _config(self, args=None):
        def print_or_set(key, val, conf):
            if val:
                setattr(conf, key, val)
            else:
                try:
                    print('{}: {}'.format(key, getattr(conf, str(key))))
                except:
                    logger.warning(_('Unsupported key value.'))

        if not args or len(args) > 2:
            logger.warning(_('Missing config or key value.'))

        key = args[0]
        val = args[1] if len(args) == 2 else None
        period = key.find('.')
        if period != -1:
            repo_name = key[:period]
            key = key[period+1:]
            repos = self.base.repos.get_matching(repo_name)
            for repo in repos:
                print_or_set(key, val, repo)
            if not repos:
                logger.warning(_('Could not find repository: %s'),
                               repo_name)
        else:
            print_or_set(key, val, self.base.conf)
 def __init__(self, no_match_group_specs=(), error_group_specs=(), no_match_pkg_specs=(),
              error_pkg_specs=(), module_depsolv_errors=()):
     """Initialize the marking error instance."""
     msg = _("Problems in request:")
     if (no_match_pkg_specs):
         msg += "\n" + _("missing packages: ") + ", ".join(no_match_pkg_specs)
     if (error_pkg_specs):
         msg += "\n" + _("broken packages: ") + ", ".join(error_pkg_specs)
     if (no_match_group_specs):
         msg += "\n" + _("missing groups or modules: ") + ", ".join(no_match_group_specs)
     if (error_group_specs):
         msg += "\n" + _("broken groups or modules: ") + ", ".join(error_group_specs)
     if (module_depsolv_errors):
         msg_mod = dnf.util._format_resolve_problems(module_depsolv_errors[0])
         if module_depsolv_errors[1] == \
                 libdnf.module.ModulePackageContainer.ModuleErrorType_ERROR_IN_DEFAULTS:
             msg += "\n" + "\n".join([P_('Modular dependency problem with Defaults:',
                                         'Modular dependency problems with Defaults:',
                                         len(module_depsolv_errors)),
                                     msg_mod])
         else:
             msg += "\n" + "\n".join([P_('Modular dependency problem:',
                                         'Modular dependency problems:',
                                         len(module_depsolv_errors)),
                                     msg_mod])
     super(MarkingErrors, self).__init__(msg)
     self.no_match_group_specs = no_match_group_specs
     self.error_group_specs = error_group_specs
     self.no_match_pkg_specs = no_match_pkg_specs
     self.error_pkg_specs = error_pkg_specs
     self.module_depsolv_errors = module_depsolv_errors
Beispiel #4
0
    def run(self, extcmds):
        pkg_specs, filenames = self.parse_extcmds(extcmds)

        # Reinstall files.
        local_pkgs = map(self.base.add_remote_rpm, filenames)
        results = map(self.base.package_install, local_pkgs)
        done = functools.reduce(operator.or_, results, False)

        # Reinstall packages.
        for pkg_spec in pkg_specs:
            try:
                self.base.reinstall(pkg_spec)
            except dnf.exceptions.PackagesNotInstalledError:
                logger.info(_('No match for argument: %s'), pkg_spec)
            except dnf.exceptions.PackagesNotAvailableError as err:
                for pkg in err.packages:
                    xmsg = ''
                    yumdb_info = self.base.yumdb.get_package(pkg)
                    if 'from_repo' in yumdb_info:
                        xmsg = _(' (from %s)') % yumdb_info.from_repo
                    msg = _('Installed package %s%s%s%s not available.')
                    logger.info(msg, self.base.output.term.MODE['bold'], pkg,
                                self.base.output.term.MODE['normal'], xmsg)
            except dnf.exceptions.MarkingError:
                assert False, 'Only the above marking errors are expected.'
            else:
                done = True

        if not done:
            raise dnf.exceptions.Error(_('Nothing to do.'))
Beispiel #5
0
def cli_run(cli, base):
    # Try to open the current directory to see if we have
    # read and execute access. If not, chdir to /
    try:
        f = open(".")
    except IOError as e:
        if e.errno == errno.EACCES:
            logger.critical(_('No read/execute access in current directory, moving to /'))
            os.chdir("/")
    else:
        f.close()

    try:
        cli.run()
    except dnf.exceptions.LockError:
        raise
    except (IOError, OSError) as e:
        return ex_IOError(e)

    if cli.demands.resolving:
        try:
            ret = resolving(cli, base)
        except dnf.exceptions.DepsolveError as e:
            ex_Error(e)
            if not cli.demands.allow_erasing:
                logger.info(_("(try to add '%s' to command line to"
                              " replace conflicting packages)"),
                            "--allowerasing")
            raise
        if ret:
            return ret

    cli.command.run_transaction()
    return cli.demands.success_exit_status
Beispiel #6
0
    def history_undo_transaction(self, extcmd):
        """Undo given transaction."""
        old = self.history_get_transaction((extcmd,))
        if old is None:
            return 1, ['Failed history undo']

        tm = time.ctime(old.beg_timestamp)
        print("Undoing transaction %u, from %s" % (old.tid, tm))
        self.output.historyInfoCmdPkgsAltered(old)  # :todo

        history = dnf.history.open_history(self.history)  # :todo

        hibeg = self.output.term.MODE['bold']
        hiend = self.output.term.MODE['normal']
        try:
            self.history_undo_operations(history.transaction_nevra_ops(old.tid))
        except dnf.exceptions.PackagesNotInstalledError as err:
            logger.info(_('No package %s%s%s installed.'),
                             hibeg, ucd(err.pkg_spec), hiend)
            return 1, ['An operation cannot be undone']
        except dnf.exceptions.PackagesNotAvailableError as err:
            logger.info(_('No package %s%s%s available.'),
                             hibeg, ucd(err.pkg_spec), hiend)
            return 1, ['An operation cannot be undone']
        except dnf.exceptions.MarkingError:
            assert False
        else:
            return 2, ["Undoing transaction %u" % (old.tid,)]
Beispiel #7
0
    def run(self):

        # Reinstall files.
        done = False
        for pkg in self.base.add_remote_rpms(self.opts.filenames, strict=False):
            try:
                self.base.package_reinstall(pkg)
            except dnf.exceptions.MarkingError as e:
                logger.info(e)
            else:
                done = True

        # Reinstall packages.
        for pkg_spec in self.opts.pkg_specs + ['@' + x for x in self.opts.grp_specs]:
            try:
                self.base.reinstall(pkg_spec)
            except dnf.exceptions.PackagesNotInstalledError:
                logger.info(_('No match for argument: %s'), pkg_spec)
            except dnf.exceptions.PackagesNotAvailableError as err:
                for pkg in err.packages:
                    xmsg = ''
                    yumdb_info = self.base._yumdb.get_package(pkg)
                    if 'from_repo' in yumdb_info:
                        xmsg = _(' (from %s)') % yumdb_info.from_repo
                    msg = _('Installed package %s%s%s%s not available.')
                    logger.info(msg, self.base.output.term.MODE['bold'], pkg,
                                self.base.output.term.MODE['normal'], xmsg)
            except dnf.exceptions.MarkingError:
                assert False, 'Only the above marking errors are expected.'
            else:
                done = True

        if not done:
            raise dnf.exceptions.Error(_('Nothing to do.'))
Beispiel #8
0
    def errorSummary(self, errstring):
        """Parse the error string for 'interesting' errors which can
        be grouped, such as disk space issues.

        :param errstring: the error string
        :return: a string containing a summary of the errors
        """
        summary = ''
        # do disk space report first
        p = re.compile('needs (\d+)MB on the (\S+) filesystem')
        disk = {}
        for m in p.finditer(errstring):
            if m.group(2) not in disk:
                disk[m.group(2)] = int(m.group(1))
            if disk[m.group(2)] < int(m.group(1)):
                disk[m.group(2)] = int(m.group(1))

        if disk:
            summary += _('Disk Requirements:\n')
            for k in disk:
                summary += P_('  At least %dMB more space needed on the %s filesystem.\n', '  At least %dMB more space needed on the %s filesystem.\n', disk[k]) % (disk[k], k)

        # TODO: simplify the dependency errors?

        # Fixup the summary
        summary = _('Error Summary\n-------------\n') + summary

        return summary
Beispiel #9
0
    def _history_get_transactions(self, extcmds):
        if not extcmds:
            logger.critical(_('No transaction ID given'))
            return None

        tids = []
        last = None
        for extcmd in extcmds:
            try:
                id_or_offset = self.transaction_id_or_offset(extcmd)
            except ValueError:
                logger.critical(_('Bad transaction ID given'))
                return None

            if id_or_offset < 0:
                if last is None:
                    cto = False
                    last = self.history.last(complete_transactions_only=cto)
                    if last is None:
                        logger.critical(_('Bad transaction ID given'))
                        return None
                tids.append(str(last.tid + id_or_offset + 1))
            else:
                tids.append(str(id_or_offset))

        old = self.history.old(tids)
        if not old:
            logger.critical(_('Not found given transaction ID'))
            return None
        return old
Beispiel #10
0
Datei: cli.py Projekt: dmnks/dnf
    def _parse_commands(self):
        """Check that the requested CLI command exists."""

        if len(self.base.cmds) < 1:
            logger.critical(_('You need to give some command'))
            self.print_usage()
            raise CliError

        basecmd = self.base.cmds[0] # our base command
        command_cls = self.cli_commands.get(basecmd)
        if command_cls is None:
            logger.critical(_('No such command: %s. Please use %s --help'),
                            basecmd, sys.argv[0])
            if self.base.conf.plugins:
                logger.info(_("It could be a DNF plugin command, "
                            "try: \"dnf install 'dnf-command(%s)'\""), basecmd)
            else:
                logger.info(_("It could be a DNF plugin command, "
                            "but loading of plugins is currently disabled."))
            raise CliError
        self.command = command_cls(self)

        (base, ext) = self.command.canonical(self.base.cmds)
        self.base.basecmd, self.base.extcmds = (base, ext)
        logger.log(dnf.logging.DDEBUG, 'Base command: %s', base)
        logger.log(dnf.logging.DDEBUG, 'Extra commands: %s', ext)
Beispiel #11
0
    def run(self):
        if any([self.opts.grp_specs, self.opts.pkg_specs, self.opts.filenames]):
            self.opts.pkg_specs += self.opts.filenames
            done = False
            # Remove groups.
            if self.opts.grp_specs and self.forms:
                for grp_spec in self.opts.grp_specs:
                    msg = _('Not a valid form: %s')
                    logger.warning(msg, self.base.output.term.bold(grp_spec))
            elif self.opts.grp_specs:
                self.base.read_comps(arch_filter=True)
                if self.base.env_group_remove(self.opts.grp_specs):
                    done = True

            for pkg_spec in self.opts.pkg_specs:
                try:
                    self.base.remove(pkg_spec, forms=self.forms)
                except dnf.exceptions.MarkingError:
                    logger.info(_('No match for argument: %s'),
                                pkg_spec)
                else:
                    done = True

            if not done:
                raise dnf.exceptions.Error(_('No packages marked for removal.'))

        else:
            base = self.base
            pkgs = base.sack.query()._unneeded(base.sack, base._yumdb,
                                               debug_solver=base.conf.debug_solver)
            for pkg in pkgs:
                base.package_remove(pkg)
Beispiel #12
0
        def run_on_repo(self, reponame, cli_args):
            """Execute the command with respect to given arguments *cli_args*."""
            self.check(cli_args)
            pkg_specs = self.parse_arguments(cli_args)

            done = False

            if not pkg_specs:
                # Remove all packages.
                try:
                    self.base.remove("*", reponame)
                except dnf.exceptions.MarkingError:
                    msg = _("No package installed from the repository.")
                    logger.info(msg)
                else:
                    done = True
            else:
                # Remove packages.
                for pkg_spec in pkg_specs:
                    try:
                        self.base.remove(pkg_spec, reponame)
                    except dnf.exceptions.MarkingError:
                        logger.info(_("No match for argument: %s"), pkg_spec)
                    else:
                        done = True

            if not done:
                raise dnf.exceptions.Error(_("No packages marked for removal."))
Beispiel #13
0
Datei: cli.py Projekt: dmnks/dnf
    def _process_demands(self):
        demands = self.demands
        repos = self.base.repos

        if not demands.cacheonly:
            if demands.freshest_metadata:
                for repo in repos.iter_enabled():
                    repo.md_expire_cache()
            elif not demands.fresh_metadata:
                for repo in repos.values():
                    repo.md_lazy = True

        if demands.sack_activation:
            lar = self.demands.available_repos
            self.base.fill_sack(load_system_repo='auto',
                                load_available_repos=lar)
            if lar:
                repos = list(self.base.repos.iter_enabled())
                if repos:
                    mts = max(repo.metadata.timestamp for repo in repos)
                    # do not bother users with fractions of seconds
                    age = int(min(repo.metadata.age for repo in repos))
                    for repo in repos:
                        logger.debug(_("%s: using metadata from %s."),
                                     repo.id,
                                     time.ctime(repo.metadata.md_timestamp))
                    if age != 0:
                        logger.info(_("Last metadata expiration check: "
                                    "%s ago on %s."),
                                    datetime.timedelta(seconds=age),
                                    time.ctime(mts))
            self.base.plugins.run_sack()
Beispiel #14
0
        def run_on_repo(self, reponame, cli_args):
            """Execute the command with respect to given arguments *cli_args*."""
            self.check(cli_args)
            pkg_specs = self.parse_arguments(cli_args)

            done = False

            if not pkg_specs:
                # Sync all packages.
                try:
                    self._replace("*", reponame)
                except dnf.exceptions.PackagesNotInstalledError:
                    msg = _("No package installed from the repository.")
                    logger.info(msg)
                else:
                    done = True
            else:
                # Reinstall packages.
                for pkg_spec in pkg_specs:
                    try:
                        self._replace(pkg_spec, reponame)
                    except dnf.exceptions.PackagesNotInstalledError:
                        msg = _("No match for argument: %s")
                        logger.info(msg, pkg_spec)
                    else:
                        done = True

            if not done:
                raise dnf.exceptions.Error(_("Nothing to do."))
Beispiel #15
0
        def run_on_repo(self, reponame, cli_args):
            """Execute the command with respect to given arguments *cli_args*."""
            self.check(cli_args)
            pkg_specs = self.parse_arguments(cli_args)

            done = False

            if not pkg_specs:
                # Reinstall all packages.
                try:
                    self.base.reinstall("*", old_reponame=reponame, new_reponame_neq=reponame, remove_na=True)
                except dnf.exceptions.PackagesNotInstalledError:
                    msg = _("No package installed from the repository.")
                    logger.info(msg)
                except dnf.exceptions.MarkingError:
                    assert False, "Only the above marking error is expected."
                else:
                    done = True
            else:
                # Reinstall packages.
                for pkg_spec in pkg_specs:
                    try:
                        self.base.reinstall(pkg_spec, old_reponame=reponame, new_reponame_neq=reponame, remove_na=True)
                    except dnf.exceptions.PackagesNotInstalledError:
                        msg = _("No match for argument: %s")
                        logger.info(msg, pkg_spec)
                    except dnf.exceptions.MarkingError:
                        assert False, "Only the above marking error is expected."
                    else:
                        done = True

            if not done:
                raise dnf.exceptions.Error(_("Nothing to do."))
Beispiel #16
0
        def run_on_repo(self, reponame, cli_args):
            """Execute the command with respect to given arguments *cli_args*."""
            self.check(cli_args)
            pkg_specs = self.parse_arguments(cli_args)

            done = False

            if not pkg_specs:
                # Install all packages.
                try:
                    self.base.install("*", reponame)
                except dnf.exceptions.MarkingError:
                    logger.info(_("No package available."))
                else:
                    done = True
            else:
                # Install packages.
                for pkg_spec in pkg_specs:
                    try:
                        self.base.install(pkg_spec, reponame)
                    except dnf.exceptions.MarkingError:
                        msg = _("No package %s%s%s available.")
                        logger.info(msg, self.output.term.MODE["bold"], pkg_spec, self.output.term.MODE["normal"])
                    else:
                        done = True

            if not done:
                raise dnf.exceptions.Error(_("Nothing to do."))
Beispiel #17
0
def checkGPGKey(base, cli):
    """Verify that there are gpg keys for the enabled repositories in the
    rpm database.

    :param base: a :class:`dnf.Base` object.
    :raises: :class:`cli.CliError`
    """
    if cli.nogpgcheck:
        return
    if not base.gpgKeyCheck():
        for repo in base.repos.iter_enabled():
            if (repo.gpgcheck or repo.repo_gpgcheck) and not repo.gpgkey:
                msg = _(
                    """
You have enabled checking of packages via GPG keys. This is a good thing.
However, you do not have any GPG public keys installed. You need to download
the keys for packages you wish to install and install them.
You can do that by running the command:
    rpm --import public.gpg.key


Alternatively you can specify the url to the key you would like to use
for a repository in the 'gpgkey' option in a repository section and DNF
will install it for you.

For more information contact your distribution or package provider.
"""
                )
                logger.critical(msg)
                logger.critical(_("Problem repository: %s"), repo)
                raise dnf.cli.CliError
Beispiel #18
0
    def _makeOutput(command):
        canonical_name = command.aliases[0]

        usage = command.usage
        summary = command.summary

        # XXX need detailed help here, too
        help_output = ""
        if usage is not None:
            help_output += "%s %s" % (canonical_name, usage)
        if summary is not None:
            help_output += "\n\n%s" % summary

        if usage is None and summary is None:
            help_output = _("No help available for %s") % canonical_name

        command_names = command.aliases
        if len(command_names) > 1:
            if len(command_names) > 2:
                help_output += _("\n\naliases: ")
            else:
                help_output += _("\n\nalias: ")
            help_output += ", ".join(command.aliases[1:])

        return help_output
Beispiel #19
0
    def _hcmd_redo(self, extcmds):
        try:
            extcmd, = extcmds
        except ValueError:
            if not extcmds:
                logger.critical(_("No transaction ID given"))
            elif len(extcmds) > 1:
                logger.critical(_("Found more than one transaction ID!"))
            return 1, ["Failed history redo"]

        old = self.base.history_get_transaction((extcmd,))
        if old is None:
            return 1, ["Failed history redo"]
        tm = time.ctime(old.beg_timestamp)
        print("Repeating transaction %u, from %s" % (old.tid, tm))
        self.output.historyInfoCmdPkgsAltered(old)

        converter = dnf.history.TransactionConverter(self.base.sack)
        history = dnf.history.open_history(self.base.history)
        operations = history.transaction_nevra_ops(old.tid)

        hibeg = self.output.term.MODE["bold"]
        hiend = self.output.term.MODE["normal"]
        try:
            self.base.transaction = converter.convert(operations, "history")
        except dnf.exceptions.PackagesNotInstalledError as err:
            logger.info(_("No package %s%s%s installed."), hibeg, ucd(err.pkg_spec), hiend)
            return 1, ["An operation cannot be redone"]
        except dnf.exceptions.PackagesNotAvailableError as err:
            logger.info(_("No package %s%s%s available."), hibeg, ucd(err.pkg_spec), hiend)
            return 1, ["An operation cannot be redone"]
        else:
            return 2, ["Repeating transaction %u" % (old.tid,)]
Beispiel #20
0
Datei: cli.py Projekt: hnk/dnf
def print_versions(pkgs, base, output):
    def sm_ui_time(x):
        return time.strftime("%Y-%m-%d %H:%M", time.gmtime(x))

    def sm_ui_date(x):  # For changelogs, there is no time
        return time.strftime("%Y-%m-%d", time.gmtime(x))

    rpmdb_sack = dnf.sack.rpmdb_sack(base)
    done = False
    for pkg in rpmdb_sack.query().installed().filter(name=pkgs):
        if done:
            print("")
        done = True
        if pkg.epoch == '0':
            ver = '%s-%s.%s' % (pkg.version, pkg.release, pkg.arch)
        else:
            ver = '%s:%s-%s.%s' % (pkg.epoch, pkg.version, pkg.release,
                                   pkg.arch)
        name = "%s%s%s" % (output.term.MODE['bold'], pkg.name,
                           output.term.MODE['normal'])
        print(_("  Installed: %s-%s at %s") % (name, ver,
                                               sm_ui_time(pkg.installtime)))
        print(
            _("  Built    : %s at %s") % (pkg.packager if pkg.packager else "",
                                          sm_ui_time(pkg.buildtime)))
Beispiel #21
0
 def _try_revive_by_metalink(self):
     """Use metalink to check whether our metadata are still current."""
     repomd_fn = self.metadata._repo_dct['repomd']
     with dnf.util.tmpdir() as tmpdir, open(repomd_fn) as repomd:
         handle = self._handle_new_remote(tmpdir)
         handle.fetchmirrors = True
         handle._perform()
         if handle.metalink is None:
             logger.debug(_("reviving: repo '%s' skipped, no metalink."), self.id)
             return False
         hashes = handle.metalink['hashes']
         hashes = [hsh_val for hsh_val in hashes
                   if hsh_val[0] in _RECOGNIZED_CHKSUMS]
         if len(hashes) < 1:
             logger.debug(_("reviving: repo '%s' skipped, no usable hash."),
                          self.id)
             return False
         algos = list(map(operator.itemgetter(0), hashes))
         chksums = dnf.yum.misc.Checksums(algos,
                                          ignore_missing=True,
                                          ignore_none=True)
         chksums.read(repomd, -1)
         digests = chksums.hexdigests()
         for (algo, digest) in hashes:
             if digests[algo] != digest:
                 logger.debug(_("reviving: failed for '%s', mismatched %s sum."),
                              self.id, algo)
                 return False
     logger.debug(_("reviving: '%s' can be revived - metalink checksums match."), self.id)
     return True
Beispiel #22
0
    def _parse(self, s):
        if len(s) < 1:
            raise ValueError(_("no value specified"))

        if s == "-1" or s == "never": # Special cache timeout, meaning never
            return -1
        if s[-1].isalpha():
            n = s[:-1]
            unit = s[-1].lower()
            mult = self.MULTS.get(unit, None)
            if not mult:
                raise ValueError(_("unknown unit '%s'") % unit)
        else:
            n = s
            mult = 1

        try:
            n = float(n)
        except (ValueError, TypeError):
            raise ValueError(_("invalid value '%s'") % s)

        if n < 0:
            raise ValueError(_("seconds value '%s' must not be negative") % s)

        return int(n * mult)
Beispiel #23
0
def resolving(cli, base):
    """Perform the depsolve, download and RPM transaction stage."""

    if base.transaction is None:
        base.resolve(cli.demands.allow_erasing)
        logger.info(_('Dependencies resolved.'))

    # Run the transaction
    displays = []
    if cli.demands.transaction_display is not None:
        displays.append(cli.demands.transaction_display)
    try:
        base.do_transaction(display=displays)
    except dnf.cli.CliError as exc:
        logger.error(ucd(exc))
        return 1
    except dnf.exceptions.TransactionCheckError as err:
        for msg in cli.command.get_error_output(err):
            logger.critical(msg)
        return 1
    except IOError as e:
        return ex_IOError(e)
    else:
        logger.info(_('Complete!'))
    return 0
Beispiel #24
0
Datei: group.py Projekt: rhn/dnf
    def _mark_install(self, patterns):
        prst = self.base._group_persistor
        q = CompsQuery(self.base.comps, prst,
                       CompsQuery.GROUPS | CompsQuery.ENVIRONMENTS,
                       CompsQuery.AVAILABLE | CompsQuery.INSTALLED)
        solver = self.base._build_comps_solver()
        res = q.get(*patterns)
        types = dnf.comps.DEFAULT | dnf.comps.MANDATORY | dnf.comps.OPTIONAL

        for env_id in res.environments:
            if not dnf.comps.install_or_skip(solver._environment_install,
                                             env_id, types):
                res.environments.remove(env_id)
        for group_id in res.groups:
            if not dnf.comps.install_or_skip(solver._group_install,
                                             group_id, types):
                res.groups.remove(group_id)

        if res.environments:
            logger.info(_('Environments marked installed: %s'),
                        ','.join([prst.environment(g).ui_name
                                  for g in res.environments]))
        if res.groups:
            logger.info(_('Groups marked installed: %s'),
                        ','.join([prst.group(g).ui_name for g in res.groups]))
        prst.commit()
Beispiel #25
0
    def run(self):
        strict = self.base.conf.strict

        # Install files.
        err_pkgs = []
        for pkg in self.base.add_remote_rpms(self.opts.filenames, strict=strict):
            try:
                self.base.package_install(pkg, strict=strict)
            except dnf.exceptions.MarkingError:
                msg = _("No match for argument: %s")
                logger.info(msg, self.base.output.term.bold(pkg.location))
                err_pkgs.append(pkg)

        # Install groups.
        if self.opts.grp_specs:
            self.base.read_comps()
            try:
                self.base.env_group_install(self.opts.grp_specs, dnf.const.GROUP_PACKAGE_TYPES, strict=strict)
            except dnf.exceptions.Error:
                if self.base.conf.strict:
                    raise

        # Install packages.
        errs = []
        for pkg_spec in self.opts.pkg_specs:
            try:
                self.base.install(pkg_spec, strict=strict)
            except dnf.exceptions.MarkingError:
                msg = _("No package %s available.")
                logger.info(msg, self.base.output.term.bold(pkg_spec))
                errs.append(pkg_spec)
        if (len(errs) != 0 or len(err_pkgs) != 0) and self.base.conf.strict:
            raise dnf.exceptions.PackagesNotAvailableError(
                _("Unable to find a match"), pkg_spec=" ".join(errs), packages=err_pkgs
            )
Beispiel #26
0
        def run(self, reponame, cli_args):
            """Execute the command with respect to given arguments *cli_args*."""
            super(RepoPkgsCommand.UpgradeSubCommand, self).run(cli_args)
            self.check(cli_args)
            pkg_specs = self.parse_arguments(cli_args)

            done = False

            if not pkg_specs:
                # Update all packages.
                self.base.upgrade_all(reponame)
                done = True
            else:
                # Update packages.
                for pkg_spec in pkg_specs:
                    try:
                        self.base.upgrade(pkg_spec, reponame)
                    except dnf.exceptions.MarkingError:
                        logger.info(_('No match for argument: %s'),
                                              pkg_spec)
                    else:
                        done = True

            if not done:
                raise dnf.exceptions.Error(_('No packages marked for upgrade.'))
Beispiel #27
0
Datei: cli.py Projekt: dmach/dnf
    def downgradePkgs(self, specs=[], file_pkgs=[], strict=False):
        """Attempt to take the user specified list of packages or
        wildcards and downgrade them. If a complete version number is
        specified, attempt to downgrade them to the specified version

        :param specs: a list of names or wildcards specifying packages to downgrade
        :param file_pkgs: a list of pkg objects from local files
        """

        oldcount = self._goal.req_length()
        for pkg in file_pkgs:
            try:
                self.package_downgrade(pkg, strict=strict)
                continue # it was something on disk and it ended in rpm
                         # no matter what we don't go looking at repos
            except dnf.exceptions.MarkingError as e:
                logger.info(_('No match for argument: %s'),
                            self.output.term.bold(pkg.location))
                # it was something on disk and it ended in rpm
                # no matter what we don't go looking at repos

        for arg in specs:
            try:
                self.downgrade_to(arg, strict=strict)
            except dnf.exceptions.PackageNotFoundError as err:
                msg = _('No package %s available.')
                logger.info(msg, self.output.term.bold(arg))
            except dnf.exceptions.PackagesNotInstalledError as err:
                logger.info(_('Packages for argument %s available, but not installed.'),
                            self.output.term.bold(err.pkg_spec))
            except dnf.exceptions.MarkingError:
                assert False
        cnt = self._goal.req_length() - oldcount
        if cnt <= 0:
            raise dnf.exceptions.Error(_('Nothing to do.'))
Beispiel #28
0
def show_lock_owner(pid, logger):
    """Output information about another process that is holding the
    yum lock.

    :param pid: the process id number of the process holding the yum
       lock
    :param logger: the logger to output the information to
    :return: a dictionary containing information about the process.
       This is the same as the dictionary returned by
       :func:`get_process_info`.
    """
    ps = get_process_info(pid)
    if not ps:
        return None

    # This yumBackend isn't very friendly, so...
    msg = _('  The application with PID %d is: %s')
    if ps['name'] == 'yumBackend.py':
        nmsg = msg % (pid, 'PackageKit')
    else:
        nmsg = msg % (pid, ps['name'])

    logger.critical("%s", nmsg)
    logger.critical(_("    Memory : %5s RSS (%5sB VSZ)") %
                    (format_number(int(ps['vmrss']) * 1024),
                     format_number(int(ps['vmsize']) * 1024)))

    ago = seconds_to_ui_time(int(time.time()) - ps['start_time'])
    logger.critical(_("    Started: %s - %s ago") %
                    (time.ctime(ps['start_time']), ago))
    logger.critical(_("    State  : %s") % ps['state'])

    return ps
Beispiel #29
0
        def run(self, reponame, cli_args):
            """Execute the command with respect to given arguments *cli_args*."""
            super(RepoPkgsCommand.InstallSubCommand, self).run(cli_args)
            self.check(cli_args)
            pkg_specs = self.parse_arguments(cli_args)

            done = False

            if not pkg_specs:
                # Install all packages.
                try:
                    self.base.install('*', reponame)
                except dnf.exceptions.MarkingError:
                    logger.info(_('No package available.'))
                else:
                    done = True
            else:
                # Install packages.
                for pkg_spec in pkg_specs:
                    try:
                        self.base.install(pkg_spec, reponame)
                    except dnf.exceptions.MarkingError:
                        msg = _('No package %s%s%s available.')
                        logger.info(
                            msg, self.output.term.MODE['bold'],
                            pkg_spec, self.output.term.MODE['normal'])
                    else:
                        done = True

            if not done:
                raise dnf.exceptions.Error(_('Nothing to do.'))
Beispiel #30
0
    def _parse(self, s):
        """Parse a friendly bandwidth option to bytes.  The input
        should be a string containing a (possibly floating point)
        number followed by an optional single character unit. Valid
        units are 'k', 'M', 'G'. Case is ignored. The convention that
        1k = 1024 bytes is used.

        Valid inputs: 100, 123M, 45.6k, 12.4G, 100K, 786.3, 0.
        Invalid inputs: -10, -0.1, 45.6L, 123Mb.
        """
        if len(s) < 1:
            raise ValueError(_("no value specified"))

        if s[-1].isalpha():
            n = s[:-1]
            unit = s[-1].lower()
            mult = self.MULTS.get(unit, None)
            if not mult:
                raise ValueError(_("unknown unit '%s'") % unit)
        else:
            n = s
            mult = 1

        try:
            n = float(n)
        except ValueError:
            raise ValueError(_("couldn't convert '%s' to number") % s)

        if n < 0:
            raise ValueError(_("bytes value '%s' must not be negative") % s)

        return int(n * mult)
Beispiel #31
0
class InstallCommand(commands.Command):
    """A class containing methods needed by the cli to execute the
    install command.
    """
    nevra_forms = {
        'install-n': hawkey.FORM_NAME,
        'install-na': hawkey.FORM_NA,
        'install-nevra': hawkey.FORM_NEVRA
    }
    alternatives_provide = 'alternative-for({})'

    aliases = ('install', 'localinstall') + tuple(nevra_forms.keys())
    summary = _('install a package or packages on your system')

    @staticmethod
    def set_argparser(parser):
        parser.add_argument('package',
                            nargs='+',
                            metavar=_('PACKAGE'),
                            action=OptionParser.ParseSpecGroupFileCallback,
                            help=_('Package to install'))

    def configure(self):
        """Verify that conditions are met so that this command can run.
        That there are enabled repositories with gpg keys, and that
        this command is called with appropriate arguments.
        """
        demands = self.cli.demands
        demands.sack_activation = True
        demands.available_repos = True
        demands.resolving = True
        demands.root_user = True
        commands._checkGPGKey(self.base, self.cli)
        if not self.opts.filenames:
            commands._checkEnabledRepo(self.base)

    def run(self):
        err_pkgs = []
        errs = []
        error_module_specs = []

        nevra_forms = self._get_nevra_forms_from_command()

        self.cli._populate_update_security_filter(self.opts,
                                                  self.base.sack.query())
        if self.opts.command == ['localinstall'] and (self.opts.grp_specs
                                                      or self.opts.pkg_specs):
            self._log_not_valid_rpm_file_paths(self.opts.grp_specs)
            if self.base.conf.strict:
                raise dnf.exceptions.Error(_('Nothing to do.'))
        skipped_grp_specs = []
        if self.opts.grp_specs and self.opts.command != ['localinstall']:
            if dnf.base.WITH_MODULES:
                try:
                    module_base = dnf.module.module_base.ModuleBase(self.base)
                    module_base.install(self.opts.grp_specs,
                                        strict=self.base.conf.strict)
                except dnf.exceptions.MarkingErrors as e:
                    if e.no_match_group_specs:
                        for e_spec in e.no_match_group_specs:
                            skipped_grp_specs.append(e_spec)
                    if e.error_group_specs:
                        for e_spec in e.error_group_specs:
                            error_module_specs.append("@" + e_spec)
                    module_debsolv_errors = e.module_debsolv_errors
                    if module_debsolv_errors:
                        logger.error(
                            dnf.module.module_base.
                            format_modular_solver_errors(
                                module_debsolv_errors))
            else:
                skipped_grp_specs = self.opts.grp_specs
        if self.opts.filenames and nevra_forms:
            self._inform_not_a_valid_combination(self.opts.filenames)
            if self.base.conf.strict:
                raise dnf.exceptions.Error(_('Nothing to do.'))
        else:
            err_pkgs = self._install_files()

        if skipped_grp_specs and nevra_forms:
            self._inform_not_a_valid_combination(skipped_grp_specs)
            if self.base.conf.strict:
                raise dnf.exceptions.Error(_('Nothing to do.'))
        elif skipped_grp_specs and self.opts.command != ['localinstall']:
            self._install_groups(skipped_grp_specs)

        if self.opts.command != ['localinstall']:
            errs = self._install_packages(nevra_forms)

        if (len(errs) != 0 or len(err_pkgs) != 0
                or error_module_specs) and self.base.conf.strict:
            raise dnf.exceptions.PackagesNotAvailableError(
                _("Unable to find a match"),
                pkg_spec=' '.join(errs),
                packages=err_pkgs)

    def _get_nevra_forms_from_command(self):
        return [
            self.nevra_forms[command] for command in self.opts.command
            if command in list(self.nevra_forms.keys())
        ]

    def _log_not_valid_rpm_file_paths(self, grp_specs):
        group_names = map(lambda g: '@' + g, grp_specs)
        for pkg in chain(self.opts.pkg_specs, group_names):
            msg = _('Not a valid rpm file path: %s')
            logger.info(msg, self.base.output.term.bold(pkg))

    def _inform_not_a_valid_combination(self, forms):
        for form in forms:
            msg = _('Not a valid form: %s')
            logger.warning(msg, self.base.output.term.bold(form))

    def _install_files(self):
        err_pkgs = []
        strict = self.base.conf.strict
        for pkg in self.base.add_remote_rpms(
                self.opts.filenames,
                strict=strict,
                progress=self.base.output.progress):
            try:
                self.base.package_install(pkg, strict=strict)
            except dnf.exceptions.MarkingError:
                msg = _('No match for argument: %s')
                logger.info(msg, self.base.output.term.bold(pkg.location))
                err_pkgs.append(pkg)

        return err_pkgs

    def _install_groups(self, grp_specs):
        self.base.read_comps(arch_filter=True)
        try:
            self.base.env_group_install(
                grp_specs,
                tuple(self.base.conf.group_package_types),
                strict=self.base.conf.strict)
        except dnf.exceptions.Error:
            if self.base.conf.strict:
                raise

    def _report_alternatives(self, pkg_spec):
        query = self.base.sack.query().filterm(
            provides=self.alternatives_provide.format(pkg_spec))
        if query:
            msg = _('There are following alternatives for "{0}": {1}')
            logger.info(
                msg.format(pkg_spec,
                           ', '.join(sorted(set([alt.name
                                                 for alt in query])))))

    def _install_packages(self, nevra_forms):
        errs = []
        strict = self.base.conf.strict
        for pkg_spec in self.opts.pkg_specs:
            try:
                self.base.install(pkg_spec, strict=strict, forms=nevra_forms)
            except dnf.exceptions.MarkingError:
                msg = _('No match for argument: %s')
                logger.info(msg, self.base.output.term.bold(pkg_spec))
                self.base._report_icase_hint(pkg_spec)
                self._report_alternatives(pkg_spec)
                errs.append(pkg_spec)

        return errs
Beispiel #32
0
 def set_argparser(parser):
     parser.add_argument('dependency', nargs='+', metavar=_('SOME_STRING'))
Beispiel #33
0
class InfoCommand(Command):
    """A class containing methods needed by the cli to execute the
    info command.
    """

    aliases = ('info', )
    summary = _('display details about a package or group of packages')
    DEFAULT_PKGNARROW = 'all'
    pkgnarrows = {
        'available', 'installed', 'extras', 'updates', 'upgrades',
        'autoremove', 'recent', 'obsoletes', DEFAULT_PKGNARROW
    }

    @classmethod
    def set_argparser(cls, parser):
        narrows = parser.add_mutually_exclusive_group()
        narrows.add_argument('--all',
                             dest='_packages_action',
                             action='store_const',
                             const='all',
                             default=None,
                             help=_("show all packages (default)"))
        narrows.add_argument('--available',
                             dest='_packages_action',
                             action='store_const',
                             const='available',
                             help=_("show only available packages"))
        narrows.add_argument('--installed',
                             dest='_packages_action',
                             action='store_const',
                             const='installed',
                             help=_("show only installed packages"))
        narrows.add_argument('--extras',
                             dest='_packages_action',
                             action='store_const',
                             const='extras',
                             help=_("show only extras packages"))
        narrows.add_argument('--updates',
                             dest='_packages_action',
                             action='store_const',
                             const='upgrades',
                             help=_("show only upgrades packages"))
        narrows.add_argument('--upgrades',
                             dest='_packages_action',
                             action='store_const',
                             const='upgrades',
                             help=_("show only upgrades packages"))
        narrows.add_argument('--autoremove',
                             dest='_packages_action',
                             action='store_const',
                             const='autoremove',
                             help=_("show only autoremove packages"))
        narrows.add_argument('--recent',
                             dest='_packages_action',
                             action='store_const',
                             const='recent',
                             help=_("show only recently changed packages"))
        narrows.add_argument('--obsoletes',
                             dest='_packages_action',
                             action='store_const',
                             const='obsoletes',
                             help=_("show only obsoletes packages"))
        parser.add_argument('packages',
                            nargs='*',
                            metavar=_('PACKAGE'),
                            choices=cls.pkgnarrows,
                            default=cls.DEFAULT_PKGNARROW,
                            action=OptionParser.PkgNarrowCallback)

    def configure(self):
        demands = self.cli.demands
        demands.available_repos = True
        demands.fresh_metadata = False
        demands.sack_activation = True
        if self.opts._packages_action:
            self.opts.packages_action = self.opts._packages_action
        if self.opts.packages_action == 'updates':
            self.opts.packages_action = 'upgrades'

    def run(self):
        return self.base.output_packages('info', self.opts.packages_action,
                                         self.opts.packages)
Beispiel #34
0
import argparse
import dnf.cli
import dnf.cli.demand
import dnf.const
import dnf.exceptions
import dnf.i18n
import dnf.pycomp
import dnf.util
import functools
import logging
import operator
import os

logger = logging.getLogger('dnf')
_RPM_VERIFY = _("To diagnose the problem, try running: '%s'.") % \
    'rpm -Va --nofiles --nodigest'
_RPM_REBUILDDB = _("You probably have corrupted RPMDB, running '%s'"
                   " might fix the issue.") % 'rpm --rebuilddb'

gpg_msg = \
    _("""You have enabled checking of packages via GPG keys. This is a good thing.
However, you do not have any GPG public keys installed. You need to download
the keys for packages you wish to install and install them.
You can do that by running the command:
    rpm --import public.gpg.key


Alternatively you can specify the url to the key you would like to use
for a repository in the 'gpgkey' option in a repository section and DNF
will install it for you.
Beispiel #35
0
    def run(self):
        strict = self.base.conf.strict
        forms = [self.nevra_forms[command] for command in self.opts.command
                 if command in list(self.nevra_forms.keys())]

        self.cli._populate_update_security_filter(self.opts, self.base.sack.query())

        # localinstall valid arguments check
        nonfilenames = self.opts.grp_specs or self.opts.pkg_specs
        if self.opts.command == ['localinstall'] and nonfilenames:
            group_names = map(lambda g: '@' + g, self.opts.grp_specs)
            for pkg in chain(self.opts.pkg_specs, group_names):
                msg = _('Not a valid rpm file path: %s')
                logger.info(msg, self.base.output.term.bold(pkg))
            if strict:
                raise dnf.exceptions.Error(_('No packages marked for install.'))

        # Install files.
        err_pkgs = []
        if self.opts.filenames and forms:
            for filename in self.opts.filenames:
                msg = _('Not a valid form: %s')
                logger.warning(msg, self.base.output.term.bold(filename))
            if strict:
                raise dnf.exceptions.Error(_('No packages marked for install.'))
        else:
            for pkg in self.base.add_remote_rpms(self.opts.filenames, strict=strict):
                try:
                    self.base.package_install(pkg, strict=strict)
                except dnf.exceptions.MarkingError:
                    msg = _('No match for argument: %s')
                    logger.info(msg, self.base.output.term.bold(pkg.location))
                    err_pkgs.append(pkg)

        # Install groups.
        if self.opts.grp_specs and forms:
            for grp_spec in self.opts.grp_specs:
                msg = _('Not a valid form: %s')
                logger.warning(msg, self.base.output.term.bold(grp_spec))
            if strict:
                raise dnf.exceptions.Error(_('No packages marked for install.'))
        elif self.opts.grp_specs and self.opts.command != ['localinstall']:
            self.base.read_comps(arch_filter=True)
            try:
                self.base.env_group_install(self.opts.grp_specs,
                                            tuple(self.base.conf.group_package_types),
                                            strict=strict)
            except dnf.exceptions.Error:
                if self.base.conf.strict:
                    raise

        # Install packages.
        errs = []
        if self.opts.command != ['localinstall']:
            for pkg_spec in self.opts.pkg_specs:
                try:
                    self.base.install(pkg_spec, strict=strict, forms=forms)
                except dnf.exceptions.MarkingError:
                    msg = _('No match for argument: %s')
                    logger.info(msg, self.base.output.term.bold(pkg_spec))
                    errs.append(pkg_spec)

        if (len(errs) != 0 or len(err_pkgs) != 0) and self.base.conf.strict:
            raise dnf.exceptions.PackagesNotAvailableError(
                _("Unable to find a match"), pkg_spec=' '.join(errs),
                packages=err_pkgs)
Beispiel #36
0
 def set_argparser(parser):
     parser.add_argument('package', nargs='+', metavar=_('PACKAGE'),
                       action=OptionParser.ParseSpecGroupFileCallback,
                       help=_('Package to install'))
Beispiel #37
0
class InstallCommand(commands.Command):
    """A class containing methods needed by the cli to execute the
    install command.
    """
    nevra_forms = {'install-n': hawkey.FORM_NAME,
                   'install-na': hawkey.FORM_NA,
                   'install-nevra': hawkey.FORM_NEVRA}

    aliases = ('install', 'localinstall') + tuple(nevra_forms.keys())
    summary = _('install a package or packages on your system')

    @staticmethod
    def set_argparser(parser):
        parser.add_argument('package', nargs='+', metavar=_('PACKAGE'),
                          action=OptionParser.ParseSpecGroupFileCallback,
                          help=_('Package to install'))

    def configure(self):
        """Verify that conditions are met so that this command can run.
        That there are enabled repositories with gpg keys, and that
        this command is called with appropriate arguments.
        """
        demands = self.cli.demands
        demands.sack_activation = True
        demands.available_repos = True
        demands.resolving = True
        demands.root_user = True
        commands._checkGPGKey(self.base, self.cli)
        if not self.opts.filenames:
            commands._checkEnabledRepo(self.base)

    def run(self):
        strict = self.base.conf.strict
        forms = [self.nevra_forms[command] for command in self.opts.command
                 if command in list(self.nevra_forms.keys())]

        self.cli._populate_update_security_filter(self.opts, self.base.sack.query())

        # localinstall valid arguments check
        nonfilenames = self.opts.grp_specs or self.opts.pkg_specs
        if self.opts.command == ['localinstall'] and nonfilenames:
            group_names = map(lambda g: '@' + g, self.opts.grp_specs)
            for pkg in chain(self.opts.pkg_specs, group_names):
                msg = _('Not a valid rpm file path: %s')
                logger.info(msg, self.base.output.term.bold(pkg))
            if strict:
                raise dnf.exceptions.Error(_('No packages marked for install.'))

        # Install files.
        err_pkgs = []
        if self.opts.filenames and forms:
            for filename in self.opts.filenames:
                msg = _('Not a valid form: %s')
                logger.warning(msg, self.base.output.term.bold(filename))
            if strict:
                raise dnf.exceptions.Error(_('No packages marked for install.'))
        else:
            for pkg in self.base.add_remote_rpms(self.opts.filenames, strict=strict):
                try:
                    self.base.package_install(pkg, strict=strict)
                except dnf.exceptions.MarkingError:
                    msg = _('No match for argument: %s')
                    logger.info(msg, self.base.output.term.bold(pkg.location))
                    err_pkgs.append(pkg)

        # Install groups.
        if self.opts.grp_specs and forms:
            for grp_spec in self.opts.grp_specs:
                msg = _('Not a valid form: %s')
                logger.warning(msg, self.base.output.term.bold(grp_spec))
            if strict:
                raise dnf.exceptions.Error(_('No packages marked for install.'))
        elif self.opts.grp_specs and self.opts.command != ['localinstall']:
            self.base.read_comps(arch_filter=True)
            try:
                self.base.env_group_install(self.opts.grp_specs,
                                            tuple(self.base.conf.group_package_types),
                                            strict=strict)
            except dnf.exceptions.Error:
                if self.base.conf.strict:
                    raise

        # Install packages.
        errs = []
        if self.opts.command != ['localinstall']:
            for pkg_spec in self.opts.pkg_specs:
                try:
                    self.base.install(pkg_spec, strict=strict, forms=forms)
                except dnf.exceptions.MarkingError:
                    msg = _('No match for argument: %s')
                    logger.info(msg, self.base.output.term.bold(pkg_spec))
                    errs.append(pkg_spec)

        if (len(errs) != 0 or len(err_pkgs) != 0) and self.base.conf.strict:
            raise dnf.exceptions.PackagesNotAvailableError(
                _("Unable to find a match"), pkg_spec=' '.join(errs),
                packages=err_pkgs)
Beispiel #38
0
 def _log_not_valid_rpm_file_paths(self, grp_specs):
     group_names = map(lambda g: '@' + g, grp_specs)
     for pkg in chain(self.opts.pkg_specs, group_names):
         msg = _('Not a valid rpm file path: %s')
         logger.info(msg, self.base.output.term.bold(pkg))
Beispiel #39
0
    def _get_key_for_package(self, po, askcb=None, fullaskcb=None):
        """Retrieve a key for a package. If needed, use the given
        callback to prompt whether the key should be imported.

        :param po: the package object to retrieve the key of
        :param askcb: Callback function to use to ask permission to
           import a key.  The arguments *askck* should take are the
           package object, the userid of the key, and the keyid
        :param fullaskcb: Callback function to use to ask permission to
           import a key.  This differs from *askcb* in that it gets
           passed a dictionary so that we can expand the values passed.
        :raises: :class:`dnf.exceptions.Error` if there are errors
           retrieving the keys
        """
        repo = self.repos[po.repoid]
        keyurls = repo.gpgkey
        key_installed = False

        def _prov_key_data(msg):
            msg += _('Failing package is: %s') % (po) + '\n '
            msg += _('GPG Keys are configured as: %s') % \
                    (', '.join(repo.gpgkey) + '\n')
            return '\n\n\n' + msg

        user_cb_fail = False
        for keyurl in keyurls:
            keys = dnf.crypto.retrieve(keyurl, repo)

            for info in keys:
                ts = self._rpmconn.readonly_ts
                # Check if key is already installed
                if misc.keyInstalled(ts, info.rpm_id, info.timestamp) >= 0:
                    msg = _('GPG key at %s (0x%s) is already installed')
                    logger.info(msg, keyurl, info.short_id)
                    continue

                # Try installing/updating GPG key
                info.url = keyurl
                dnf.crypto.log_key_import(info)
                rc = False
                if self.conf.assumeno:
                    rc = False
                elif self.conf.assumeyes:
                    rc = True

                # grab the .sig/.asc for the keyurl, if it exists if it
                # does check the signature on the key if it is signed by
                # one of our ca-keys for this repo or the global one then
                # rc = True else ask as normal.

                elif fullaskcb:
                    rc = fullaskcb({
                        "po": po,
                        "userid": info.userid,
                        "hexkeyid": info.short_id,
                        "keyurl": keyurl,
                        "fingerprint": info.fingerprint,
                        "timestamp": info.timestamp
                    })
                elif askcb:
                    rc = askcb(po, info.userid, info.short_id)

                if not rc:
                    user_cb_fail = True
                    continue

                # Import the key
                result = ts.pgpImportPubkey(misc.procgpgkey(info.raw_key))
                if result != 0:
                    msg = _('Key import failed (code %d)') % result
                    raise dnf.exceptions.Error(_prov_key_data(msg))
                logger.info(_('Key imported successfully'))
                key_installed = True

        if not key_installed and user_cb_fail:
            raise dnf.exceptions.Error(_("Didn't install any keys"))

        if not key_installed:
            msg = _('The GPG keys listed for the "%s" repository are '
                    'already installed but they are not correct for this '
                    'package.\n'
                    'Check that the correct key URLs are configured for '
                    'this repository.') % repo.name
            raise dnf.exceptions.Error(_prov_key_data(msg))

        # Check if the newly installed keys helped
        result, errmsg = self._sig_check_pkg(po)
        if result != 0:
            msg = _("Import of key(s) didn't help, wrong key(s)?")
            logger.info(msg)
            errmsg = ucd(errmsg)
            raise dnf.exceptions.Error(_prov_key_data(errmsg))
Beispiel #40
0
 def _inform_not_a_valid_combination(self, forms):
     for form in forms:
         msg = _('Not a valid form: %s')
         logger.warning(msg, self.base.output.term.bold(form))
Beispiel #41
0
    def output_packages(self, basecmd, pkgnarrow='all', patterns=(), reponame=None):
        """Output selection *pkgnarrow* of packages matching *patterns* and *repoid*."""
        try:
            highlight = self.output.term.MODE['bold']
            ypl = self.returnPkgLists(
                pkgnarrow, patterns, installed_available=highlight, reponame=reponame)
        except dnf.exceptions.Error as e:
            return 1, [str(e)]
        else:
            update_pkgs = {}
            inst_pkgs = {}
            local_pkgs = {}

            columns = None
            if basecmd == 'list':
                # Dynamically size the columns
                columns = _list_cmd_calc_columns(self.output, ypl)

            if highlight and ypl.installed:
                #  If we have installed and available lists, then do the
                # highlighting for the installed packages so you can see what's
                # available to update, an extra, or newer than what we have.
                for pkg in (ypl.hidden_available +
                            ypl.reinstall_available +
                            ypl.old_available):
                    key = (pkg.name, pkg.arch)
                    if key not in update_pkgs or pkg > update_pkgs[key]:
                        update_pkgs[key] = pkg

            if highlight and ypl.available:
                #  If we have installed and available lists, then do the
                # highlighting for the available packages so you can see what's
                # available to install vs. update vs. old.
                for pkg in ypl.hidden_installed:
                    key = (pkg.name, pkg.arch)
                    if key not in inst_pkgs or pkg > inst_pkgs[key]:
                        inst_pkgs[key] = pkg

            if highlight and ypl.updates:
                # Do the local/remote split we get in "yum updates"
                for po in sorted(ypl.updates):
                    if po.reponame != hawkey.SYSTEM_REPO_NAME:
                        local_pkgs[(po.name, po.arch)] = po

            # Output the packages:
            clio = self.conf.color_list_installed_older
            clin = self.conf.color_list_installed_newer
            clir = self.conf.color_list_installed_reinstall
            clie = self.conf.color_list_installed_extra
            rip = self.output.listPkgs(ypl.installed, _('Installed Packages'), basecmd,
                                highlight_na=update_pkgs, columns=columns,
                                highlight_modes={'>' : clio, '<' : clin,
                                                 '=' : clir, 'not in' : clie})
            clau = self.conf.color_list_available_upgrade
            clad = self.conf.color_list_available_downgrade
            clar = self.conf.color_list_available_reinstall
            clai = self.conf.color_list_available_install
            rap = self.output.listPkgs(ypl.available, _('Available Packages'), basecmd,
                                highlight_na=inst_pkgs, columns=columns,
                                highlight_modes={'<' : clau, '>' : clad,
                                                 '=' : clar, 'not in' : clai})
            raep = self.output.listPkgs(ypl.autoremove, _('Autoremove Packages'),
                                basecmd, columns=columns)
            rep = self.output.listPkgs(ypl.extras, _('Extra Packages'), basecmd,
                                columns=columns)
            cul = self.conf.color_update_local
            cur = self.conf.color_update_remote
            rup = self.output.listPkgs(ypl.updates, _('Upgraded Packages'), basecmd,
                                highlight_na=local_pkgs, columns=columns,
                                highlight_modes={'=' : cul, 'not in' : cur})

            # XXX put this into the ListCommand at some point
            if len(ypl.obsoletes) > 0 and basecmd == 'list':
            # if we've looked up obsolete lists and it's a list request
                rop = [0, '']
                print(_('Obsoleting Packages'))
                for obtup in sorted(ypl.obsoletesTuples,
                                    key=operator.itemgetter(0)):
                    self.output.updatesObsoletesList(obtup, 'obsoletes',
                                                     columns=columns)
            else:
                rop = self.output.listPkgs(ypl.obsoletes, _('Obsoleting Packages'),
                                    basecmd, columns=columns)
            rrap = self.output.listPkgs(ypl.recent, _('Recently Added Packages'),
                                 basecmd, columns=columns)
            if len(patterns) and \
                rrap[0] and rop[0] and rup[0] and rep[0] and rap[0] and \
                raep[0] and rip[0]:
                raise dnf.exceptions.Error(_('No matching Packages to list'))
Beispiel #42
0
 def _prov_key_data(msg):
     msg += _('Failing package is: %s') % (po) + '\n '
     msg += _('GPG Keys are configured as: %s') % \
             (', '.join(repo.gpgkey) + '\n')
     return '\n\n\n' + msg
Beispiel #43
0
 def register_command(self, command_cls):
     """Register a Command. :api"""
     for name in command_cls.aliases:
         if name in self.cli_commands:
             raise dnf.exceptions.ConfigError(_('Command "%s" already defined') % name)
         self.cli_commands[name] = command_cls
Beispiel #44
0
    def configure(self, args):
        """Parse command line arguments, and set up :attr:`self.base.conf` and
        :attr:`self.cmds`, as well as logger objects in base instance.

        :param args: a list of command line arguments
        """
        self.optparser = dnf.cli.option_parser.OptionParser()
        opts, cmds = self.optparser.parse_known_args(args)

        # Just print out the version if that's what the user wanted
        if opts.version:
            print(dnf.const.VERSION)
            opts.quiet = True
            opts.verbose = False

        # go through all the setopts and set the global ones
        bad_setopt_tm, bad_setopt_ne = self._parse_setopts(opts.setopts)

        if self.main_setopts:
            for opt in self.main_setopts.items:
                setattr(opts, opt, getattr(self.main_setopts, opt))

        # get the install root to use
        self.optparser._checkAbsInstallRoot(opts.installroot)
        (root, opts.conffile) = self._root_and_conffile(opts.installroot,
                                                        opts.conffile)
        # the conffile is solid now
        assert(opts.conffile is not None)
        if opts.quiet:
            opts.debuglevel = 0
        if opts.verbose:
            opts.debuglevel = opts.errorlevel = dnf.const.VERBOSE_LEVEL

        # Read up configuration options and initialize plugins
        overrides = self.optparser._non_nones2dict(self._get_first_config(opts))
        releasever = opts.releasever
        try:
            self.read_conf_file(opts.conffile, root, releasever, overrides)

            # now set all the non-first-start opts from main from our setopts
            if self.main_setopts:
                for opt in self.main_setopts.items:
                    if not hasattr(self.base.conf, opt):
                        msg ="Main config did not have a %s attr. before setopt"
                        logger.warning(msg % opt)
                    setattr(self.base.conf, opt, getattr(self.main_setopts, opt))

        except (dnf.exceptions.ConfigError, ValueError) as e:
            logger.critical(_('Config error: %s'), e)
            sys.exit(1)
        except IOError as e:
            e = '%s: %s' % (ucd(e.args[1]), repr(e.filename))
            logger.critical(_('Config error: %s'), e)
            sys.exit(1)
        for item in bad_setopt_tm:
            msg = "Setopt argument has multiple values: %s"
            logger.warning(msg % item)
        for item in bad_setopt_ne:
            msg = "Setopt argument has no value: %s"
            logger.warning(msg % item)

        self.optparser.configure_from_options(opts, self.base.conf, self.demands,
                                              self.base.output)
        self.base.cmds = cmds

        if opts.version:
            opts.quiet = True
            opts.verbose = False
        if opts.quiet:
            opts.debuglevel = 0
        if opts.verbose:
            opts.debuglevel = opts.errorlevel = dnf.const.VERBOSE_LEVEL
        self.nogpgcheck = opts.nogpgcheck

        # the configuration reading phase is now concluded, finish the init
        self._configure_cachedir()
        # with cachedir in place we can configure stuff depending on it:
        self.base.activate_persistor()
        self._configure_repos(opts)

        if opts.version:
            print_versions(self.base.conf.history_record_packages, self.base,
                           self.base.output)
            sys.exit(0)

        # store the main commands & summaries, before plugins are loaded
        self.optparser.add_commands(self.cli_commands, 'main')
        if self.base.conf.plugins:
            self.base.plugins.load(self.base.conf.pluginpath, opts.disableplugins)
        self.base.plugins.run_init(self.base, self)
        # store the plugin commands & summaries
        self.optparser.add_commands(self.cli_commands,'plugin')

        # build the usage info and put it into the optparser.
        self.optparser.usage = self.optparser.get_usage()

        # show help if the user requests it
        # this is done here, because we first have the full
        # usage info after the plugins are loaded.
        if opts.help:
            self.optparser.print_help()
            sys.exit(0)

        # save our original args out
        self.base.args = args
        # save out as a nice command string
        self.cmdstring = dnf.const.PROGRAM_NAME + ' '
        for arg in self.base.args:
            self.cmdstring += '%s ' % arg

        self._log_essentials()
        try:
            self._parse_commands() # before we return check over the base command
                                  # + args make sure they match/make sense
        except CliError:
            sys.exit(1)
        self.command.configure(self.base.extcmds)

        if opts.debugsolver:
            self.base.conf.debug_solver = True

        self.base.plugins.run_config()
Beispiel #45
0
class ModuleCommand(commands.Command):
    class SubCommand(commands.Command):

        def __init__(self, cli):
            super(ModuleCommand.SubCommand, self).__init__(cli)

    class ListSubCommand(SubCommand):

        aliases = ('list',)

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True

        def run_on_module(self):
            mods = self.base.repo_module_dict

            if self.opts.enabled:
                print(mods.get_brief_description_enabled(self.opts.module_nsvp))
            elif self.opts.disabled:
                print(mods.get_brief_description_disabled(self.opts.module_nsvp))
            elif self.opts.installed:
                print(mods.get_brief_description_installed(self.opts.module_nsvp))
            else:
                print(mods.get_brief_description_latest(self.opts.module_nsvp))

            return 0

    class InfoSubCommand(SubCommand):

        aliases = ('info',)

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True

        def run_on_module(self):
            for spec in self.opts.module_nsvp:
                try:
                    print()
                    if self.opts.verbose:
                        print(self.base.repo_module_dict.get_full_info(spec))
                    elif self.opts.profile:
                        print(self.base.repo_module_dict.get_info_profiles(spec))
                    else:
                        print(self.base.repo_module_dict.get_info(spec))
                except NoModuleException as e:
                    logger.info(e)

    class EnableSubCommand(SubCommand):

        aliases = ('enable',)

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True
            demands.root_user = True

        def run_on_module(self):
            module_versions = dict()
            for module_ns in self.opts.module_nsvp:
                subj = ModuleSubject(module_ns)
                module_version, module_form = subj.find_module_version(self.base.repo_module_dict)

                if module_version.name in module_versions:
                    raise EnableMultipleStreamsException(module_version.name)

                module_versions[module_version.name] = (module_version, module_form)

            for module_version, module_form in module_versions.values():
                if module_form.profile:
                    logger.info("Ignoring unnecessary profile: '{}/{}'".format(module_form.name,
                                                                               module_form.profile))

                self.base.repo_module_dict.enable_by_version(module_version, True)
                logger.info("Module stream has been enabled: {}:{}".format(module_version.name,
                                                                           module_version.stream))

            logger.info(_("\nTo switch to the new streams' RPMs, run '{} distro-sync'. \n"
                        "Then migrate configuration files and data as necessary."
                          .format(os.path.basename(sys.argv[0]))))

    class DisableSubCommand(SubCommand):

        aliases = ('disable',)

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True
            demands.root_user = True

        def run_on_module(self):
            for module_n in self.opts.module_nsvp:
                subj = ModuleSubject(module_n)
                module_version, module_form = subj.find_module_version(self.base.repo_module_dict)

                if module_form.profile:
                    logger.info("Ignoring unnecessary profile: '{}/{}'".format(module_form.name,
                                                                               module_form.profile))

                self.base.repo_module_dict.disable_by_version(module_version, True)
                logger.info("Module stream has been disabled: {}:{}".format(module_version.name,
                                                                            module_version.stream))

    class InstallSubCommand(SubCommand):

        aliases = ('install',)

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True
            demands.resolving = True
            demands.root_user = True

        def run_on_module(self):
            module_specs = self.base.repo_module_dict.install(self.opts.module_nsvp,
                                                              self.base.conf.strict)
            if module_specs:
                raise NoModuleException(", ".join(module_specs))

    class UpdateSubCommand(SubCommand):

        aliases = ('update',)

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True
            demands.resolving = True
            demands.root_user = True

        def run_on_module(self):
            module_specs = self.base.repo_module_dict.upgrade(self.opts.module_nsvp, True)
            if module_specs:
                raise NoModuleException(", ".join(module_specs))

    class RemoveSubCommand(SubCommand):

        aliases = ('remove', 'erase',)

        def configure(self):
            demands = self.cli.demands
            demands.allow_erasing = True
            demands.available_repos = True
            demands.resolving = True
            demands.root_user = True
            demands.sack_activation = True

        def run_on_module(self):
            self.base.repo_module_dict.remove(self.opts.module_nsvp)

    class ProfileInfoSubCommand(SubCommand):

        aliases = ("profile", "profile-info")

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True

        def run_on_module(self):
            for spec in self.opts.module_nsvp:
                print()
                logger.info(self.base.repo_module_dict.get_info_profiles(spec))

    class StreamsSubCommand(SubCommand):

        aliases = ("streams", "enabled", "enabled-streams")

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True

        def run_on_module(self):
            logger.info(self.base.repo_module_dict
                        .get_brief_description_enabled(self.opts.module_nsvp))

    class ProvidesSubCommand(SubCommand):

        aliases = ("provides", )

        def configure(self):
            demands = self.cli.demands
            demands.available_repos = True
            demands.sack_activation = True

        def run_on_module(self):
            self.base.repo_module_dict.print_what_provides(self.opts.module_nsvp)

    SUBCMDS = {ListSubCommand, InfoSubCommand, EnableSubCommand,
               DisableSubCommand, InstallSubCommand, UpdateSubCommand,
               RemoveSubCommand, ProfileInfoSubCommand, StreamsSubCommand, ProvidesSubCommand}

    SUBCMDS_NOT_REQUIRED_ARG = {ListSubCommand, StreamsSubCommand}

    aliases = ("module",)
    summary = _("Interact with Modules.")

    def __init__(self, cli):
        super(ModuleCommand, self).__init__(cli)
        subcmd_objs = (subcmd(cli) for subcmd in self.SUBCMDS)
        self.subcmd = None
        self._subcmd_name2obj = {
            alias: subcmd for subcmd in subcmd_objs for alias in subcmd.aliases}

    def set_argparser(self, parser):
        subcommand_help = [subcmd.aliases[0] for subcmd in self.SUBCMDS]
        parser.add_argument('subcmd', nargs=1, choices=subcommand_help)
        parser.add_argument('module_nsvp', nargs='*')

        narrows = parser.add_mutually_exclusive_group()
        narrows.add_argument('--enabled', dest='enabled',
                             action='store_true',
                             help=_("show only enabled modules"))
        narrows.add_argument('--disabled', dest='disabled',
                             action='store_true',
                             help=_("show only disabled modules"))
        narrows.add_argument('--installed', dest='installed',
                             action='store_true',
                             help=_("show only installed modules"))
        narrows.add_argument('--profile', dest='profile',
                             action='store_true',
                             help=_("show profile content"))
        narrows.add_argument('--autoenable', dest='autoenable',
                             action='store_true',
                             help=_("auto enable stream"))

    def configure(self):
        try:
            self.subcmd = self._subcmd_name2obj[self.opts.subcmd[0]]
        except (CliError, KeyError):
            self.cli.optparser.print_usage()
            raise CliError
        self.subcmd.opts = self.opts
        self.subcmd.configure()

    def run(self):
        self.check_required_argument()
        self.subcmd.run_on_module()

    def check_required_argument(self):
        not_required_argument = [alias
                                 for subcmd in self.SUBCMDS_NOT_REQUIRED_ARG
                                 for alias in subcmd.aliases]
        if self.opts.subcmd[0] not in not_required_argument:
            if not self.opts.module_nsvp:
                raise CliError(
                    "dnf {} {}: too few arguments".format(self.opts.command[0],
                                                          self.opts.subcmd[0]))
Beispiel #46
0
    def do_transaction(self, display=()):
        """Take care of package downloading, checking, user
        confirmation and actually running the transaction.

        :param display: `TransactionDisplay` object(s)
        :return: a numeric return code, and optionally a list of
           errors.  A negative return code indicates that errors
           occurred in the pre-transaction checks
        """

        grp_diff = self._groups_diff()
        grp_str = self.output.list_group_transaction(self.comps, grp_diff)
        if grp_str:
            logger.info(grp_str)
        trans = self.transaction
        pkg_str = self.output.list_transaction(trans)
        if pkg_str:
            logger.info(pkg_str)

        if trans:
            # Check which packages have to be downloaded
            downloadpkgs = []
            rmpkgs = []
            stuff_to_download = False
            install_only = True
            for tsi in trans:
                installed = tsi.installed
                if installed is not None:
                    stuff_to_download = True
                    downloadpkgs.append(installed)
                erased = tsi.erased
                if erased is not None:
                    install_only = False
                    rmpkgs.append(erased)

            # Close the connection to the rpmdb so that rpm doesn't hold the
            # SIGINT handler during the downloads.
            del self.ts

            # report the total download size to the user
            if not stuff_to_download:
                self.output.reportRemoveSize(rmpkgs)
            else:
                self.output.reportDownloadSize(downloadpkgs, install_only)

        if trans or (grp_diff and not grp_diff.empty()):
            # confirm with user
            if self._promptWanted():
                if self.conf.assumeno or not self.output.userconfirm():
                    raise CliError(_("Operation aborted."))
        else:
            logger.info(_('Nothing to do.'))
            return

        if trans:
            if downloadpkgs:
                logger.info(_('Downloading Packages:'))
            try:
                total_cb = self.output.download_callback_total_cb
                self.download_packages(downloadpkgs, self.output.progress,
                                       total_cb)
            except dnf.exceptions.DownloadError as e:
                specific = dnf.cli.format.indent_block(ucd(e))
                errstring = _('Error downloading packages:\n%s') % specific
                raise dnf.exceptions.Error(errstring)
            # Check GPG signatures
            self.gpgsigcheck(downloadpkgs)

        if not isinstance(display, collections.Sequence):
            display = [display]
        display = [output.CliTransactionDisplay()] + list(display)
        super(BaseCli, self).do_transaction(display)
        if trans:
            msg = self.output.post_transaction_output(trans)
            logger.info(msg)
Beispiel #47
0
 def display_info(self, apkg_adv_insts, mixed, description):
     """Display the details about available advisories."""
     info = self._info(apkg_adv_insts).items()
     # Convert objects to string lines and mark verbose fields.
     verbse = lambda value: value if self.base.conf.verbose else None
     info = (
         (tit, ([id_], [self.TYPE2LABEL[typ]], [unicode(upd)],
                (id_title[0] + ' - ' + id_title[1] for id_title in bzs),
                (id_title[0] for id_title in cvs), desc.splitlines(),
                verbse(rigs.splitlines() if rigs else None), verbse(fils),
                None if not mixed else [_('true') if ins else _('false')]))
         for tit, (id_, typ, upd, bzs, cvs, desc, rigs, fils, ins) in info)
     labels = (_('Update ID'), _('Type'), _('Updated'), _('Bugs'),
               _('CVEs'), _('Description'), _('Rights'), _('Files'),
               _('Installed'))
     width = _maxlen(labels)
     for title, vallines in info:
         print('=' * 79)
         print('  ' + title)
         print('=' * 79)
         for label, lines in zip(labels, vallines):
             if lines is None:
                 continue
             # Use the label only for the first item. For the remaining
             # items, use an empty label.
             labels_ = chain([label], itertools.repeat(''))
             for label_, line in zip(labels_, lines):
                 print('%*s : %s' % (width, label_, line))
         print()
Beispiel #48
0
 def _ensure_sanity(self):
     """Make sure the input db is valid."""
     if 'GROUPS' in self.db and 'ENVIRONMENTS' in self.db:
         return
     logger.warning(_('Invalid groups database, clearing.'))
     self.db = self._empty_db()
Beispiel #49
0
    def _addYumBasicOptions(self):
        # All defaults need to be a None, so we can always tell whether the user
        # has set something or whether we are getting a default.
        self.conflict_handler = "resolve"
        self.conflict_handler = "error"

        self.add_argument('--allowerasing',
                          action='store_true',
                          default=None,
                          help=_('allow erasing of installed packages to '
                                 'resolve dependencies'))
        self.add_argument("-b",
                          "--best",
                          action="store_true",
                          default=None,
                          help=_("try the best available package versions in "
                                 "transactions."))
        self.add_argument("-C",
                          "--cacheonly",
                          dest="cacheonly",
                          action="store_true",
                          default=None,
                          help=_("run entirely from system cache, "
                                 "don't update cache"))
        self.add_argument("-c",
                          "--config",
                          dest="conffile",
                          default=None,
                          metavar='[config file]',
                          help=_("config file location"))
        self.add_argument("-d",
                          "--debuglevel",
                          dest="debuglevel",
                          metavar='[debug level]',
                          default=None,
                          help=_("debugging output level"),
                          type=int)
        self.add_argument("--debugsolver",
                          action="store_true",
                          default=None,
                          help=_("dumps detailed solving results into files"))
        self.add_argument("--showduplicates",
                          dest="showdupesfromrepos",
                          action="store_true",
                          default=None,
                          help=_("show duplicates, in repos, "
                                 "in list/search commands"))
        self.add_argument("-e",
                          "--errorlevel",
                          default=None,
                          type=int,
                          help=_("error output level"))
        self.add_argument("--rpmverbosity",
                          default=None,
                          help=_("debugging output level for rpm"),
                          metavar='[debug level name]')
        self.add_argument("-q",
                          "--quiet",
                          dest="quiet",
                          action="store_true",
                          default=None,
                          help=_("quiet operation"))
        self.add_argument("-v",
                          "--verbose",
                          action="store_true",
                          default=None,
                          help=_("verbose operation"))
        self.add_argument("-y",
                          "--assumeyes",
                          action="store_true",
                          default=None,
                          help=_("answer yes for all questions"))
        self.add_argument("--assumeno",
                          action="store_true",
                          default=None,
                          help=_("answer no for all questions"))
        self.add_argument("--version",
                          action="store_true",
                          default=None,
                          help=_("show DNF version and exit"))
        self.add_argument("--installroot",
                          help=_("set install root"),
                          metavar='[path]')
        self.add_argument("--enablerepo",
                          action=self._RepoCallback,
                          dest='repos_ed',
                          default=[],
                          metavar='[repo]')
        self.add_argument("--disablerepo",
                          action=self._RepoCallback,
                          dest='repos_ed',
                          default=[],
                          metavar='[repo]')
        self.add_argument("-x",
                          "--exclude",
                          default=[],
                          dest='excludepkgs',
                          action=self._SplitCallback,
                          help=_("exclude packages by name or glob"),
                          metavar='[package]')
        self.add_argument("--disableexcludes",
                          default=[],
                          dest="disable_excludes",
                          action=self._SplitCallback,
                          help=_("disable excludes"),
                          metavar='[repo]')
        self.add_argument(
            "--obsoletes",
            action="store_true",
            default=None,
            help=_("enable obsoletes processing during upgrades"))
        self.add_argument("--noplugins",
                          action="store_false",
                          default=None,
                          dest='plugins',
                          help=_("disable all plugins"))
        self.add_argument("--nogpgcheck",
                          action="store_true",
                          default=None,
                          help=_("disable gpg signature checking"))
        self.add_argument("--disableplugin",
                          dest="disableplugins",
                          default=[],
                          action=self._SplitCallback,
                          help=_("disable plugins by name"),
                          metavar='[plugin]')
        self.add_argument("--color",
                          dest="color",
                          default=None,
                          help=_("control whether color is used"))
        self.add_argument("--releasever",
                          default=None,
                          help=_("override the value of $releasever in config"
                                 " and repo files"))
        self.add_argument("--setopt",
                          dest="setopts",
                          default=[],
                          action="append",
                          help=_("set arbitrary config and repo options"))
        self.add_argument("--refresh",
                          dest="freshest_metadata",
                          action="store_true")
        self.add_argument("-4",
                          dest="ip_resolve",
                          default=None,
                          help=_("resolve to IPv4 addresses only"),
                          action="store_const",
                          const='ipv4')
        self.add_argument("-6",
                          dest="ip_resolve",
                          default=None,
                          help=_("resolve to IPv6 addresses only"),
                          action="store_const",
                          const='ipv6')
        # we add our own help option, so we can control that help is not shown
        # automatic when we do the .parse_known_args(args)
        # but first after plugins are loaded.
        self.add_argument('-h',
                          '--help',
                          action="store_true",
                          help="show help")
Beispiel #50
0
class UpdateInfoCommand(commands.Command):
    """Implementation of the UpdateInfo command."""

    TYPE2LABEL = {hawkey.ADVISORY_BUGFIX: _('bugfix'),
                  hawkey.ADVISORY_ENHANCEMENT: _('enhancement'),
                  hawkey.ADVISORY_SECURITY: _('security'),
                  hawkey.ADVISORY_UNKNOWN: _('unknown'),
                  hawkey.ADVISORY_NEWPACKAGE: _('newpackage')}

    aliases = ['updateinfo']
    summary = _('display advisories about packages')

    def __init__(self, cli):
        """Initialize the command."""
        super(UpdateInfoCommand, self).__init__(cli)
        self._ina2evr_cache = None
        self.clear_installed_cache()

    def refresh_installed_cache(self):
        """Fill the cache of installed packages."""
        self._ina2evr_cache = {(pkg.name, pkg.arch): pkg.evr
                               for pkg in self.base.sack.query().installed()}

    def clear_installed_cache(self):
        """Clear the cache of installed packages."""
        self._ina2evr_cache = None

    def _older_installed(self, apackage):
        """Test whether an older version of a package is installed."""
        # Non-cached lookup not implemented. Fill the cache or implement the
        # functionality via the slow sack query.
        assert self._ina2evr_cache is not None
        try:
            ievr = self._ina2evr_cache[(apackage.name, apackage.arch)]
        except KeyError:
            return False
        q = self.base.sack.query().filter(name=apackage.name, evr=apackage.evr)
        if len(self.base._merge_update_filters(q, warning=False)) == 0:
            return False
        return self.base.sack.evr_cmp(ievr, apackage.evr) < 0

    def _newer_equal_installed(self, apkg):
        """Test whether a newer or equal version of a package is installed."""
        # Non-cached lookup not implemented. Fill the cache or implement the
        # functionality via the slow sack query.
        assert self._ina2evr_cache is not None
        try:
            ievr = self._ina2evr_cache[(apkg.name, apkg.arch)]
        except KeyError:
            return False
        q = self.base.sack.query().filter(name=apkg.name, evr=apkg.evr)
        if len(self.base._merge_update_filters(q, warning=False)) == 0:
            return False
        return self.base.sack.evr_cmp(ievr, apkg.evr) >= 0

    def _any_installed(self, apkg):
        """Test whether any version of a package is installed."""
        # Non-cached lookup not implemented. Fill the cache or implement the
        # functionality via the slow sack query.
        assert self._ina2evr_cache is not None
        q = self.base.sack.query().filter(name=apkg.name, evr=apkg.evr)
        if len(self.base._merge_update_filters(q, warning=False)) == 0:
            return False
        return (apkg.name, apkg.arch) in self._ina2evr_cache

    @staticmethod
    def set_argparser(parser):
        cmds = ['summary', 'list', 'info']
        parser.add_argument('spec', nargs='*', metavar='SPEC',
                            choices=cmds, default=cmds[0],
                            action=OptionParser.PkgNarrowCallback)

    def configure(self):
        """Do any command-specific configuration based on command arguments."""
        self.cli.demands.available_repos = True
        self.cli.demands.sack_activation = True

    @staticmethod
    def _apackage_advisory_match(apackage, advisory, specs=()):
        """Test whether an (adv. pkg., adv.) pair matches specifications."""

        if not specs:
            return True

        specs = set(specs)
        types = set()
        if 'bugfix' in specs:
            types.add(hawkey.ADVISORY_BUGFIX)
        if 'enhancement' in specs:
            types.add(hawkey.ADVISORY_ENHANCEMENT)
        if {'security', 'sec'} & specs:
            types.add(hawkey.ADVISORY_SECURITY)
        if 'newpackage' in specs:
            types.add(hawkey.ADVISORY_NEWPACKAGE)

        return (any(fnmatch.fnmatchcase(advisory.id, pat) for pat in specs) or
                advisory.type in types or
                any(fnmatch.fnmatchcase(apackage.name, pat) for pat in specs))

    def _apackage_advisory_installeds(self, pkgs, cmptype, req_apkg, specs=()):
        """Return (adv. package, advisory, installed) triplets and a flag."""
        for package in pkgs:
            for advisory in package.get_advisories(cmptype):
                for apackage in advisory.packages:
                    passed = (req_apkg(apackage) and
                              self._apackage_advisory_match(
                                  apackage, advisory, specs))
                    if passed:
                        installed = self._newer_equal_installed(apackage)
                        yield apackage, advisory, installed

    def available_apkg_adv_insts(self, specs=()):
        """Return available (adv. package, adv., inst.) triplets and a flag."""
        return False, self._apackage_advisory_installeds(
            self.base.sack.query().installed(), hawkey.GT,
            self._older_installed, specs)

    def installed_apkg_adv_insts(self, specs=()):
        """Return installed (adv. package, adv., inst.) triplets and a flag."""
        return False, self._apackage_advisory_installeds(
            self.base.sack.query().installed(), hawkey.LT | hawkey.EQ,
            self._newer_equal_installed, specs)

    def updating_apkg_adv_insts(self, specs=()):
        """Return updating (adv. package, adv., inst.) triplets and a flag."""
        return False, self._apackage_advisory_installeds(
            self.base.sack.query().filter(upgradable=True), hawkey.GT,
            self._older_installed, specs)

    def all_apkg_adv_insts(self, specs=()):
        """Return installed (adv. package, adv., inst.) triplets and a flag."""
        ipackages = self.base.sack.query().installed()
        gttriplets = self._apackage_advisory_installeds(
            ipackages, hawkey.GT, self._any_installed, specs)
        lteqtriplets = self._apackage_advisory_installeds(
            ipackages, hawkey.LT | hawkey.EQ, self._any_installed, specs)
        return True, chain(gttriplets, lteqtriplets)

    @staticmethod
    def _summary(apkg_adv_insts):
        """Make the summary of advisories."""
        # Remove duplicate advisory IDs. We assume that the ID is unique within
        # a repository and two advisories with the same IDs in different
        # repositories must have the same type.
        id2type = {pkadin[1].id: pkadin[1].type for pkadin in apkg_adv_insts}
        return collections.Counter(id2type.values())

    @classmethod
    def display_summary(cls, apkg_adv_insts, mixed, description):
        """Display the summary of advisories."""
        typ2cnt = cls._summary(apkg_adv_insts)
        if not typ2cnt:
            return
        print(_('Updates Information Summary: ') + description)
        # Convert types to strings and order the entries.
        label_counts = [
            (_('New Package notice(s)'), typ2cnt[hawkey.ADVISORY_NEWPACKAGE]),
            (_('Security notice(s)'), typ2cnt[hawkey.ADVISORY_SECURITY]),
            (_('Bugfix notice(s)'), typ2cnt[hawkey.ADVISORY_BUGFIX]),
            (_('Enhancement notice(s)'), typ2cnt[hawkey.ADVISORY_ENHANCEMENT]),
            (_('other notice(s)'), typ2cnt[hawkey.ADVISORY_UNKNOWN])]
        # Convert counts to strings and skip missing types.
        label2value = OrderedDict(
            (label, unicode(count)) for label, count in label_counts if count)
        width = _maxlen(label2value.values())
        for label, value in label2value.items():
            print('    %*s %s' % (width, value, label))

    @staticmethod
    def _list(apkg_adv_insts):
        """Make the list of advisories."""
        # Get ((NEVRA, installed), advisory ID, advisory type)
        apkg2nevra = lambda apkg: apkg.name + '-' + apkg.evr + '.' + apkg.arch
        nevrains_id_types = (
            ((apkg2nevra(apkg), inst), adv.id, adv.type)
            for apkg, adv, inst in apkg_adv_insts)
        # Sort and group by (NEVRA, installed).
        nevrains_nits = itertools.groupby(
            sorted(nevrains_id_types, key=itemgetter(0)), key=itemgetter(0))
        for nevra_ins, nits in nevrains_nits:
            # Remove duplicate IDs. We assume that two advisories with the same
            # IDs (e.g. from different repositories) must have the same type.
            yield nevra_ins, {nit[1]: nit[2] for nit in nits}

    @classmethod
    def display_list(cls, apkg_adv_insts, mixed, description):
        """Display the list of advisories."""
        # Sort IDs and convert types to labels.
        inst2mark = lambda inst: '' if not mixed else 'i ' if inst else '  '
        nevramark2id2tlbl = OrderedDict(
            ((nevra, inst2mark(inst)),
             OrderedDict(sorted(((id_, cls.TYPE2LABEL[typ])
                                 for id_, typ in id2type.items()),
                                key=itemgetter(0))))
            for (nevra, inst), id2type in cls._list(apkg_adv_insts))
        if not nevramark2id2tlbl:
            return
        # Get all advisory IDs and types as two iterables.
        ids, tlbls = zip(*chain.from_iterable(
            id2tlbl.items() for id2tlbl in nevramark2id2tlbl.values()))
        idw, tlw = _maxlen(ids), _maxlen(tlbls)
        for (nevra, mark), id2tlbl in nevramark2id2tlbl.items():
            for id_, tlbl in id2tlbl.items():
                print('%s%-*s %-*s %s' % (mark, idw, id_, tlw, tlbl, nevra))

    def _info(self, apkg_adv_insts):
        """Make detailed information about advisories."""
        # Get mapping from identity to (title, ID, type, time, BZs, CVEs,
        # description, rights, files, installed). This way we get rid of
        # unneeded advisory packages given with the advisories and we remove
        # duplicate advisories (that SPEEDS UP the information extraction
        # because the advisory attribute getters are expensive, so we won't get
        # the attributes multiple times). We cannot use a set because
        # advisories are not hashable.
        getrefs = lambda apkg, typ: (
            (ref.id, ref.title) for ref in apkg.references if ref.type == typ)
        id2tuple = OrderedDict()
        for apkg_adv_inst in apkg_adv_insts:
            identity, inst = id(apkg_adv_inst[1]), apkg_adv_inst[2]
            try:
                tuple_ = id2tuple[identity]
            except KeyError:
                id2tuple[identity] = (
                    apkg_adv_inst[1].title,
                    apkg_adv_inst[1].id,
                    apkg_adv_inst[1].type,
                    apkg_adv_inst[1].updated,
                    getrefs(apkg_adv_inst[1], hawkey.REFERENCE_BUGZILLA),
                    getrefs(apkg_adv_inst[1], hawkey.REFERENCE_CVE),
                    apkg_adv_inst[1].description,
                    apkg_adv_inst[1].rights,
                    (pkg.filename for pkg in apkg_adv_inst[1].packages
                     if pkg.arch in self.base.sack.list_arches()),
                    inst)
            else:
                # If the stored advisory is marked as not installed and the
                # current is marked as installed, mark the stored as installed.
                if not tuple_[9] and inst:
                    id2tuple[identity] = tuple_[:9] + (inst,)
        # Get mapping from title to (ID, type, time, BZs, CVEs, description,
        # rights, files, installed) => group by titles and merge values. We
        # assume that two advisories with the same title (e.g. from different
        # repositories) must have the same ID, type, time, description and
        # rights. References, files and installs are merged.
        merge = lambda old, new: set(chain(old, new))
        title2info = OrderedDict()
        for tuple_ in id2tuple.values():
            title, new = tuple_[0], tuple_[1:]
            old = title2info.get(
                title, (None, None, None, [], [], None, None, [], False))
            title2info[title] = (
                new[:3] +
                (merge(old[3], new[3]),
                 merge(old[4], new[4])) +
                new[5:7] +
                (merge(old[7], new[7]),
                 old[8] or new[8]))
        return title2info

    def display_info(self, apkg_adv_insts, mixed, description):
        """Display the details about available advisories."""
        info = self._info(apkg_adv_insts).items()
        # Convert objects to string lines and mark verbose fields.
        verbse = lambda value: value if self.base.conf.verbose else None
        info = (
            (tit, ([id_], [self.TYPE2LABEL[typ]], [unicode(upd)],
                   (id_title[0] + ' - ' + id_title[1] for id_title in bzs),
                   (id_title[0] for id_title in cvs), desc.splitlines(),
                   verbse(rigs.splitlines() if rigs else None), verbse(fils),
                   None if not mixed else [_('true') if ins else _('false')]))
            for tit, (id_, typ, upd, bzs, cvs, desc, rigs, fils, ins) in info)
        labels = (_('Update ID'), _('Type'), _('Updated'), _('Bugs'),
                  _('CVEs'), _('Description'), _('Rights'), _('Files'),
                  _('Installed'))
        width = _maxlen(labels)
        for title, vallines in info:
            print('=' * 79)
            print('  ' + title)
            print('=' * 79)
            for label, lines in zip(labels, vallines):
                if lines is None:
                    continue
                # Use the label only for the first item. For the remaining
                # items, use an empty label.
                labels_ = chain([label], itertools.repeat(''))
                for label_, line in zip(labels_, lines):
                    print('%*s : %s' % (width, label_, line))
            print()

    def run(self):
        """Execute the command with arguments."""
        self.cli._populate_update_security_filter(self.opts, minimal=True)

        args = self.opts.spec
        display = self.display_summary
        if self.opts.spec_action == 'list':
            display = self.display_list
        elif self.opts.spec_action == 'info':
            display = self.display_info

        self.refresh_installed_cache()

        if args[:1] == ['installed']:
            mixed, apkg_adv_insts = self.installed_apkg_adv_insts(args[1:])
            description = _('installed')
        elif args[:1] == ['updates']:
            mixed, apkg_adv_insts = self.updating_apkg_adv_insts(args[1:])
            description = _('updates')
        elif args[:1] == ['all']:
            mixed, apkg_adv_insts = self.all_apkg_adv_insts(args[1:])
            description = _('all')
        else:
            if args[:1] == ['available']:
                args = args[1:]
            mixed, apkg_adv_insts = self.available_apkg_adv_insts(args)
            description = _('available')

        display(apkg_adv_insts, mixed, description)

        self.clear_installed_cache()
Beispiel #51
0
    def configure(self, args, option_parser=None):
        """Parse command line arguments, and set up :attr:`self.base.conf` and
        :attr:`self.cmds`, as well as logger objects in base instance.

        :param args: a list of command line arguments
        :param option_parser: a class for parsing cli options
        """
        aliases = dnf.cli.aliases.Aliases()
        args = aliases.resolve(args)

        self.optparser = dnf.cli.option_parser.OptionParser() \
            if option_parser is None else option_parser
        opts = self.optparser.parse_main_args(args)

        # Just print out the version if that's what the user wanted
        if opts.version:
            print(dnf.const.VERSION)
            print_versions(self.base.conf.history_record_packages, self.base,
                           self.base.output)
            sys.exit(0)

        if opts.quiet:
            opts.debuglevel = 0
            opts.errorlevel = 2
        if opts.verbose:
            opts.debuglevel = opts.errorlevel = dnf.const.VERBOSE_LEVEL

        # Read up configuration options and initialize plugins
        try:
            if opts.cacheonly:
                self.base.conf._set_value("cachedir",
                                          self.base.conf.system_cachedir,
                                          dnf.conf.PRIO_DEFAULT)
                self.demands.cacheonly = True
            self.base.conf._configure_from_options(opts)
            self._read_conf_file(opts.releasever)
            if 'arch' in opts:
                self.base.conf.arch = opts.arch
            self.base.conf._adjust_conf_options()
        except (dnf.exceptions.ConfigError, ValueError) as e:
            logger.critical(_('Config error: %s'), e)
            sys.exit(1)
        except IOError as e:
            e = '%s: %s' % (ucd(str(e)), repr(e.filename))
            logger.critical(_('Config error: %s'), e)
            sys.exit(1)
        if opts.destdir is not None:
            self.base.conf.destdir = opts.destdir
            if not self.base.conf.downloadonly and opts.command not in (
                    'download', 'system-upgrade', 'reposync'):
                logger.critical(
                    _('--destdir or --downloaddir must be used with --downloadonly '
                      'or download or system-upgrade command.'))
                sys.exit(1)
        if (opts.set_enabled
                or opts.set_disabled) and opts.command != 'config-manager':
            logger.critical(
                _('--enable, --set-enabled and --disable, --set-disabled '
                  'must be used with config-manager command.'))
            sys.exit(1)

        if opts.sleeptime is not None:
            time.sleep(random.randrange(opts.sleeptime * 60))

        # store the main commands & summaries, before plugins are loaded
        self.optparser.add_commands(self.cli_commands, 'main')
        # store the plugin commands & summaries
        self.base.init_plugins(opts.disableplugin, opts.enableplugin, self)
        self.optparser.add_commands(self.cli_commands, 'plugin')

        # show help if no command specified
        # this is done here, because we first have the full
        # usage info after the plugins are loaded.
        if not opts.command:
            self.optparser.print_help()
            sys.exit(0)

        # save our original args out
        self.base.args = args
        # save out as a nice command string
        self.cmdstring = self.optparser.prog + ' '
        for arg in self.base.args:
            self.cmdstring += '%s ' % arg

        self._log_essentials()
        try:
            self._parse_commands(opts, args)
        except CliError:
            sys.exit(1)

        # show help for dnf <command> --help / --help-cmd
        if opts.help:
            self.optparser.print_help(self.command)
            sys.exit(0)

        opts = self.optparser.parse_command_args(self.command, args)

        if opts.allowerasing:
            self.demands.allow_erasing = opts.allowerasing
            self.base._allow_erasing = True
        if opts.freshest_metadata:
            self.demands.freshest_metadata = opts.freshest_metadata
        if opts.debugsolver:
            self.base.conf.debug_solver = True
        if opts.obsoletes:
            self.base.conf.obsoletes = True
        self.command.pre_configure()
        self.base.pre_configure_plugins()

        # with cachedir in place we can configure stuff depending on it:
        self.base._activate_persistor()

        self._configure_repos(opts)

        self.base.configure_plugins()

        self.base.conf._configure_from_options(opts)

        self.command.configure()

        if self.base.conf.destdir:
            dnf.util.ensure_dir(self.base.conf.destdir)
            self.base.repos.all().pkgdir = self.base.conf.destdir

        if self.base.conf.color != 'auto':
            self.base.output.term.reinit(color=self.base.conf.color)

        if rpm.expandMacro('%_pkgverify_level') in ('signature', 'all'):
            forcing = False
            for repo in self.base.repos.iter_enabled():
                if repo.gpgcheck:
                    continue
                repo.gpgcheck = True
                forcing = True
            if not self.base.conf.localpkg_gpgcheck:
                self.base.conf.localpkg_gpgcheck = True
                forcing = True
            if forcing:
                logger.warning(
                    _("Warning: Enforcing GPG signature check globally "
                      "as per active RPM security policy (see 'gpgcheck' in "
                      "dnf.conf(5) for how to squelch this message)"))
Beispiel #52
0
class ReinstallCommand(commands.Command):
    """A class containing methods needed by the cli to execute the reinstall command.
    """

    aliases = ('reinstall', 'rei', 'ri')
    summary = _('reinstall a package')

    @staticmethod
    def set_argparser(parser):
        parser.add_argument('packages',
                            nargs='+',
                            help=_('Package to reinstall'),
                            action=OptionParser.ParseSpecGroupFileCallback,
                            metavar=_('PACKAGE'))

    def configure(self):
        """Verify that conditions are met so that this command can
        run.  These include that the program is being run by the root
        user, that there are enabled repositories with gpg keys, and
        that this command is called with appropriate arguments.
        """
        demands = self.cli.demands
        demands.sack_activation = True
        demands.available_repos = True
        demands.resolving = True
        demands.root_user = True
        commands._checkGPGKey(self.base, self.cli)
        if not self.opts.filenames:
            commands._checkEnabledRepo(self.base)

    def run(self):

        # Reinstall files.
        done = False
        for pkg in self.base.add_remote_rpms(self.opts.filenames,
                                             strict=False):
            try:
                self.base.package_reinstall(pkg)
            except dnf.exceptions.MarkingError:
                logger.info(_('No match for argument: %s'),
                            self.base.output.term.bold(pkg.location))
            else:
                done = True

        # Reinstall packages.
        for pkg_spec in self.opts.pkg_specs + [
                '@' + x for x in self.opts.grp_specs
        ]:
            try:
                self.base.reinstall(pkg_spec)
            except dnf.exceptions.PackagesNotInstalledError as err:
                for pkg in err.packages:
                    logger.info(_('Package %s available, but not installed.'),
                                self.output.term.bold(pkg.name))
                    break
                logger.info(_('No match for argument: %s'),
                            self.base.output.term.bold(pkg_spec))
            except dnf.exceptions.PackagesNotAvailableError as err:
                for pkg in err.packages:
                    xmsg = ''
                    yumdb_info = self.base._yumdb.get_package(pkg)
                    if 'from_repo' in yumdb_info:
                        xmsg = _(' (from %s)') % yumdb_info.from_repo
                    msg = _('Installed package %s%s not available.')
                    logger.info(msg, self.base.output.term.bold(pkg), xmsg)
            except dnf.exceptions.MarkingError:
                assert False, 'Only the above marking errors are expected.'
            else:
                done = True

        if not done:
            raise dnf.exceptions.Error(_('Nothing to do.'))
Beispiel #53
0
def report_module_switch(switchedModules):
    msg1 = _(
        "The operation would result in switching of module '{0}' stream '{1}' to "
        "stream '{2}'")
    for moduleName, streams in switchedModules.items():
        logger.warning(msg1.format(moduleName, streams[0], streams[1]))
Beispiel #54
0
def _name_unset_wrapper(input_name):
    # returns <name-unset> for everything that evaluates to False (None, empty..)
    return input_name if input_name else _("<name-unset>")
Beispiel #55
0
def ex_Error(e):
    logger.log(dnf.logging.SUBDEBUG, '', exc_info=True)
    if e.value is not None:
        logger.critical(_('Error: %s'), ucd(e))
    return 1
Beispiel #56
0
    def do_transaction(self, display=()):
        """Take care of package downloading, checking, user
        confirmation and actually running the transaction.

        :param display: `rpm.callback.TransactionProgress` object(s)
        :return: history database transaction ID or None
        """
        if dnf.base.WITH_MODULES:
            if not self.conf.module_stream_switch:
                switchedModules = dict(
                    self._moduleContainer.getSwitchedStreams())
                if switchedModules:
                    report_module_switch(switchedModules)
                    msg = _(
                        "It is not possible to switch enabled streams of a module unless explicitly "
                        "enabled via configuration option module_stream_switch.\n"
                        "It is recommended to rather remove all installed content from the module, and "
                        "reset the module using '{prog} module reset <module_name>' command. After "
                        "you reset the module, you can install the other stream."
                    ).format(prog=dnf.util.MAIN_PROG)
                    raise dnf.exceptions.Error(msg)

        trans = self.transaction
        pkg_str = self.output.list_transaction(trans)
        if pkg_str:
            logger.info(pkg_str)

        if trans:
            # Check which packages have to be downloaded
            install_pkgs = []
            rmpkgs = []
            install_only = True
            for tsi in trans:
                if tsi.action in dnf.transaction.FORWARD_ACTIONS:
                    install_pkgs.append(tsi.pkg)
                elif tsi.action in dnf.transaction.BACKWARD_ACTIONS:
                    install_only = False
                    rmpkgs.append(tsi.pkg)

            # Close the connection to the rpmdb so that rpm doesn't hold the
            # SIGINT handler during the downloads.
            del self._ts

            # report the total download size to the user
            if not install_pkgs:
                self.output.reportRemoveSize(rmpkgs)
            else:
                self.output.reportDownloadSize(install_pkgs, install_only)

        if trans or self._moduleContainer.isChanged() or \
                (self._history and (self._history.group or self._history.env)):
            # confirm with user
            if self.conf.downloadonly:
                logger.info(
                    _("{prog} will only download packages for the transaction."
                      ).format(prog=dnf.util.MAIN_PROG_UPPER))
            elif 'test' in self.conf.tsflags:
                logger.info(
                    _("{prog} will only download packages, install gpg keys, and check the "
                      "transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
            if self._promptWanted():
                if self.conf.assumeno or not self.output.userconfirm():
                    raise CliError(_("Operation aborted."))
        else:
            logger.info(_('Nothing to do.'))
            return

        if trans:
            if install_pkgs:
                logger.info(_('Downloading Packages:'))
                try:
                    total_cb = self.output.download_callback_total_cb
                    self.download_packages(install_pkgs, self.output.progress,
                                           total_cb)
                except dnf.exceptions.DownloadError as e:
                    specific = dnf.cli.format.indent_block(ucd(e))
                    errstr = _(
                        'Error downloading packages:') + '\n%s' % specific
                    # setting the new line to prevent next chars being eaten up
                    # by carriage returns
                    print()
                    raise dnf.exceptions.Error(errstr)
            # Check GPG signatures
            self.gpgsigcheck(install_pkgs)

        if self.conf.downloadonly:
            return

        if not isinstance(display, Sequence):
            display = [display]
        display = [output.CliTransactionDisplay()] + list(display)
        tid = super(BaseCli, self).do_transaction(display)

        # display last transaction (which was closed during do_transaction())
        if tid is not None:
            trans = self.history.old([tid])[0]
            trans = dnf.db.group.RPMTransaction(self.history, trans._trans)
        else:
            trans = None

        if trans:
            # the post transaction summary is already written to log during
            # Base.do_transaction() so here only print the messages to the
            # user arranged in columns
            print()
            print('\n'.join(self.output.post_transaction_output(trans)))
            print()
            for tsi in trans:
                if tsi.state == libdnf.transaction.TransactionItemState_ERROR:
                    raise dnf.exceptions.Error(_('Transaction failed'))

        return tid
Beispiel #57
0
class ShellCommand(commands.Command, cmd.Cmd):

    aliases = ('shell', 'sh')
    summary = _('run an interactive DNF shell')

    MAPPING = {
        'repo': 'repo',
        'repository': 'repo',
        'exit': 'quit',
        'quit': 'quit',
        'run': 'ts_run',
        'ts': 'transaction',
        'transaction': 'transaction',
        'config': 'config',
        'resolvedep': 'resolve',
        'help': 'help'
    }

    def __init__(self, cli):
        commands.Command.__init__(self, cli)
        cmd.Cmd.__init__(self)
        self.prompt = '> '

    @staticmethod
    def set_argparser(parser):
        parser.add_argument('script',
                            nargs='?',
                            metavar=_('SCRIPT'),
                            help=_('Script to run in DNF shell'))

    def configure(self):
        self.cli.demands = ShellDemandSheet()

    def run(self):
        if self.opts.script:
            self._run_script(self.opts.script)
        else:
            self.cmdloop()

    def _clean(self):
        self.base._finalize_base()
        self.base._transaction = None
        self.base.fill_sack()

    def onecmd(self, line):
        if not line or line == '\n':
            return
        if line == 'EOF':
            line = 'quit'
        try:
            s_line = shlex.split(line)
        except:
            self._help()
            return
        opts = self.cli.optparser.parse_main_args(s_line)
        # Disable shell recursion.
        if opts.command == 'shell':
            return
        if opts.command in self.MAPPING:
            getattr(self, '_' + self.MAPPING[opts.command])(s_line[1::])
        else:
            cmd_cls = self.cli.cli_commands.get(opts.command)
            if cmd_cls is not None:
                cmd = cmd_cls(self.cli)
                try:
                    opts = self.cli.optparser.parse_command_args(cmd, s_line)
                    cmd.cli.demands = copy.deepcopy(self.cli.demands)
                    cmd.configure()
                    cmd.run()
                except dnf.exceptions.Error as e:
                    logger.error(_("Error:") + " " + e.value)
                except:
                    return
            else:
                self._help()

    def _config(self, args=None):
        def print_or_set(key, val, conf):
            if val:
                setattr(conf, key, val)
            else:
                try:
                    print('{}: {}'.format(key, getattr(conf, str(key))))
                except:
                    logger.warning(_('Unsupported key value.'))

        if not args or len(args) > 2:
            self._help('config')
            return

        key = args[0]
        val = args[1] if len(args) == 2 else None
        period = key.find('.')
        if period != -1:
            repo_name = key[:period]
            key = key[period + 1:]
            repos = self.base.repos.get_matching(repo_name)
            for repo in repos:
                print_or_set(key, val, repo)
            if not repos:
                logger.warning(_('Could not find repository: %s'), repo_name)
        else:
            print_or_set(key, val, self.base.conf)

    def _help(self, args=None):
        """Output help information.

        :param args: the command to output help information about. If
           *args* is an empty, general help will be output.
        """
        arg = args[0] if isinstance(args, list) and len(args) > 0 else args
        msg = None

        if arg:
            if arg == 'config':
                msg = _("""{} arg [value]
  arg: debuglevel, errorlevel, obsoletes, gpgcheck, assumeyes, exclude,
        repo_id.gpgcheck, repo_id.exclude
    If no value is given it prints the current value.
    If value is given it sets that value.""").format(arg)

            elif arg == 'help':
                msg = _("""{} [command]
    print help""").format(arg)

            elif arg in ['repo', 'repository']:
                msg = _("""{} arg [option]
  list: lists repositories and their status. option = [all | id | glob]
  enable: enable repositories. option = repository id
  disable: disable repositories. option = repository id""").format(arg)

            elif arg == 'resolvedep':
                msg = _("""{}
    resolve the transaction set""").format(arg)

            elif arg in ['transaction', 'ts']:
                msg = _("""{} arg
  list: lists the contents of the transaction
  reset: reset (zero-out) the transaction
  run: run the transaction""").format(arg)

            elif arg == 'run':
                msg = _("""{}
    run the transaction""").format(arg)

            elif arg in ['exit', 'quit']:
                msg = _("""{}
    exit the shell""").format(arg)

        if not msg:
            self.cli.optparser.print_help()
            msg = _("""Shell specific arguments:

config                   set config options
help                     print help
repository (or repo)     enable, disable or list repositories
resolvedep               resolve the transaction set
transaction (or ts)      list, reset or run the transaction set
run                      resolve and run the transaction set
exit (or quit)           exit the shell""")

        print('\n' + msg)

    def _repo(self, args=None):
        cmd = args[0] if args else None

        if cmd in ['list', None]:
            self.onecmd('repolist ' + ' '.join(args[1:]))

        elif cmd in ['enable', 'disable']:
            repos = self.cli.base.repos
            fill_sack = False
            for repo in args[1::]:
                r = repos.get_matching(repo)
                if r:
                    getattr(r, cmd)()
                    fill_sack = True
                else:
                    logger.critical(
                        _("Error:") + " " + _("Unknown repo: '%s'"),
                        self.base.output.term.bold(repo))
            if fill_sack:
                self.base.fill_sack()

        else:
            self._help('repo')

    def _resolve(self, args=None):
        if self.cli.base.transaction is None:
            try:
                self.cli.base.resolve(self.cli.demands.allow_erasing)
            except dnf.exceptions.DepsolveError as e:
                print(e)

    def _run_script(self, file):
        try:
            with open(file, 'r') as fd:
                lines = fd.readlines()
                for line in lines:
                    if not line.startswith('#'):
                        self.onecmd(line)
        except IOError:
            logger.info(_('Error: Cannot open %s for reading'),
                        self.base.output.term.bold(file))
            sys.exit(1)

    def _transaction(self, args=None):
        cmd = args[0] if args else None

        if cmd == 'reset':
            self._clean()
            return

        self._resolve()
        if cmd in ['list', None]:
            if self.base._transaction:
                out = self.base.output.list_transaction(self.base._transaction)
                logger.info(out)

        elif cmd == 'run':
            try:
                self.base.do_transaction()
            except:
                pass
            self._clean()

        else:
            self._help('transaction')

    def _ts_run(self, args=None):
        self._transaction(['run'])

    def _quit(self, args=None):
        logger.info(_('Leaving Shell'))
        sys.exit(0)
Beispiel #58
0
 def _option_conflict(self, option_string_1, option_string_2):
     print(self.optparser.print_usage())
     raise dnf.exceptions.Error(
         _("argument {}: not allowed with argument {}".format(
             option_string_1, option_string_2)))
Beispiel #59
0
 def _quit(self, args=None):
     logger.info(_('Leaving Shell'))
     sys.exit(0)
Beispiel #60
0
 def set_argparser(parser):
     parser.add_argument('script',
                         nargs='?',
                         metavar=_('SCRIPT'),
                         help=_('Script to run in DNF shell'))