Blame dnf/cli/output.py

Packit Service 21c75c
# Copyright 2005 Duke University
Packit Service 21c75c
# Copyright (C) 2012-2016 Red Hat, Inc.
Packit Service 21c75c
#
Packit Service 21c75c
# This program is free software; you can redistribute it and/or modify
Packit Service 21c75c
# it under the terms of the GNU General Public License as published by
Packit Service 21c75c
# the Free Software Foundation; either version 2 of the License, or
Packit Service 21c75c
# (at your option) any later version.
Packit Service 21c75c
#
Packit Service 21c75c
# This program is distributed in the hope that it will be useful,
Packit Service 21c75c
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 21c75c
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 21c75c
# GNU Library General Public License for more details.
Packit Service 21c75c
#
Packit Service 21c75c
# You should have received a copy of the GNU General Public License
Packit Service 21c75c
# along with this program; if not, write to the Free Software
Packit Service 21c75c
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 21c75c
Packit Service 21c75c
"""Handle actual output from the cli."""
Packit Service 21c75c
Packit Service 21c75c
from __future__ import absolute_import
Packit Service 21c75c
from __future__ import print_function
Packit Service 21c75c
from __future__ import unicode_literals
Packit Service 21c75c
Packit Service 21c75c
import fnmatch
Packit Service 21c75c
import hawkey
Packit Service 21c75c
import itertools
Packit Service 21c75c
import libdnf.transaction
Packit Service 21c75c
import logging
Packit Service 21c75c
import operator
Packit Service 21c75c
import pwd
Packit Service 21c75c
import re
Packit Service 21c75c
import sys
Packit Service 21c75c
import time
Packit Service 21c75c
Packit Service 21c75c
from dnf.cli.format import format_number, format_time
Packit Service 21c75c
from dnf.i18n import _, C_, P_, ucd, fill_exact_width, textwrap_fill, exact_width, select_short_long
Packit Service 21c75c
from dnf.pycomp import xrange, basestring, long, unicode, sys_maxsize
Packit Service a86e0b
from dnf.yum.rpmtrans import TransactionDisplay
Packit Service 21c75c
from dnf.db.history import MergedTransactionWrapper
Packit Service 21c75c
import dnf.base
Packit Service 21c75c
import dnf.callback
Packit Service 21c75c
import dnf.cli.progress
Packit Service 21c75c
import dnf.cli.term
Packit Service 21c75c
import dnf.conf
Packit Service 21c75c
import dnf.crypto
Packit Service 21c75c
import dnf.i18n
Packit Service 21c75c
import dnf.transaction
Packit Service 21c75c
import dnf.util
Packit Service 21c75c
import dnf.yum.misc
Packit Service 21c75c
Packit Service 21c75c
logger = logging.getLogger('dnf')
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _spread_in_columns(cols_count, label, lst):
Packit Service 21c75c
    left = itertools.chain((label,), itertools.repeat(''))
Packit Service 21c75c
    lst_length = len(lst)
Packit Service 21c75c
    right_count = cols_count - 1
Packit Service 21c75c
    missing_items = -lst_length % right_count
Packit Service 21c75c
    if not lst_length:
Packit Service 21c75c
        lst = itertools.repeat('', right_count)
Packit Service 21c75c
    elif missing_items:
Packit Service 21c75c
        lst.extend(('',) * missing_items)
Packit Service 21c75c
    lst_iter = iter(lst)
Packit Service 21c75c
    return list(zip(left, *[lst_iter] * right_count))
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
class Output(object):
Packit Service 21c75c
    """Main output class for the yum command line."""
Packit Service 21c75c
Packit Service 21c75c
    GRP_PACKAGE_INDENT = ' ' * 3
Packit Service 21c75c
    FILE_PROVIDE_RE = re.compile(r'^\*{0,2}/')
Packit Service 21c75c
Packit Service 21c75c
    def __init__(self, base, conf):
Packit Service 21c75c
        self.conf = conf
Packit Service 21c75c
        self.base = base
Packit Service 21c75c
        self.term = dnf.cli.term.Term()
Packit Service 21c75c
        self.progress = None
Packit Service 21c75c
Packit Service 21c75c
    def _banner(self, col_data, row):
Packit Service 21c75c
        term_width = self.term.columns
Packit Service 21c75c
        rule = '%s' % '=' * term_width
Packit Service 21c75c
        header = self.fmtColumns(zip(row, col_data), ' ')
Packit Service 21c75c
        return rule, header, rule
Packit Service 21c75c
Packit Service 21c75c
    def _col_widths(self, rows):
Packit Service 21c75c
        col_data = [dict() for _ in rows[0]]
Packit Service 21c75c
        for row in rows:
Packit Service 21c75c
            for (i, val) in enumerate(row):
Packit Service 21c75c
                col_dct = col_data[i]
Packit Service 21c75c
                length = len(val)
Packit Service 21c75c
                col_dct[length] = col_dct.get(length, 0) + 1
Packit Service 21c75c
        cols = self.calcColumns(col_data, None, indent='  ')
Packit Service 21c75c
        # align to the left
Packit Service 21c75c
        return list(map(operator.neg, cols))
Packit Service 21c75c
Packit Service 21c75c
    def _highlight(self, highlight):
Packit Service 21c75c
        hibeg = ''
Packit Service 21c75c
        hiend = ''
Packit Service 21c75c
        if not highlight:
Packit Service 21c75c
            pass
Packit Service 21c75c
        elif not isinstance(highlight, basestring) or highlight == 'bold':
Packit Service 21c75c
            hibeg = self.term.MODE['bold']
Packit Service 21c75c
        elif highlight == 'normal':
Packit Service 21c75c
            pass # Minor opt.
Packit Service 21c75c
        else:
Packit Service 21c75c
            # Turn a string into a specific output: colour, bold, etc.
Packit Service 21c75c
            for high in highlight.replace(',', ' ').split():
Packit Service 21c75c
                if high == 'normal':
Packit Service 21c75c
                    hibeg = ''
Packit Service 21c75c
                elif high in self.term.MODE:
Packit Service 21c75c
                    hibeg += self.term.MODE[high]
Packit Service 21c75c
                elif high in self.term.FG_COLOR:
Packit Service 21c75c
                    hibeg += self.term.FG_COLOR[high]
Packit Service 21c75c
                elif (high.startswith('fg:') and
Packit Service 21c75c
                      high[3:] in self.term.FG_COLOR):
Packit Service 21c75c
                    hibeg += self.term.FG_COLOR[high[3:]]
Packit Service 21c75c
                elif (high.startswith('bg:') and
Packit Service 21c75c
                      high[3:] in self.term.BG_COLOR):
Packit Service 21c75c
                    hibeg += self.term.BG_COLOR[high[3:]]
Packit Service 21c75c
Packit Service 21c75c
        if hibeg:
Packit Service 21c75c
            hiend = self.term.MODE['normal']
Packit Service 21c75c
        return (hibeg, hiend)
Packit Service 21c75c
Packit Service 21c75c
    def _sub_highlight(self, haystack, highlight, needles, **kwds):
Packit Service 21c75c
        hibeg, hiend = self._highlight(highlight)
Packit Service 21c75c
        return self.term.sub(haystack, hibeg, hiend, needles, **kwds)
Packit Service 21c75c
Packit Service 21c75c
    @staticmethod
Packit Service 21c75c
    def _calc_columns_spaces_helps(current, data_tups, left):
Packit Service 21c75c
        """ Spaces left on the current field will help how many pkgs? """
Packit Service 21c75c
        ret = 0
Packit Service 21c75c
        for tup in data_tups:
Packit Service 21c75c
            if left < (tup[0] - current):
Packit Service 21c75c
                break
Packit Service 21c75c
            ret += tup[1]
Packit Service 21c75c
        return ret
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def history(self):
Packit Service 21c75c
        return self.base.history
Packit Service 21c75c
Packit Service 21c75c
    @property
Packit Service 21c75c
    def sack(self):
Packit Service 21c75c
        return self.base.sack
Packit Service 21c75c
Packit Service 21c75c
    def calcColumns(self, data, columns=None, remainder_column=0,
Packit Service 21c75c
                    total_width=None, indent=''):
Packit Service 21c75c
        """Dynamically calculate the widths of the columns that the
Packit Service 21c75c
        fields in data should be placed into for output.
Packit Service 21c75c
Packit Service 21c75c
        :param data: a list of dictionaries that represent the data to
Packit Service 21c75c
           be output.  Each dictionary in the list corresponds to a
Packit Service 21c75c
           column of output. The keys of the dictionary are the
Packit Service 21c75c
           lengths of the items to be output, and the value associated
Packit Service 21c75c
           with a key is the number of items of that length.
Packit Service 21c75c
        :param columns: a list containing the minimum amount of space
Packit Service 21c75c
           that must be allocated for each row. This can be used to
Packit Service 21c75c
           ensure that there is space available in a column if, for
Packit Service 21c75c
           example, the actual lengths of the items being output
Packit Service 21c75c
           cannot be given in *data*
Packit Service 21c75c
        :param remainder_column: number of the column to receive a few
Packit Service 21c75c
           extra spaces that may remain after other allocation has
Packit Service 21c75c
           taken place
Packit Service 21c75c
        :param total_width: the total width of the output.
Packit Service 21c75c
           self.term.real_columns is used by default
Packit Service 21c75c
        :param indent: string that will be prefixed to a line of
Packit Service 21c75c
           output to create e.g. an indent
Packit Service 21c75c
        :return: a list of the widths of the columns that the fields
Packit Service 21c75c
           in data should be placed into for output
Packit Service 21c75c
        """
Packit Service 21c75c
        cols = len(data)
Packit Service 21c75c
        # Convert the data to ascending list of tuples, (field_length, pkgs)
Packit Service 21c75c
        pdata = data
Packit Service 21c75c
        data = [None] * cols # Don't modify the passed in data
Packit Service 21c75c
        for d in range(0, cols):
Packit Service 21c75c
            data[d] = sorted(pdata[d].items())
Packit Service 21c75c
Packit Service 21c75c
        if total_width is None:
Packit Service 21c75c
            total_width = self.term.real_columns
Packit Service 21c75c
Packit Service 21c75c
        #  We start allocating 1 char to everything but the last column, and a
Packit Service 21c75c
        # space between each (again, except for the last column). Because
Packit Service 21c75c
        # at worst we are better with:
Packit Service 21c75c
        # |one two three|
Packit Service 21c75c
        # | four        |
Packit Service 21c75c
        # ...than:
Packit Service 21c75c
        # |one two three|
Packit Service 21c75c
        # |            f|
Packit Service 21c75c
        # |our          |
Packit Service 21c75c
        # ...the later being what we get if we pre-allocate the last column, and
Packit Service 21c75c
        # thus. the space, due to "three" overflowing it's column by 2 chars.
Packit Service 21c75c
        if columns is None:
Packit Service 21c75c
            columns = [1] * (cols - 1)
Packit Service 21c75c
            columns.append(0)
Packit Service 21c75c
Packit Service 21c75c
        # i'm not able to get real terminal width so i'm probably
Packit Service 21c75c
        # running in non interactive terminal (pipe to grep, redirect to file...)
Packit Service 21c75c
        # avoid splitting lines to enable filtering output
Packit Service 21c75c
        if not total_width:
Packit Service 21c75c
            full_columns = []
Packit Service 21c75c
            for d in xrange(0, cols):
Packit Service 21c75c
                col = data[d]
Packit Service 21c75c
                if col:
Packit Service 21c75c
                    full_columns.append(col[-1][0])
Packit Service 21c75c
                else:
Packit Service 21c75c
                    full_columns.append(columns[d] + 1)
Packit Service 21c75c
            full_columns[0] += len(indent)
Packit Service 21c75c
            # if possible, try to keep default width (usually 80 columns)
Packit Service 21c75c
            default_width = self.term.columns
Packit Service 21c75c
            if sum(full_columns) > default_width:
Packit Service 21c75c
                return full_columns
Packit Service 21c75c
            total_width = default_width
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
        total_width -= (sum(columns) + (cols - 1) + exact_width(indent))
Packit Service 21c75c
        if not columns[-1]:
Packit Service 21c75c
            total_width += 1
Packit Service 21c75c
        while total_width > 0:
Packit Service 21c75c
            # Find which field all the spaces left will help best
Packit Service 21c75c
            helps = 0
Packit Service 21c75c
            val = 0
Packit Service 21c75c
            for d in xrange(0, cols):
Packit Service 21c75c
                thelps = self._calc_columns_spaces_helps(columns[d], data[d],
Packit Service 21c75c
                                                         total_width)
Packit Service 21c75c
                if not thelps:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                #  We prefer to overflow: the last column, and then earlier
Packit Service 21c75c
                # columns. This is so that in the best case (just overflow the
Packit Service 21c75c
                # last) ... grep still "works", and then we make it prettier.
Packit Service 21c75c
                if helps and (d == (cols - 1)) and (thelps / 2) < helps:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                if thelps < helps:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                helps = thelps
Packit Service 21c75c
                val = d
Packit Service 21c75c
Packit Service 21c75c
            #  If we found a column to expand, move up to the next level with
Packit Service 21c75c
            # that column and start again with any remaining space.
Packit Service 21c75c
            if helps:
Packit Service 21c75c
                diff = data[val].pop(0)[0] - columns[val]
Packit Service 21c75c
                if not columns[val] and (val == (cols - 1)):
Packit Service 21c75c
                    #  If we are going from 0 => N on the last column, take 1
Packit Service 21c75c
                    # for the space before the column.
Packit Service 21c75c
                    total_width -= 1
Packit Service 21c75c
                columns[val] += diff
Packit Service 21c75c
                total_width -= diff
Packit Service 21c75c
                continue
Packit Service 21c75c
Packit Service 21c75c
            overflowed_columns = 0
Packit Service 21c75c
            for d in xrange(0, cols):
Packit Service 21c75c
                if not data[d]:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                overflowed_columns += 1
Packit Service 21c75c
            if overflowed_columns:
Packit Service 21c75c
                #  Split the remaining spaces among each overflowed column
Packit Service 21c75c
                # equally
Packit Service 21c75c
                norm = total_width // overflowed_columns
Packit Service 21c75c
                for d in xrange(0, cols):
Packit Service 21c75c
                    if not data[d]:
Packit Service 21c75c
                        continue
Packit Service 21c75c
                    columns[d] += norm
Packit Service 21c75c
                    total_width -= norm
Packit Service 21c75c
Packit Service 21c75c
            #  Split the remaining spaces among each column equally, except the
Packit Service 21c75c
            # last one. And put the rest into the remainder column
Packit Service 21c75c
            cols -= 1
Packit Service 21c75c
            norm = total_width // cols
Packit Service 21c75c
            for d in xrange(0, cols):
Packit Service 21c75c
                columns[d] += norm
Packit Service 21c75c
            columns[remainder_column] += total_width - (cols * norm)
Packit Service 21c75c
            total_width = 0
Packit Service 21c75c
Packit Service 21c75c
        return columns
Packit Service 21c75c
Packit Service 21c75c
    @staticmethod
Packit Service 21c75c
    def _fmt_column_align_width(width):
Packit Service 21c75c
        """Returns tuple of (align_left, width)"""
Packit Service 21c75c
        if width < 0:
Packit Service 21c75c
            return (True, -width)
Packit Service 21c75c
        return (False, width)
Packit Service 21c75c
Packit Service 21c75c
    def _col_data(self, col_data):
Packit Service 21c75c
        assert len(col_data) == 2 or len(col_data) == 3
Packit Service 21c75c
        if len(col_data) == 2:
Packit Service 21c75c
            (val, width) = col_data
Packit Service 21c75c
            hibeg = hiend = ''
Packit Service 21c75c
        if len(col_data) == 3:
Packit Service 21c75c
            (val, width, highlight) = col_data
Packit Service 21c75c
            (hibeg, hiend) = self._highlight(highlight)
Packit Service 21c75c
        return (ucd(val), width, hibeg, hiend)
Packit Service 21c75c
Packit Service 21c75c
    def fmtColumns(self, columns, msg=u'', end=u''):
Packit Service 21c75c
        """Return a row of data formatted into a string for output.
Packit Service 21c75c
        Items can overflow their columns.
Packit Service 21c75c
Packit Service 21c75c
        :param columns: a list of tuples containing the data to
Packit Service 21c75c
           output.  Each tuple contains first the item to be output,
Packit Service 21c75c
           then the amount of space allocated for the column, and then
Packit Service 21c75c
           optionally a type of highlighting for the item
Packit Service 21c75c
        :param msg: a string to begin the line of output with
Packit Service 21c75c
        :param end: a string to end the line of output with
Packit Service 21c75c
        :return: a row of data formatted into a string for output
Packit Service 21c75c
        """
Packit Service 21c75c
        columns = list(columns)
Packit Service 21c75c
        total_width = len(msg)
Packit Service 21c75c
        data = []
Packit Service 21c75c
        for col_data in columns[:-1]:
Packit Service 21c75c
            (val, width, hibeg, hiend) = self._col_data(col_data)
Packit Service 21c75c
Packit Service 21c75c
            if not width: # Don't count this column, invisible text
Packit Service 21c75c
                msg += u"%s"
Packit Service 21c75c
                data.append(val)
Packit Service 21c75c
                continue
Packit Service 21c75c
Packit Service 21c75c
            (align_left, width) = self._fmt_column_align_width(width)
Packit Service 21c75c
            val_width = exact_width(val)
Packit Service 21c75c
            if val_width <= width:
Packit Service 21c75c
                #  Don't use fill_exact_width() because it sucks performance
Packit Service 21c75c
                # wise for 1,000s of rows. Also allows us to use len(), when
Packit Service 21c75c
                # we can.
Packit Service 21c75c
                msg += u"%s%s%s%s "
Packit Service 21c75c
                if align_left:
Packit Service 21c75c
                    data.extend([hibeg, val, " " * (width - val_width), hiend])
Packit Service 21c75c
                else:
Packit Service 21c75c
                    data.extend([hibeg, " " * (width - val_width), val, hiend])
Packit Service 21c75c
            else:
Packit Service 21c75c
                msg += u"%s%s%s\n" + " " * (total_width + width + 1)
Packit Service 21c75c
                data.extend([hibeg, val, hiend])
Packit Service 21c75c
            total_width += width
Packit Service 21c75c
            total_width += 1
Packit Service 21c75c
        (val, width, hibeg, hiend) = self._col_data(columns[-1])
Packit Service 21c75c
        (align_left, width) = self._fmt_column_align_width(width)
Packit Service 21c75c
        val = fill_exact_width(val, width, left=align_left,
Packit Service 21c75c
                              prefix=hibeg, suffix=hiend)
Packit Service 21c75c
        msg += u"%%s%s" % end
Packit Service 21c75c
        data.append(val)
Packit Service 21c75c
        return msg % tuple(data)
Packit Service 21c75c
Packit Service 21c75c
    def simpleList(self, pkg, ui_overflow=False, indent='', highlight=False,
Packit Service 21c75c
                   columns=None):
Packit Service 21c75c
        """Print a package as a line.
Packit Service 21c75c
Packit Service 21c75c
        :param pkg: the package to be printed
Packit Service 21c75c
        :param ui_overflow: unused
Packit Service 21c75c
        :param indent: string to be prefixed onto the line to provide
Packit Service 21c75c
           e.g. an indent
Packit Service 21c75c
        :param highlight: highlighting options for the name of the
Packit Service 21c75c
           package
Packit Service 21c75c
        :param columns: tuple containing the space allocated for each
Packit Service 21c75c
           column of output.  The columns are the package name, version,
Packit Service 21c75c
           and repository
Packit Service 21c75c
        """
Packit Service 21c75c
        if columns is None:
Packit Service 21c75c
            columns = (-40, -22, -16) # Old default
Packit Service 21c75c
        na = '%s%s.%s' % (indent, pkg.name, pkg.arch)
Packit Service 21c75c
        hi_cols = [highlight, 'normal', 'normal']
Packit Service 21c75c
Packit Service 21c75c
        columns = zip((na, pkg.evr, pkg._from_repo), columns, hi_cols)
Packit Service 21c75c
        print(self.fmtColumns(columns))
Packit Service 21c75c
Packit Service 21c75c
    def simpleEnvraList(self, pkg, ui_overflow=False,
Packit Service 21c75c
                        indent='', highlight=False, columns=None):
Packit Service 21c75c
        """Print a package as a line, with the package itself in envra
Packit Service 21c75c
        format so it can be passed to list/install/etc.
Packit Service 21c75c
Packit Service 21c75c
        :param pkg: the package to be printed
Packit Service 21c75c
        :param ui_overflow: unused
Packit Service 21c75c
        :param indent: string to be prefixed onto the line to provide
Packit Service 21c75c
           e.g. an indent
Packit Service 21c75c
        :param highlight: highlighting options for the name of the
Packit Service 21c75c
           package
Packit Service 21c75c
        :param columns: tuple containing the space allocated for each
Packit Service 21c75c
           column of output.  The columns the are the package envra and
Packit Service 21c75c
           repository
Packit Service 21c75c
        """
Packit Service 21c75c
        if columns is None:
Packit Service 21c75c
            columns = (-63, -16) # Old default
Packit Service 21c75c
        envra = '%s%s' % (indent, ucd(pkg))
Packit Service 21c75c
        hi_cols = [highlight, 'normal', 'normal']
Packit Service 21c75c
        rid = pkg.ui_from_repo
Packit Service 21c75c
        columns = zip((envra, rid), columns, hi_cols)
Packit Service 21c75c
        print(self.fmtColumns(columns))
Packit Service 21c75c
Packit Service 21c75c
    def simple_name_list(self, pkg):
Packit Service 21c75c
        """Print a package as a line containing its name."""
Packit Service 21c75c
        print(ucd(pkg.name))
Packit Service 21c75c
Packit Service 21c75c
    def simple_nevra_list(self, pkg):
Packit Service 21c75c
        """Print a package as a line containing its NEVRA."""
Packit Service 21c75c
        print(ucd(pkg))
Packit Service 21c75c
Packit Service 21c75c
    def fmtKeyValFill(self, key, val):
Packit Service 21c75c
        """Return a key value pair in the common two column output
Packit Service 21c75c
        format.
Packit Service 21c75c
Packit Service 21c75c
        :param key: the key to be formatted
Packit Service 21c75c
        :param val: the value associated with *key*
Packit Service 21c75c
        :return: the key value pair formatted in two columns for output
Packit Service 21c75c
        """
Packit Service 21c75c
        keylen = exact_width(key)
Packit Service 21c75c
        cols = self.term.real_columns
Packit Service 21c75c
        if not cols:
Packit Service 21c75c
            cols = sys_maxsize
Packit Service 21c75c
        elif cols < 20:
Packit Service 21c75c
            cols = 20
Packit Service 21c75c
        nxt = ' ' * (keylen - 2) + ': '
Packit Service 21c75c
        if not val:
Packit Service 21c75c
            # textwrap.fill in case of empty val returns empty string
Packit Service 21c75c
            return key
Packit Service 21c75c
        val = ucd(val)
Packit Service 21c75c
        ret = textwrap_fill(val, width=cols, initial_indent=key,
Packit Service 21c75c
                            subsequent_indent=nxt)
Packit Service 21c75c
        if ret.count("\n") > 1 and keylen > (cols // 3):
Packit Service 21c75c
            # If it's big, redo it again with a smaller subsequent off
Packit Service 21c75c
            ret = textwrap_fill(val, width=cols, initial_indent=key,
Packit Service 21c75c
                                subsequent_indent='     ...: ')
Packit Service 21c75c
        return ret
Packit Service 21c75c
Packit Service 21c75c
    def fmtSection(self, name, fill='='):
Packit Service 21c75c
        """Format and return a section header.  The format of the
Packit Service 21c75c
        header is a line with *name* centered, and *fill* repeated on
Packit Service 21c75c
        either side to fill an entire line on the terminal.
Packit Service 21c75c
Packit Service 21c75c
        :param name: the name of the section
Packit Service 21c75c
        :param fill: the character to repeat on either side of *name*
Packit Service 21c75c
          to fill an entire line.  *fill* must be a single character.
Packit Service 21c75c
        :return: a string formatted to be a section header
Packit Service 21c75c
        """
Packit Service 21c75c
        name = ucd(name)
Packit Service 21c75c
        cols = self.term.columns - 2
Packit Service 21c75c
        name_len = exact_width(name)
Packit Service 21c75c
        if name_len >= (cols - 4):
Packit Service 21c75c
            beg = end = fill * 2
Packit Service 21c75c
        else:
Packit Service 21c75c
            beg = fill * ((cols - name_len) // 2)
Packit Service 21c75c
            end = fill * (cols - name_len - len(beg))
Packit Service 21c75c
Packit Service 21c75c
        return "%s %s %s" % (beg, name, end)
Packit Service 21c75c
Packit Service 21c75c
    def infoOutput(self, pkg, highlight=False):
Packit Service 21c75c
        """Print information about the given package.
Packit Service 21c75c
Packit Service 21c75c
        :param pkg: the package to print information about
Packit Service 21c75c
        :param highlight: highlighting options for the name of the
Packit Service 21c75c
           package
Packit Service 21c75c
        """
Packit Service 21c75c
        def format_key_val(key, val):
Packit Service 21c75c
            return " ".join([fill_exact_width(key, 12, 12), ":", str(val)])
Packit Service 21c75c
Packit Service 21c75c
        def format_key_val_fill(key, val):
Packit Service 21c75c
            return self.fmtKeyValFill(fill_exact_width(key, 12, 12) + " : ", val or "")
Packit Service 21c75c
Packit Service 21c75c
        output_list = []
Packit Service 21c75c
        (hibeg, hiend) = self._highlight(highlight)
Packit Service 21c75c
        # Translators: This is abbreviated 'Name'. Should be no longer
Packit Service 21c75c
        # than 12 characters. You can use the full version if it is short
Packit Service 21c75c
        # enough in your language.
Packit Service 21c75c
        key = select_short_long(12, C_("short", "Name"),
Packit Service 21c75c
                                    C_("long", "Name"))
Packit Service 21c75c
        output_list.append(format_key_val(key,
Packit Service 21c75c
                                          "%s%s%s" % (hibeg, pkg.name, hiend)))
Packit Service 21c75c
        if pkg.epoch:
Packit Service 21c75c
            # Translators: This message should be no longer than 12 characters.
Packit Service 21c75c
            output_list.append(format_key_val(_("Epoch"), pkg.epoch))
Packit Service 21c75c
        key = select_short_long(12, C_("short", "Version"),
Packit Service 21c75c
                                    C_("long", "Version"))
Packit Service 21c75c
        output_list.append(format_key_val(key, pkg.version))
Packit Service 21c75c
        # Translators: This message should be no longer than 12 characters.
Packit Service 21c75c
        output_list.append(format_key_val(_("Release"), pkg.release))
Packit Service 21c75c
        key = select_short_long(12, C_("short", "Arch"),
Packit Service 21c75c
                                    C_("long", "Architecture"))
Packit Service 21c75c
        output_list.append(format_key_val(key, pkg.arch))
Packit Service 21c75c
        key = select_short_long(12, C_("short", "Size"), C_("long", "Size"))
Packit Service 21c75c
        output_list.append(format_key_val(key,
Packit Service 21c75c
                                          format_number(float(pkg._size))))
Packit Service 21c75c
        # Translators: This message should be no longer than 12 characters.
Packit Service 21c75c
        output_list.append(format_key_val(_("Source"), pkg.sourcerpm))
Packit Service 21c75c
        key = select_short_long(12, C_("short", "Repo"),
Packit Service 21c75c
                                    C_("long", "Repository"))
Packit Service 21c75c
        output_list.append(format_key_val(key, pkg.repoid))
Packit Service 21c75c
Packit Service 21c75c
        if pkg._from_system:
Packit Service 21c75c
            history_repo = self.history.repo(pkg)
Packit Service 21c75c
            if history_repo:
Packit Service 21c75c
                # Translators: This message should be no longer than 12 chars.
Packit Service 21c75c
                output_list.append(format_key_val(_("From repo"), history_repo))
Packit Service 21c75c
        if self.conf.verbose:
Packit Service 21c75c
            # :hawkey does not support changelog information
Packit Service 21c75c
            # print(_("Committer   : %s") % ucd(pkg.committer))
Packit Service 21c75c
            # print(_("Committime  : %s") % time.ctime(pkg.committime))
Packit Service 21c75c
            # Translators: This message should be no longer than 12 characters.
Packit Service 21c75c
            output_list.append(format_key_val(_("Packager"), pkg.packager))
Packit Service 21c75c
            # Translators: This message should be no longer than 12 characters.
Packit Service 21c75c
            output_list.append(format_key_val(_("Buildtime"),
Packit Service 21c75c
                                              dnf.util.normalize_time(pkg.buildtime)))
Packit Service 21c75c
            if pkg.installtime:
Packit Service 21c75c
            # Translators: This message should be no longer than 12 characters.
Packit Service 21c75c
                output_list.append(format_key_val(_("Install time"),
Packit Service 21c75c
                                                  dnf.util.normalize_time(pkg.installtime)))
Packit Service 21c75c
            history_pkg = self.history.package_data(pkg)
Packit Service 21c75c
            if history_pkg:
Packit Service 21c75c
                try:
Packit Service 21c75c
                    uid = int(history_pkg._item.getInstalledBy())
Packit Service 21c75c
                except ValueError: # In case int() fails
Packit Service 21c75c
                    uid = None
Packit Service 21c75c
                # Translators: This message should be no longer than 12 chars.
Packit Service 21c75c
                output_list.append(format_key_val(_("Installed by"), self._pwd_ui_username(uid)))
Packit Service 21c75c
        # Translators: This is abbreviated 'Summary'. Should be no longer
Packit Service 21c75c
        # than 12 characters. You can use the full version if it is short
Packit Service 21c75c
        # enough in your language.
Packit Service 21c75c
        key = select_short_long(12, C_("short", "Summary"),
Packit Service 21c75c
                                    C_("long", "Summary"))
Packit Service 21c75c
        output_list.append(format_key_val_fill(key, pkg.summary))
Packit Service 21c75c
        if pkg.url:
Packit Service 21c75c
            output_list.append(format_key_val(_("URL"), ucd(pkg.url)))
Packit Service 21c75c
        # Translators: This message should be no longer than 12 characters.
Packit Service 21c75c
        output_list.append(format_key_val_fill(_("License"), pkg.license))
Packit Service 21c75c
        # Translators: This is abbreviated 'Description'. Should be no longer
Packit Service 21c75c
        # than 12 characters. You can use the full version if it is short
Packit Service 21c75c
        # enough in your language.
Packit Service 21c75c
        key = select_short_long(12, C_("short", "Description"),
Packit Service 21c75c
                                    C_("long", "Description"))
Packit Service 21c75c
        output_list.append(format_key_val_fill(key, pkg.description))
Packit Service 21c75c
        return "\n".join(output_list)
Packit Service 21c75c
Packit Service 21c75c
    def updatesObsoletesList(self, uotup, changetype, columns=None):
Packit Service 21c75c
        """Print a simple string that explains the relationship
Packit Service 21c75c
        between the members of an update or obsoletes tuple.
Packit Service 21c75c
Packit Service 21c75c
        :param uotup: an update or obsoletes tuple.  The first member
Packit Service 21c75c
           is the new package, and the second member is the old
Packit Service 21c75c
           package
Packit Service 21c75c
        :param changetype: a string indicating what the change between
Packit Service 21c75c
           the packages is, e.g. 'updates' or 'obsoletes'
Packit Service 21c75c
        :param columns: a tuple containing information about how to
Packit Service 21c75c
           format the columns of output.  The absolute value of each
Packit Service 21c75c
           number in the tuple indicates how much space has been
Packit Service 21c75c
           allocated for the corresponding column.  If the number is
Packit Service 21c75c
           negative, the text in the column will be left justified,
Packit Service 21c75c
           and if it is positive, the text will be right justified.
Packit Service 21c75c
           The columns of output are the package name, version, and repository
Packit Service 21c75c
        """
Packit Service 21c75c
        (changePkg, instPkg) = uotup
Packit Service 21c75c
Packit Service 21c75c
        if columns is not None:
Packit Service 21c75c
            # New style, output all info. for both old/new with old indented
Packit Service 21c75c
            chi = self.conf.color_update_remote
Packit Service 21c75c
            if changePkg.reponame != hawkey.SYSTEM_REPO_NAME:
Packit Service 21c75c
                chi = self.conf.color_update_local
Packit Service 21c75c
            self.simpleList(changePkg, columns=columns, highlight=chi)
Packit Service 21c75c
            self.simpleList(instPkg, columns=columns, indent=' ' * 4,
Packit Service 21c75c
                            highlight=self.conf.color_update_installed)
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        # Old style
Packit Service 21c75c
        c_compact = changePkg.compactPrint()
Packit Service 21c75c
        i_compact = '%s.%s' % (instPkg.name, instPkg.arch)
Packit Service 21c75c
        c_repo = changePkg.repoid
Packit Service 21c75c
        print('%-35.35s [%.12s] %.10s %-20.20s' %
Packit Service 21c75c
              (c_compact, c_repo, changetype, i_compact))
Packit Service 21c75c
Packit Service 21c75c
    def listPkgs(self, lst, description, outputType, highlight_na={},
Packit Service 21c75c
                 columns=None, highlight_modes={}):
Packit Service 21c75c
        """Prints information about the given list of packages.
Packit Service 21c75c
Packit Service 21c75c
        :param lst: a list of packages to print information about
Packit Service 21c75c
        :param description: string describing what the list of
Packit Service 21c75c
           packages contains, e.g. 'Available Packages'
Packit Service 21c75c
        :param outputType: The type of information to be printed.
Packit Service 21c75c
           Current options::
Packit Service 21c75c
Packit Service 21c75c
              'list' - simple pkg list
Packit Service 21c75c
              'info' - similar to rpm -qi output
Packit Service 21c75c
              'name' - simple name list
Packit Service 21c75c
              'nevra' - simple nevra list
Packit Service 21c75c
        :param highlight_na: a dictionary containing information about
Packit Service 21c75c
              packages that should be highlighted in the output.  The
Packit Service 21c75c
              dictionary keys are (name, arch) tuples for the package,
Packit Service 21c75c
              and the associated values are the package objects
Packit Service 21c75c
              themselves.
Packit Service 21c75c
        :param columns: a tuple containing information about how to
Packit Service 21c75c
           format the columns of output.  The absolute value of each
Packit Service 21c75c
           number in the tuple indicates how much space has been
Packit Service 21c75c
           allocated for the corresponding column.  If the number is
Packit Service 21c75c
           negative, the text in the column will be left justified,
Packit Service 21c75c
           and if it is positive, the text will be right justified.
Packit Service 21c75c
           The columns of output are the package name, version, and
Packit Service 21c75c
           repository
Packit Service 21c75c
        :param highlight_modes: dictionary containing information
Packit Service 21c75c
              about to highlight the packages in *highlight_na*.
Packit Service 21c75c
              *highlight_modes* should contain the following keys::
Packit Service 21c75c
Packit Service 21c75c
                 'not_in' - highlighting used for packages not in *highlight_na*
Packit Service 21c75c
                 '=' - highlighting used when the package versions are equal
Packit Service 21c75c
                 '<' - highlighting used when the package has a lower version
Packit Service 21c75c
                       number
Packit Service 21c75c
                 '>' - highlighting used when the package has a higher version
Packit Service 21c75c
                       number
Packit Service 2bb387
        :return: number of packages listed
Packit Service 21c75c
        """
Packit Service 21c75c
        if outputType in ['list', 'info', 'name', 'nevra']:
Packit Service 21c75c
            if len(lst) > 0:
Packit Service 21c75c
                print('%s' % description)
Packit Service 21c75c
                info_set = set()
Packit Service 21c75c
                if outputType == 'list':
Packit Service 21c75c
                    unique_item_dict = {}
Packit Service 21c75c
                    for pkg in lst:
Packit Service 21c75c
                        unique_item_dict[str(pkg) + str(pkg._from_repo)] = pkg
Packit Service 21c75c
Packit Service 21c75c
                    lst = unique_item_dict.values()
Packit Service 21c75c
Packit Service 21c75c
                for pkg in sorted(lst):
Packit Service 21c75c
                    key = (pkg.name, pkg.arch)
Packit Service 21c75c
                    highlight = False
Packit Service 21c75c
                    if key not in highlight_na:
Packit Service 21c75c
                        highlight = highlight_modes.get('not in', 'normal')
Packit Service 21c75c
                    elif pkg.evr_eq(highlight_na[key]):
Packit Service 21c75c
                        highlight = highlight_modes.get('=', 'normal')
Packit Service 21c75c
                    elif pkg.evr_lt(highlight_na[key]):
Packit Service 21c75c
                        highlight = highlight_modes.get('>', 'bold')
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        highlight = highlight_modes.get('<', 'normal')
Packit Service 21c75c
Packit Service 21c75c
                    if outputType == 'list':
Packit Service 21c75c
                        self.simpleList(pkg, ui_overflow=True,
Packit Service 21c75c
                                        highlight=highlight, columns=columns)
Packit Service 21c75c
                    elif outputType == 'info':
Packit Service 21c75c
                        info_set.add(self.infoOutput(pkg, highlight=highlight) + "\n")
Packit Service 21c75c
                    elif outputType == 'name':
Packit Service 21c75c
                        self.simple_name_list(pkg)
Packit Service 21c75c
                    elif outputType == 'nevra':
Packit Service 21c75c
                        self.simple_nevra_list(pkg)
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        pass
Packit Service 21c75c
Packit Service 21c75c
                if info_set:
Packit Service 21c75c
                    print("\n".join(sorted(info_set)))
Packit Service 21c75c
Packit Service 2bb387
            return len(lst)
Packit Service 21c75c
Packit Service 21c75c
    def userconfirm(self, msg=None, defaultyes_msg=None):
Packit Service 21c75c
        """Get a yes or no from the user, and default to No
Packit Service 21c75c
Packit Service 21c75c
        :msg: String for case with [y/N]
Packit Service 21c75c
        :defaultyes_msg: String for case with [Y/n]
Packit Service 21c75c
        :return: True if the user selects yes, and False if the user
Packit Service 21c75c
           selects no
Packit Service 21c75c
        """
Packit Service 21c75c
        yui = (ucd(_('y')), ucd(_('yes')))
Packit Service 21c75c
        nui = (ucd(_('n')), ucd(_('no')))
Packit Service 21c75c
        aui = yui + nui
Packit Service 21c75c
        while True:
Packit Service 21c75c
            if msg is None:
Packit Service 21c75c
                msg = _('Is this ok [y/N]: ')
Packit Service 21c75c
            choice = ''
Packit Service 21c75c
            if self.conf.defaultyes:
Packit Service 21c75c
                if defaultyes_msg is None:
Packit Service 21c75c
                    msg = _('Is this ok [Y/n]: ')
Packit Service 21c75c
                else:
Packit Service 21c75c
                    msg = defaultyes_msg
Packit Service 21c75c
            try:
Packit Service 21c75c
                choice = dnf.i18n.ucd_input(msg)
Packit Service 21c75c
            except EOFError:
Packit Service 21c75c
                pass
Packit Service 21c75c
            except KeyboardInterrupt:
Packit Service 21c75c
                choice = nui[0]
Packit Service 21c75c
            choice = ucd(choice).lower()
Packit Service 21c75c
            if len(choice) == 0:
Packit Service 21c75c
                choice = yui[0] if self.conf.defaultyes else nui[0]
Packit Service 21c75c
            if choice in aui:
Packit Service 21c75c
                break
Packit Service 21c75c
Packit Service 21c75c
            # If the English one letter names don't mix with the translated
Packit Service 21c75c
            # letters, allow them too:
Packit Service 21c75c
            if u'y' == choice and u'y' not in aui:
Packit Service 21c75c
                choice = yui[0]
Packit Service 21c75c
                break
Packit Service 21c75c
            if u'n' == choice and u'n' not in aui:
Packit Service 21c75c
                choice = nui[0]
Packit Service 21c75c
                break
Packit Service 21c75c
Packit Service 21c75c
        if choice in yui:
Packit Service 21c75c
            return True
Packit Service 21c75c
        return False
Packit Service 21c75c
Packit Service 21c75c
    def _pkgs2name_dict(self, sections):
Packit Service 21c75c
        installed = self.sack.query().installed()._name_dict()
Packit Service 21c75c
        available = self.sack.query().available()._name_dict()
Packit Service 21c75c
Packit Service 21c75c
        d = {}
Packit Service 21c75c
        for pkg_name in itertools.chain(*list(zip(*sections))[1]):
Packit Service 21c75c
            if pkg_name in installed:
Packit Service 21c75c
                d[pkg_name] = installed[pkg_name][0]
Packit Service 21c75c
            elif pkg_name in available:
Packit Service 21c75c
                d[pkg_name] = available[pkg_name][0]
Packit Service 21c75c
        return d
Packit Service 21c75c
Packit Service 21c75c
    def _pkgs2col_lengths(self, sections, name_dict):
Packit Service 21c75c
        nevra_lengths = {}
Packit Service 21c75c
        repo_lengths = {}
Packit Service 21c75c
        for pkg_name in itertools.chain(*list(zip(*sections))[1]):
Packit Service 21c75c
            pkg = name_dict.get(pkg_name)
Packit Service 21c75c
            if pkg is None:
Packit Service 21c75c
                continue
Packit Service 21c75c
            nevra_l = exact_width(ucd(pkg)) + exact_width(self.GRP_PACKAGE_INDENT)
Packit Service 21c75c
            repo_l = exact_width(ucd(pkg.reponame))
Packit Service 21c75c
            nevra_lengths[nevra_l] = nevra_lengths.get(nevra_l, 0) + 1
Packit Service 21c75c
            repo_lengths[repo_l] = repo_lengths.get(repo_l, 0) + 1
Packit Service 21c75c
        return (nevra_lengths, repo_lengths)
Packit Service 21c75c
Packit Service 21c75c
    def _display_packages(self, pkg_names):
Packit Service 21c75c
        for name in pkg_names:
Packit Service 21c75c
            print('%s%s' % (self.GRP_PACKAGE_INDENT, name))
Packit Service 21c75c
Packit Service 21c75c
    def _display_packages_verbose(self, pkg_names, name_dict, columns):
Packit Service 21c75c
        for name in pkg_names:
Packit Service 21c75c
            try:
Packit Service 21c75c
                pkg = name_dict[name]
Packit Service 21c75c
            except KeyError:
Packit Service 21c75c
                # package not in any repo -> print only package name
Packit Service 21c75c
                print('%s%s' % (self.GRP_PACKAGE_INDENT, name))
Packit Service 21c75c
                continue
Packit Service 21c75c
            highlight = False
Packit Service 21c75c
            if not pkg._from_system:
Packit Service 21c75c
                highlight = self.conf.color_list_available_install
Packit Service 21c75c
            self.simpleEnvraList(pkg, ui_overflow=True,
Packit Service 21c75c
                                 indent=self.GRP_PACKAGE_INDENT,
Packit Service 21c75c
                                 highlight=highlight,
Packit Service 21c75c
                                 columns=columns)
Packit Service 21c75c
Packit Service 21c75c
    def display_pkgs_in_groups(self, group):
Packit Service 21c75c
        """Output information about the packages in a given group
Packit Service 21c75c
Packit Service 21c75c
        :param group: a Group object to output information about
Packit Service 21c75c
        """
Packit Service 21c75c
        def names(packages):
Packit Service 21c75c
            return sorted(pkg.name for pkg in packages)
Packit Service 21c75c
        print('\n' + _('Group: %s') % group.ui_name)
Packit Service 21c75c
Packit Service 21c75c
        verbose = self.conf.verbose
Packit Service 21c75c
        if verbose:
Packit Service 21c75c
            print(_(' Group-Id: %s') % ucd(group.id))
Packit Service 21c75c
        if group.ui_description:
Packit Service 21c75c
            print(_(' Description: %s') % ucd(group.ui_description) or "")
Packit Service 21c75c
        if group.lang_only:
Packit Service 21c75c
            print(_(' Language: %s') % group.lang_only)
Packit Service 21c75c
Packit Service 21c75c
        sections = (
Packit Service 21c75c
            (_(' Mandatory Packages:'), names(group.mandatory_packages)),
Packit Service 21c75c
            (_(' Default Packages:'), names(group.default_packages)),
Packit Service 21c75c
            (_(' Optional Packages:'), names(group.optional_packages)),
Packit Service 21c75c
            (_(' Conditional Packages:'), names(group.conditional_packages)))
Packit Service 21c75c
        if verbose:
Packit Service 21c75c
            name_dict = self._pkgs2name_dict(sections)
Packit Service 21c75c
            col_lengths = self._pkgs2col_lengths(sections, name_dict)
Packit Service 21c75c
            columns = self.calcColumns(col_lengths)
Packit Service 21c75c
            columns = (-columns[0], -columns[1])
Packit Service 21c75c
            for (section_name, packages) in sections:
Packit Service 21c75c
                if len(packages) < 1:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                print(section_name)
Packit Service 21c75c
                self._display_packages_verbose(packages, name_dict, columns)
Packit Service 21c75c
        else:
Packit Service 21c75c
            for (section_name, packages) in sections:
Packit Service 21c75c
                if len(packages) < 1:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                print(section_name)
Packit Service 21c75c
                self._display_packages(packages)
Packit Service 21c75c
Packit Service 21c75c
    def display_groups_in_environment(self, environment):
Packit Service 21c75c
        """Output information about the packages in a given environment
Packit Service 21c75c
Packit Service 21c75c
        :param environment: an Environment object to output information about
Packit Service 21c75c
        """
Packit Service 21c75c
        def names(groups):
Packit Service 21c75c
            return sorted(group.name for group in groups)
Packit Service 21c75c
        print(_('Environment Group: %s') % environment.ui_name)
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.verbose:
Packit Service 21c75c
            print(_(' Environment-Id: %s') % ucd(environment.id))
Packit Service 21c75c
        if environment.ui_description:
Packit Service 21c75c
            description = ucd(environment.ui_description) or ""
Packit Service 21c75c
            print(_(' Description: %s') % description)
Packit Service 21c75c
Packit Service 21c75c
        sections = (
Packit Service 21c75c
            (_(' Mandatory Groups:'), names(environment.mandatory_groups)),
Packit Service 21c75c
            (_(' Optional Groups:'), names(environment.optional_groups)))
Packit Service 21c75c
        for (section_name, packages) in sections:
Packit Service 21c75c
            if len(packages) < 1:
Packit Service 21c75c
                continue
Packit Service 21c75c
            print(section_name)
Packit Service 21c75c
            self._display_packages(packages)
Packit Service 21c75c
Packit Service 21c75c
    def matchcallback(self, po, values, matchfor=None, verbose=None,
Packit Service 21c75c
                      highlight=None):
Packit Service 21c75c
        """Output search/provides type callback matches.
Packit Service 21c75c
Packit Service 21c75c
        :param po: the package object that matched the search
Packit Service 21c75c
        :param values: the information associated with *po* that
Packit Service 21c75c
           matched the search
Packit Service 21c75c
        :param matchfor: a list of strings to be highlighted in the
Packit Service 21c75c
           output
Packit Service 21c75c
        :param verbose: whether to output extra verbose information
Packit Service 21c75c
        :param highlight: highlighting options for the highlighted matches
Packit Service 21c75c
        """
Packit Service 21c75c
        def print_highlighted_key_item(key, item, printed_headline, can_overflow=False):
Packit Service 21c75c
            if not printed_headline:
Packit Service 21c75c
                print(_('Matched from:'))
Packit Service 21c75c
            item = ucd(item) or ""
Packit Service 21c75c
            if item == "":
Packit Service 21c75c
                return
Packit Service 21c75c
            if matchfor:
Packit Service 21c75c
                item = self._sub_highlight(item, highlight, matchfor, ignore_case=True)
Packit Service 21c75c
            if can_overflow:
Packit Service 21c75c
                print(self.fmtKeyValFill(key, item))
Packit Service 21c75c
            else:
Packit Service 21c75c
                print(key % item)
Packit Service 21c75c
Packit Service 21c75c
        def print_file_provides(item, printed_match):
Packit Service 21c75c
            if not self.FILE_PROVIDE_RE.match(item):
Packit Service 21c75c
                return False
Packit Service 21c75c
            key = _("Filename    : %s")
Packit Service 21c75c
            file_match = False
Packit Service 21c75c
            for filename in po.files:
Packit Service 21c75c
                if fnmatch.fnmatch(filename, item):
Packit Service 21c75c
                    print_highlighted_key_item(
Packit Service 21c75c
                        key, filename, file_match or printed_match, can_overflow=False)
Packit Service 21c75c
                    file_match = True
Packit Service 21c75c
            return file_match
Packit Service 21c75c
Packit Service 21c75c
        if self.conf.showdupesfromrepos:
Packit Service 21c75c
            msg = '%s : ' % po
Packit Service 21c75c
        else:
Packit Service 21c75c
            msg = '%s.%s : ' % (po.name, po.arch)
Packit Service 21c75c
        msg = self.fmtKeyValFill(msg, po.summary or "")
Packit Service 21c75c
        if matchfor:
Packit Service 21c75c
            if highlight is None:
Packit Service 21c75c
                highlight = self.conf.color_search_match
Packit Service 21c75c
            msg = self._sub_highlight(msg, highlight, matchfor, ignore_case=True)
Packit Service 21c75c
        print(msg)
Packit Service 21c75c
Packit Service 21c75c
        if verbose is None:
Packit Service 21c75c
            verbose = self.conf.verbose
Packit Service 21c75c
        if not verbose:
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        print(_("Repo        : %s") % po.ui_from_repo)
Packit Service 21c75c
        printed_match = False
Packit Service 21c75c
        name_match = False
Packit Service 21c75c
        for item in set(values):
Packit Service 21c75c
            if po.summary == item:
Packit Service 21c75c
                name_match = True
Packit Service 21c75c
                continue # Skip double name/summary printing
Packit Service 21c75c
Packit Service 21c75c
            if po.description == item:
Packit Service 21c75c
                key = _("Description : ")
Packit Service 21c75c
                print_highlighted_key_item(key, item, printed_match, can_overflow=True)
Packit Service 21c75c
                printed_match = True
Packit Service 21c75c
            elif po.url == item:
Packit Service 21c75c
                key = _("URL         : %s")
Packit Service 21c75c
                print_highlighted_key_item(key, item, printed_match, can_overflow=False)
Packit Service 21c75c
                printed_match = True
Packit Service 21c75c
            elif po.license == item:
Packit Service 21c75c
                key = _("License     : %s")
Packit Service 21c75c
                print_highlighted_key_item(key, item, printed_match, can_overflow=False)
Packit Service 21c75c
                printed_match = True
Packit Service 21c75c
            elif print_file_provides(item, printed_match):
Packit Service 21c75c
                printed_match = True
Packit Service 21c75c
            else:
Packit Service 21c75c
                key = _("Provide    : %s")
Packit Service 21c75c
                for provide in po.provides:
Packit Service 21c75c
                    provide = str(provide)
Packit Service 21c75c
                    if fnmatch.fnmatch(provide, item):
Packit Service 21c75c
                        print_highlighted_key_item(key, provide, printed_match, can_overflow=False)
Packit Service 21c75c
                        printed_match = True
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        first_provide = provide.split()[0]
Packit Service 21c75c
                        possible = set('=<>')
Packit Service 21c75c
                        if any((char in possible) for char in item):
Packit Service 21c75c
                            item_new = item.split()[0]
Packit Service 21c75c
                        else:
Packit Service 21c75c
                            item_new = item
Packit Service 21c75c
                        if fnmatch.fnmatch(first_provide, item_new):
Packit Service 21c75c
                            print_highlighted_key_item(
Packit Service 21c75c
                                key, provide, printed_match, can_overflow=False)
Packit Service 21c75c
                            printed_match = True
Packit Service 21c75c
Packit Service 21c75c
        if not any([printed_match, name_match]):
Packit Service 21c75c
            for item in set(values):
Packit Service 21c75c
                key = _("Other       : %s")
Packit Service 21c75c
                print_highlighted_key_item(key, item, printed_match, can_overflow=False)
Packit Service 21c75c
        print()
Packit Service 21c75c
Packit Service 21c75c
    def matchcallback_verbose(self, po, values, matchfor=None):
Packit Service 21c75c
        """Output search/provides type callback matches.  This will
Packit Service 21c75c
        output more information than :func:`matchcallback`.
Packit Service 21c75c
Packit Service 21c75c
        :param po: the package object that matched the search
Packit Service 21c75c
        :param values: the information associated with *po* that
Packit Service 21c75c
           matched the search
Packit Service 21c75c
        :param matchfor: a list of strings to be highlighted in the
Packit Service 21c75c
           output
Packit Service 21c75c
        """
Packit Service 21c75c
        return self.matchcallback(po, values, matchfor, verbose=True)
Packit Service 21c75c
Packit Service 21c75c
    def reportDownloadSize(self, packages, installonly=False):
Packit Service 21c75c
        """Report the total download size for a set of packages
Packit Service 21c75c
Packit Service 21c75c
        :param packages: a list of package objects
Packit Service 21c75c
        :param installonly: whether the transaction consists only of installations
Packit Service 21c75c
        """
Packit Service 21c75c
        totsize = 0
Packit Service 21c75c
        locsize = 0
Packit Service 21c75c
        insize = 0
Packit Service 21c75c
        error = False
Packit Service 21c75c
        for pkg in packages:
Packit Service 21c75c
            # Just to be on the safe side, if for some reason getting
Packit Service 21c75c
            # the package size fails, log the error and don't report download
Packit Service 21c75c
            # size
Packit Service 21c75c
            try:
Packit Service 21c75c
                size = int(pkg._size)
Packit Service 21c75c
                totsize += size
Packit Service 21c75c
                try:
Packit Service 21c75c
                    if pkg.verifyLocalPkg():
Packit Service 21c75c
                        locsize += size
Packit Service 21c75c
                except Exception:
Packit Service 21c75c
                    pass
Packit Service 21c75c
Packit Service 21c75c
                if not installonly:
Packit Service 21c75c
                    continue
Packit Service 21c75c
Packit Service 21c75c
                try:
Packit Service 21c75c
                    size = int(pkg.installsize)
Packit Service 21c75c
                except Exception:
Packit Service 21c75c
                    pass
Packit Service 21c75c
                insize += size
Packit Service 21c75c
            except Exception:
Packit Service 21c75c
                error = True
Packit Service 21c75c
                msg = _('There was an error calculating total download size')
Packit Service 21c75c
                logger.error(msg)
Packit Service 21c75c
                break
Packit Service 21c75c
Packit Service 21c75c
        if not error:
Packit Service 21c75c
            if locsize:
Packit Service 21c75c
                logger.info(_("Total size: %s"),
Packit Service 21c75c
                                        format_number(totsize))
Packit Service 21c75c
            if locsize != totsize:
Packit Service 21c75c
                logger.info(_("Total download size: %s"),
Packit Service 21c75c
                                        format_number(totsize - locsize))
Packit Service 21c75c
            if installonly:
Packit Service 21c75c
                logger.info(_("Installed size: %s"), format_number(insize))
Packit Service 21c75c
Packit Service 21c75c
    def reportRemoveSize(self, packages):
Packit Service 21c75c
        """Report the total size of packages being removed.
Packit Service 21c75c
Packit Service 21c75c
        :param packages: a list of package objects
Packit Service 21c75c
        """
Packit Service 21c75c
        totsize = 0
Packit Service 21c75c
        error = False
Packit Service 21c75c
        for pkg in packages:
Packit Service 21c75c
            # Just to be on the safe side, if for some reason getting
Packit Service 21c75c
            # the package size fails, log the error and don't report download
Packit Service 21c75c
            # size
Packit Service 21c75c
            try:
Packit Service 21c75c
                size = pkg._size
Packit Service 21c75c
                totsize += size
Packit Service 21c75c
            except Exception:
Packit Service 21c75c
                error = True
Packit Service 21c75c
                msg = _('There was an error calculating installed size')
Packit Service 21c75c
                logger.error(msg)
Packit Service 21c75c
                break
Packit Service 21c75c
        if not error:
Packit Service 21c75c
            logger.info(_("Freed space: %s"), format_number(totsize))
Packit Service 21c75c
Packit Service 21c75c
    def list_group_transaction(self, comps, history, diff):
Packit Service 21c75c
        if not diff:
Packit Service 21c75c
            return None
Packit Service 21c75c
Packit Service 21c75c
        out = []
Packit Service 21c75c
        rows = []
Packit Service 21c75c
        if diff.new_groups:
Packit Service 21c75c
            out.append(_('Marking packages as installed by the group:'))
Packit Service 21c75c
        for grp_id in diff.new_groups:
Packit Service 21c75c
            pkgs = list(diff.added_packages(grp_id))
Packit Service 21c75c
            group_object = comps._group_by_id(grp_id)
Packit Service 21c75c
            grp_name = group_object.ui_name if group_object else grp_id
Packit Service 21c75c
            rows.extend(_spread_in_columns(4, "@" + grp_name, pkgs))
Packit Service 21c75c
        if diff.removed_groups:
Packit Service 21c75c
            out.append(_('Marking packages as removed by the group:'))
Packit Service 21c75c
        for grp_id in diff.removed_groups:
Packit Service 21c75c
            pkgs = list(diff.removed_packages(grp_id))
Packit Service 21c75c
            grp_name = history.group.get(grp_id).ui_name
Packit Service 21c75c
            rows.extend(_spread_in_columns(4, "@" + grp_name, pkgs))
Packit Service 21c75c
Packit Service 21c75c
        if rows:
Packit Service 21c75c
            col_data = self._col_widths(rows)
Packit Service 21c75c
            for row in rows:
Packit Service 21c75c
                out.append(self.fmtColumns(zip(row, col_data), ' '))
Packit Service 21c75c
            out[0:0] = self._banner(col_data, (_('Group'), _('Packages'), '', ''))
Packit Service 21c75c
        return '\n'.join(out)
Packit Service 21c75c
Packit Service 21c75c
    def list_transaction(self, transaction, total_width=None):
Packit Service 21c75c
        """Return a string representation of the transaction in an
Packit Service 21c75c
        easy-to-read format.
Packit Service 21c75c
        """
Packit Service 21c75c
        forward_actions = hawkey.UPGRADE | hawkey.UPGRADE_ALL | hawkey.DISTUPGRADE | \
Packit Service 21c75c
            hawkey.DISTUPGRADE_ALL | hawkey.DOWNGRADE | hawkey.INSTALL
Packit Service 21c75c
        skipped_conflicts = set()
Packit Service 21c75c
        skipped_broken = set()
Packit Service 21c75c
Packit Service 21c75c
        if transaction is None:
Packit Service 21c75c
            # set empty transaction list instead of returning None
Packit Service 21c75c
            # in order to display module changes when RPM transaction is empty
Packit Service 21c75c
            transaction = []
Packit Service 21c75c
Packit Service cfdb81
        list_bunch = dnf.util._make_lists(transaction)
Packit Service 21c75c
        pkglist_lines = []
Packit Service 21c75c
        data = {'n' : {}, 'v' : {}, 'r' : {}}
Packit Service 21c75c
        a_wid = 0 # Arch can't get "that big" ... so always use the max.
Packit Service 21c75c
Packit Service 21c75c
        def _add_line(lines, data, a_wid, po, obsoletes=[]):
Packit Service 21c75c
            (n, a, e, v, r) = po.pkgtup
Packit Service 21c75c
            evr = po.evr
Packit Service 21c75c
            repoid = po._from_repo
Packit Service 21c75c
            size = format_number(po._size)
Packit Service 21c75c
Packit Service 21c75c
            if a is None: # gpgkeys are weird
Packit Service 21c75c
                a = 'noarch'
Packit Service 21c75c
Packit Service 21c75c
            # none, partial, full?
Packit Service 21c75c
            if po._from_system:
Packit Service 21c75c
                hi = self.conf.color_update_installed
Packit Service 21c75c
            elif po._from_cmdline:
Packit Service 21c75c
                hi = self.conf.color_update_local
Packit Service 21c75c
            else:
Packit Service 21c75c
                hi = self.conf.color_update_remote
Packit Service 21c75c
            lines.append((n, a, evr, repoid, size, obsoletes, hi))
Packit Service 21c75c
            #  Create a dict of field_length => number of packages, for
Packit Service 21c75c
            # each field.
Packit Service 21c75c
            for (d, v) in (("n", len(n)), ("v", len(evr)), ("r", len(repoid))):
Packit Service 21c75c
                data[d].setdefault(v, 0)
Packit Service 21c75c
                data[d][v] += 1
Packit Service 21c75c
            a_wid = max(a_wid, len(a))
Packit Service 21c75c
            return a_wid
Packit Service 21c75c
        ins_group_msg = _('Installing group/module packages') if dnf.base.WITH_MODULES \
Packit Service 21c75c
            else _('Installing group packages')
Packit Service 21c75c
Packit Service 21c75c
        for (action, pkglist) in [
Packit Service 21c75c
                # TRANSLATORS: This is for a list of packages to be installed.
Packit Service 21c75c
                (C_('summary', 'Installing'), list_bunch.installed),
Packit Service 21c75c
                # TRANSLATORS: This is for a list of packages to be upgraded.
Packit Service 21c75c
                (C_('summary', 'Upgrading'), list_bunch.upgraded),
Packit Service 21c75c
                # TRANSLATORS: This is for a list of packages to be reinstalled.
Packit Service 21c75c
                (C_('summary', 'Reinstalling'), list_bunch.reinstalled),
Packit Service 21c75c
                (ins_group_msg, list_bunch.installed_group),
Packit Service 21c75c
                (_('Installing dependencies'), list_bunch.installed_dep),
Packit Service 21c75c
                (_('Installing weak dependencies'), list_bunch.installed_weak),
Packit Service 21c75c
                # TRANSLATORS: This is for a list of packages to be removed.
Packit Service 21c75c
                (_('Removing'), list_bunch.erased),
Packit Service 21c75c
                (_('Removing dependent packages'), list_bunch.erased_dep),
Packit Service 21c75c
                (_('Removing unused dependencies'), list_bunch.erased_clean),
Packit Service 21c75c
                # TRANSLATORS: This is for a list of packages to be downgraded.
Packit Service 21c75c
                (C_('summary', 'Downgrading'), list_bunch.downgraded)]:
Packit Service 21c75c
            lines = []
Packit Service 21c75c
Packit Service 21c75c
            # build a reverse mapping to 'replaced_by'
Packit Service 21c75c
            # this is required to achieve reasonable speed
Packit Service 21c75c
            replaces = {}
Packit Service 21c75c
            for tsi in transaction:
Packit Service 21c75c
                if tsi.action != libdnf.transaction.TransactionItemAction_OBSOLETED:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                for i in tsi._item.getReplacedBy():
Packit Service 21c75c
                    replaces.setdefault(i, set()).add(tsi)
Packit Service 21c75c
Packit Service 21c75c
            for tsi in sorted(pkglist, key=lambda x: x.pkg):
Packit Service 21c75c
                if tsi.action not in dnf.transaction.FORWARD_ACTIONS + [libdnf.transaction.TransactionItemAction_REMOVE]:
Packit Service 21c75c
                    continue
Packit Service 21c75c
Packit Service 21c75c
                # get TransactionItems obsoleted by tsi
Packit Service 21c75c
                obsoleted = sorted(replaces.get(tsi._item, []))
Packit Service 21c75c
Packit Service 21c75c
                a_wid = _add_line(lines, data, a_wid, tsi.pkg, obsoleted)
Packit Service 21c75c
Packit Service 21c75c
            pkglist_lines.append((action, lines))
Packit Service 21c75c
Packit Service 21c75c
        installedProfiles = sorted(dict(self.base._moduleContainer.getInstalledProfiles()).items())
Packit Service 21c75c
        if installedProfiles:
Packit Service 21c75c
            action = _("Installing module profiles")
Packit Service 21c75c
            lines = []
Packit Service 21c75c
            for name, profiles in installedProfiles:
Packit Service 21c75c
                for profile in list(profiles):
Packit Service 21c75c
                    lines.append(("%s/%s" % (name, profile), "", "", "", "", "", ""))
Packit Service 21c75c
            pkglist_lines.append((action, lines))
Packit Service 21c75c
Packit Service 21c75c
        removedProfiles = sorted(dict(self.base._moduleContainer.getRemovedProfiles()).items())
Packit Service 21c75c
        if removedProfiles:
Packit Service 21c75c
            action = _("Disabling module profiles")
Packit Service 21c75c
            lines = []
Packit Service 21c75c
            for name, profiles in removedProfiles:
Packit Service 21c75c
                for profile in list(profiles):
Packit Service 21c75c
                    lines.append(("%s/%s" % (name, profile), "", "", "", "", "", ""))
Packit Service 21c75c
            pkglist_lines.append((action, lines))
Packit Service 21c75c
Packit Service 21c75c
        enabledStreams = sorted(dict(self.base._moduleContainer.getEnabledStreams()).items())
Packit Service 21c75c
        if enabledStreams:
Packit Service 21c75c
            action = _("Enabling module streams")
Packit Service 21c75c
            lines = []
Packit Service 21c75c
            for name, stream in enabledStreams:
Packit Service 21c75c
                lines.append((name, "", stream, "", "", "", ""))
Packit Service 21c75c
            pkglist_lines.append((action, lines))
Packit Service 21c75c
Packit Service 21c75c
        switchedStreams = sorted(dict(self.base._moduleContainer.getSwitchedStreams()).items())
Packit Service 21c75c
        if switchedStreams:
Packit Service 21c75c
            action = _("Switching module streams")
Packit Service 21c75c
            lines = []
Packit Service 21c75c
            for name, stream in switchedStreams:
Packit Service 21c75c
                lines.append((name, "", "%s -> %s" % (stream[0], stream[1]), "", "", "", ""))
Packit Service 21c75c
            pkglist_lines.append((action, lines))
Packit Service 21c75c
Packit Service 21c75c
        disabledModules = sorted(list(self.base._moduleContainer.getDisabledModules()))
Packit Service 21c75c
        if disabledModules:
Packit Service 21c75c
            action = _("Disabling modules")
Packit Service 21c75c
            lines = []
Packit Service 21c75c
            for name in disabledModules:
Packit Service 21c75c
                lines.append((name, "", "", "", "", "", ""))
Packit Service 21c75c
            pkglist_lines.append((action, lines))
Packit Service 21c75c
Packit Service 21c75c
        resetModules = sorted(list(self.base._moduleContainer.getResetModules()))
Packit Service 21c75c
        if resetModules:
Packit Service 21c75c
            action = _("Resetting modules")
Packit Service 21c75c
            lines = []
Packit Service 21c75c
            for name in resetModules:
Packit Service 21c75c
                lines.append((name, "", "", "", "", "", ""))
Packit Service 21c75c
            pkglist_lines.append((action, lines))
Packit Service 21c75c
        if self.base._history:
Packit Service 21c75c
            def format_line(group):
Packit Service 21c75c
                name = group.getName()
Packit Service 21c75c
                return (name if name else _("<name-unset>"), "", "", "", "", "", "")
Packit Service 21c75c
Packit Service 21c75c
            install_env_group = self.base._history.env._installed
Packit Service 21c75c
            if install_env_group:
Packit Service 21c75c
                action = _("Installing Environment Groups")
Packit Service 21c75c
                lines = []
Packit Service 21c75c
                for group in install_env_group.values():
Packit Service 21c75c
                    lines.append(format_line(group))
Packit Service 21c75c
                pkglist_lines.append((action, lines))
Packit Service 21c75c
            upgrade_env_group = self.base._history.env._upgraded
Packit Service 21c75c
            if upgrade_env_group:
Packit Service 21c75c
                action = _("Upgrading Environment Groups")
Packit Service 21c75c
                lines = []
Packit Service 21c75c
                for group in upgrade_env_group.values():
Packit Service 21c75c
                    lines.append(format_line(group))
Packit Service 21c75c
                pkglist_lines.append((action, lines))
Packit Service 21c75c
            remove_env_group = self.base._history.env._removed
Packit Service 21c75c
            if remove_env_group:
Packit Service 21c75c
                action = _("Removing Environment Groups")
Packit Service 21c75c
                lines = []
Packit Service 21c75c
                for group in remove_env_group.values():
Packit Service 21c75c
                    lines.append(format_line(group))
Packit Service 21c75c
                pkglist_lines.append((action, lines))
Packit Service 21c75c
            install_group = self.base._history.group._installed
Packit Service 21c75c
            if install_group:
Packit Service 21c75c
                action = _("Installing Groups")
Packit Service 21c75c
                lines = []
Packit Service 21c75c
                for group in install_group.values():
Packit Service 21c75c
                    lines.append(format_line(group))
Packit Service 21c75c
                pkglist_lines.append((action, lines))
Packit Service 21c75c
            upgrade_group = self.base._history.group._upgraded
Packit Service 21c75c
            if upgrade_group:
Packit Service 21c75c
                action = _("Upgrading Groups")
Packit Service 21c75c
                lines = []
Packit Service 21c75c
                for group in upgrade_group.values():
Packit Service 21c75c
                    lines.append(format_line(group))
Packit Service 21c75c
                pkglist_lines.append((action, lines))
Packit Service 21c75c
            remove_group = self.base._history.group._removed
Packit Service 21c75c
            if remove_group:
Packit Service 21c75c
                action = _("Removing Groups")
Packit Service 21c75c
                lines = []
Packit Service 21c75c
                for group in remove_group.values():
Packit Service 21c75c
                    lines.append(format_line(group))
Packit Service 21c75c
                pkglist_lines.append((action, lines))
Packit Service 21c75c
        # show skipped conflicting packages
Packit Service 21c75c
        if not self.conf.best and self.base._goal.actions & forward_actions:
Packit Service 21c75c
            lines = []
Packit Service cfdb81
            skipped_conflicts, skipped_broken = self.base._skipped_packages(
Packit Service 21c75c
                report_problems=True, transaction=transaction)
Packit Service 21c75c
            skipped_broken = dict((str(pkg), pkg) for pkg in skipped_broken)
Packit Service 21c75c
            for pkg in sorted(skipped_conflicts):
Packit Service 21c75c
                a_wid = _add_line(lines, data, a_wid, pkg, [])
Packit Service 21c75c
            recommendations = ["--best"]
Packit Service 21c75c
            if not self.base._allow_erasing:
Packit Service 21c75c
                recommendations.append("--allowerasing")
Packit Service 21c75c
            skip_str = _("Skipping packages with conflicts:\n"
Packit Service 21c75c
                         "(add '%s' to command line "
Packit Service 21c75c
                         "to force their upgrade)") % " ".join(recommendations)
Packit Service 21c75c
            # remove misleading green color from the "packages with conflicts" lines
Packit Service 21c75c
            lines = [i[:-1] + ("", ) for i in lines]
Packit Service 21c75c
            pkglist_lines.append((skip_str, lines))
Packit Service 21c75c
Packit Service 21c75c
            lines = []
Packit Service 21c75c
            for nevra, pkg in sorted(skipped_broken.items()):
Packit Service 21c75c
                a_wid = _add_line(lines, data, a_wid, pkg, [])
Packit Service 21c75c
            skip_str = _("Skipping packages with broken dependencies%s")
Packit Service 21c75c
            if self.base.conf.upgrade_group_objects_upgrade:
Packit Service 21c75c
                skip_str = skip_str % ""
Packit Service 21c75c
            else:
Packit Service 21c75c
                skip_str = skip_str % _(" or part of a group")
Packit Service 21c75c
Packit Service 21c75c
            # remove misleading green color from the "broken dependencies" lines
Packit Service 21c75c
            lines = [i[:-1] + ("", ) for i in lines]
Packit Service 21c75c
            pkglist_lines.append((skip_str, lines))
Packit Service 21c75c
        output_width = self.term.columns
Packit Service 21c75c
        if not data['n'] and not self.base._moduleContainer.isChanged() and not \
Packit Service 21c75c
                (self.base._history and (self.base._history.group or self.base._history.env)):
Packit Service 21c75c
            return u''
Packit Service 21c75c
        else:
Packit Service 21c75c
            data = [data['n'], {}, data['v'], data['r'], {}]
Packit Service 21c75c
            columns = [1, a_wid, 1, 1, 5]
Packit Service 21c75c
            columns = self.calcColumns(data, indent="  ", columns=columns,
Packit Service 21c75c
                                       remainder_column=2, total_width=total_width)
Packit Service 21c75c
            (n_wid, a_wid, v_wid, r_wid, s_wid) = columns
Packit Service 21c75c
            real_width = sum(columns) + 5
Packit Service 21c75c
            output_width = output_width if output_width >= real_width else real_width
Packit Service 21c75c
Packit Service 21c75c
            # Do not use 'Package' without context. Using context resolves
Packit Service 21c75c
            # RhBug 1302935 as a side effect.
Packit Service 21c75c
            msg_package = select_short_long(n_wid,
Packit Service 21c75c
            # Translators: This is the short version of 'Package'. You can
Packit Service 21c75c
            # use the full (unabbreviated) term 'Package' if you think that
Packit Service 21c75c
            # the translation to your language is not too long and will
Packit Service 21c75c
            # always fit to limited space.
Packit Service 21c75c
                                            C_('short', 'Package'),
Packit Service 21c75c
            # Translators: This is the full (unabbreviated) term 'Package'.
Packit Service 21c75c
                                            C_('long', 'Package'))
Packit Service 21c75c
            msg_arch = select_short_long(a_wid,
Packit Service 21c75c
            # Translators: This is abbreviated 'Architecture', used when
Packit Service 21c75c
            # we have not enough space to display the full word.
Packit Service 21c75c
                                         C_('short', 'Arch'),
Packit Service 21c75c
            # Translators: This is the full word 'Architecture', used when
Packit Service 21c75c
            # we have enough space.
Packit Service 21c75c
                                         C_('long', 'Architecture'))
Packit Service 21c75c
            msg_version = select_short_long(v_wid,
Packit Service 21c75c
            # Translators: This is the short version of 'Version'. You can
Packit Service 21c75c
            # use the full (unabbreviated) term 'Version' if you think that
Packit Service 21c75c
            # the translation to your language is not too long and will
Packit Service 21c75c
            # always fit to limited space.
Packit Service 21c75c
                                            C_('short', 'Version'),
Packit Service 21c75c
            # Translators: This is the full (unabbreviated) term 'Version'.
Packit Service 21c75c
                                            C_('long', 'Version'))
Packit Service 21c75c
            msg_repository = select_short_long(r_wid,
Packit Service 21c75c
            # Translators: This is abbreviated 'Repository', used when
Packit Service 21c75c
            # we have not enough space to display the full word.
Packit Service 21c75c
                                               C_('short', 'Repo'),
Packit Service 21c75c
            # Translators: This is the full word 'Repository', used when
Packit Service 21c75c
            # we have enough space.
Packit Service 21c75c
                                               C_('long', 'Repository'))
Packit Service 21c75c
            msg_size = select_short_long(s_wid,
Packit Service 21c75c
            # Translators: This is the short version of 'Size'. It should
Packit Service 21c75c
            # not be longer than 5 characters. If the term 'Size' in your
Packit Service 21c75c
            # language is not longer than 5 characters then you can use it
Packit Service 21c75c
            # unabbreviated.
Packit Service 21c75c
                                         C_('short', 'Size'),
Packit Service 21c75c
            # Translators: This is the full (unabbreviated) term 'Size'.
Packit Service 21c75c
                                         C_('long', 'Size'))
Packit Service 21c75c
Packit Service 21c75c
            out = [u"%s\n%s\n%s\n" % ('=' * output_width,
Packit Service 21c75c
                                      self.fmtColumns(((msg_package, -n_wid),
Packit Service 21c75c
                                                       (msg_arch, -a_wid),
Packit Service 21c75c
                                                       (msg_version, -v_wid),
Packit Service 21c75c
                                                       (msg_repository, -r_wid),
Packit Service 21c75c
                                                       (msg_size, s_wid)), u" "),
Packit Service 21c75c
                                      '=' * output_width)]
Packit Service 21c75c
Packit Service 21c75c
        for (action, lines) in pkglist_lines:
Packit Service 21c75c
            if lines:
Packit Service 21c75c
                totalmsg = u"%s:\n" % action
Packit Service 21c75c
            for (n, a, evr, repoid, size, obsoletes, hi) in lines:
Packit Service 21c75c
                columns = ((n, -n_wid, hi), (a, -a_wid),
Packit Service 21c75c
                           (evr, -v_wid), (repoid, -r_wid), (size, s_wid))
Packit Service 21c75c
                msg = self.fmtColumns(columns, u" ", u"\n")
Packit Service 21c75c
                hibeg, hiend = self._highlight(self.conf.color_update_installed)
Packit Service 21c75c
                for obspo in sorted(obsoletes):
Packit Service 21c75c
                    appended = '     ' + _('replacing') + '  %s%s%s.%s %s\n'
Packit Service 21c75c
                    appended %= (hibeg, obspo.name, hiend, obspo.arch, obspo.evr)
Packit Service 21c75c
                    msg += appended
Packit Service 21c75c
                totalmsg = totalmsg + msg
Packit Service 21c75c
Packit Service 21c75c
            if lines:
Packit Service 21c75c
                out.append(totalmsg)
Packit Service 21c75c
        out.append(_("""
Packit Service 21c75c
Transaction Summary
Packit Service 21c75c
%s
Packit Service 21c75c
""") % ('=' * output_width))
Packit Service 21c75c
        summary_data = (
Packit Service 21c75c
            (_('Install'), len(list_bunch.installed) +
Packit Service 21c75c
             len(list_bunch.installed_group) +
Packit Service 21c75c
             len(list_bunch.installed_weak) +
Packit Service 21c75c
             len(list_bunch.installed_dep), 0),
Packit Service 21c75c
            (_('Upgrade'), len(list_bunch.upgraded), 0),
Packit Service 21c75c
            (_('Remove'), len(list_bunch.erased) + len(list_bunch.erased_dep) +
Packit Service 21c75c
             len(list_bunch.erased_clean), 0),
Packit Service 21c75c
            (_('Downgrade'), len(list_bunch.downgraded), 0),
Packit Service 21c75c
            (_('Skip'), len(skipped_conflicts) + len(skipped_broken), 0))
Packit Service 21c75c
        max_msg_action = 0
Packit Service 21c75c
        max_msg_count = 0
Packit Service 21c75c
        max_msg_pkgs = 0
Packit Service 21c75c
        max_msg_depcount = 0
Packit Service 21c75c
        for action, count, depcount in summary_data:
Packit Service 21c75c
            if not count and not depcount:
Packit Service 21c75c
                continue
Packit Service 21c75c
Packit Service 21c75c
            msg_pkgs = P_('Package', 'Packages', count)
Packit Service 21c75c
            len_msg_action = exact_width(action)
Packit Service 21c75c
            len_msg_count = exact_width(unicode(count))
Packit Service 21c75c
            len_msg_pkgs = exact_width(msg_pkgs)
Packit Service 21c75c
Packit Service 21c75c
            if depcount:
Packit Service 21c75c
                len_msg_depcount = exact_width(unicode(depcount))
Packit Service 21c75c
            else:
Packit Service 21c75c
                len_msg_depcount = 0
Packit Service 21c75c
Packit Service 21c75c
            max_msg_action = max(len_msg_action, max_msg_action)
Packit Service 21c75c
            max_msg_count = max(len_msg_count, max_msg_count)
Packit Service 21c75c
            max_msg_pkgs = max(len_msg_pkgs, max_msg_pkgs)
Packit Service 21c75c
            max_msg_depcount = max(len_msg_depcount, max_msg_depcount)
Packit Service 21c75c
Packit Service 21c75c
        for action, count, depcount in summary_data:
Packit Service 21c75c
            msg_pkgs = P_('Package', 'Packages', count)
Packit Service 21c75c
            if depcount:
Packit Service 21c75c
                msg_deppkgs = P_('Dependent package', 'Dependent packages',
Packit Service 21c75c
                                 depcount)
Packit Service 21c75c
                action_msg = fill_exact_width(action, max_msg_action)
Packit Service 21c75c
                if count:
Packit Service 21c75c
                    msg = '%s  %*d %s (+%*d %s)\n'
Packit Service 21c75c
                    out.append(msg % (action_msg,
Packit Service 21c75c
                                      max_msg_count, count,
Packit Service 21c75c
                                      "%-*s" % (max_msg_pkgs, msg_pkgs),
Packit Service 21c75c
                                      max_msg_depcount, depcount, msg_deppkgs))
Packit Service 21c75c
                else:
Packit Service 21c75c
                    msg = '%s  %s  ( %*d %s)\n'
Packit Service 21c75c
                    out.append(msg % (action_msg,
Packit Service 21c75c
                                      (max_msg_count + max_msg_pkgs) * ' ',
Packit Service 21c75c
                                      max_msg_depcount, depcount, msg_deppkgs))
Packit Service 21c75c
            elif count:
Packit Service 21c75c
                msg = '%s  %*d %s\n'
Packit Service 21c75c
                out.append(msg % (fill_exact_width(action, max_msg_action),
Packit Service 21c75c
                                  max_msg_count, count, msg_pkgs))
Packit Service 21c75c
        return ''.join(out)
Packit Service 21c75c
Packit Service 21c75c
Packit Service cfdb81
    def _pto_callback(self, action, tsis):
Packit Service 21c75c
        #  Works a bit like calcColumns, but we never overflow a column we just
Packit Service 21c75c
        # have a dynamic number of columns.
Packit Service 21c75c
        def _fits_in_cols(msgs, num):
Packit Service 21c75c
            """ Work out how many columns we can use to display stuff, in
Packit Service 21c75c
                the post trans output. """
Packit Service 21c75c
            if len(msgs) < num:
Packit Service 21c75c
                return []
Packit Service 21c75c
Packit Service 21c75c
            left = self.term.columns - ((num - 1) + 2)
Packit Service 21c75c
            if left <= 0:
Packit Service 21c75c
                return []
Packit Service 21c75c
Packit Service 21c75c
            col_lens = [0] * num
Packit Service 21c75c
            col = 0
Packit Service 21c75c
            for msg in msgs:
Packit Service 21c75c
                if len(msg) > col_lens[col]:
Packit Service 21c75c
                    diff = (len(msg) - col_lens[col])
Packit Service 21c75c
                    if left <= diff:
Packit Service 21c75c
                        return []
Packit Service 21c75c
                    left -= diff
Packit Service 21c75c
                    col_lens[col] = len(msg)
Packit Service 21c75c
                col += 1
Packit Service 21c75c
                col %= len(col_lens)
Packit Service 21c75c
Packit Service 21c75c
            for col in range(len(col_lens)):
Packit Service 21c75c
                col_lens[col] += left // num
Packit Service 21c75c
                col_lens[col] *= -1
Packit Service 21c75c
            return col_lens
Packit Service 21c75c
Packit Service cfdb81
        if not tsis:
Packit Service cfdb81
            return ''
Packit Service cfdb81
        out = []
Packit Service cfdb81
        msgs = []
Packit Service cfdb81
        out.append('{}:'.format(action))
Packit Service cfdb81
        for tsi in tsis:
Packit Service cfdb81
            msgs.append(str(tsi))
Packit Service cfdb81
        for num in (8, 7, 6, 5, 4, 3, 2):
Packit Service cfdb81
            cols = _fits_in_cols(msgs, num)
Packit Service cfdb81
            if cols:
Packit Service cfdb81
                break
Packit Service cfdb81
        if not cols:
Packit Service cfdb81
            cols = [-(self.term.columns - 2)]
Packit Service cfdb81
        while msgs:
Packit Service cfdb81
            current_msgs = msgs[:len(cols)]
Packit Service cfdb81
            out.append('  {}'.format(self.fmtColumns(zip(current_msgs, cols))))
Packit Service cfdb81
            msgs = msgs[len(cols):]
Packit Service 9e55ff
        return out
Packit Service 57000e
Packit Service cfdb81
Packit Service cfdb81
    def post_transaction_output(self, transaction):
Packit Service cfdb81
        """
Packit Service cfdb81
        Return a human-readable summary of the transaction. Packages in sections
Packit Service cfdb81
        are arranged to columns.
Packit Service cfdb81
        """
Packit Service cfdb81
        return dnf.util._post_transaction_output(self.base, transaction, self._pto_callback)
Packit Service cfdb81
Packit Service 21c75c
    def setup_progress_callbacks(self):
Packit Service 21c75c
        """Set up the progress callbacks and various
Packit Service 21c75c
           output bars based on debug level.
Packit Service 21c75c
        """
Packit Service 21c75c
        progressbar = None
Packit Service 21c75c
        if self.conf.debuglevel >= 2:
Packit Service 21c75c
            progressbar = dnf.cli.progress.MultiFileProgressMeter(fo=sys.stdout)
Packit Service 21c75c
            self.progress = dnf.cli.progress.MultiFileProgressMeter(fo=sys.stdout)
Packit Service 21c75c
Packit Service 21c75c
        # setup our depsolve progress callback
Packit Service 21c75c
        return (progressbar, DepSolveProgressCallBack())
Packit Service 21c75c
Packit Service 21c75c
    def download_callback_total_cb(self, remote_size, download_start_timestamp):
Packit Service 21c75c
        """Outputs summary information about the download process.
Packit Service 21c75c
Packit Service 21c75c
        :param remote_size: the total amount of information that was
Packit Service 21c75c
           downloaded, in bytes
Packit Service 21c75c
        :param download_start_timestamp: the time when the download
Packit Service 21c75c
           process started, in seconds since the epoch
Packit Service 21c75c
        """
Packit Service 21c75c
        if remote_size <= 0:
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        width = self.term.columns
Packit Service 21c75c
        logger.info("-" * width)
Packit Service 21c75c
        dl_time = max(0.01, time.time() - download_start_timestamp)
Packit Service 21c75c
        msg = ' %5sB/s | %5sB %9s     ' % (
Packit Service 21c75c
            format_number(remote_size // dl_time),
Packit Service 21c75c
            format_number(remote_size),
Packit Service 21c75c
            format_time(dl_time))
Packit Service 21c75c
        msg = fill_exact_width(_("Total"), width - len(msg)) + msg
Packit Service 21c75c
        logger.info(msg)
Packit Service 21c75c
Packit Service 21c75c
    def _history_uiactions(self, hpkgs):
Packit Service 21c75c
        actions = set()
Packit Service 21c75c
        actions_short = set()
Packit Service 21c75c
        count = 0
Packit Service 21c75c
        for pkg in hpkgs:
Packit Service 21c75c
            if pkg.action in (libdnf.transaction.TransactionItemAction_UPGRADED, libdnf.transaction.TransactionItemAction_DOWNGRADED):
Packit Service 21c75c
                # skip states we don't want to display in user input
Packit Service 21c75c
                continue
Packit Service 21c75c
            actions.add(pkg.action_name)
Packit Service 21c75c
            actions_short.add(pkg.action_short)
Packit Service 21c75c
            count += 1
Packit Service 21c75c
Packit Service 21c75c
        if len(actions) > 1:
Packit Service 21c75c
            return count, ", ".join(sorted(actions_short))
Packit Service 21c75c
Packit Service 21c75c
        # So empty transactions work, although that "shouldn't" really happen
Packit Service 21c75c
        return count, "".join(list(actions))
Packit Service 21c75c
Packit Service 21c75c
    def _pwd_ui_username(self, uid, limit=None):
Packit Service 21c75c
        if isinstance(uid, list):
Packit Service 21c75c
            return [self._pwd_ui_username(u, limit) for u in uid]
Packit Service 21c75c
Packit Service 21c75c
        # loginuid is set to      -1 (0xFFFF_FFFF) on init, in newer kernels.
Packit Service 21c75c
        # loginuid is set to INT_MAX (0x7FFF_FFFF) on init, in older kernels.
Packit Service 21c75c
        if uid is None or uid in (0xFFFFFFFF, 0x7FFFFFFF):
Packit Service 21c75c
            loginid = _("<unset>")
Packit Service 21c75c
            name = _("System") + " " + loginid
Packit Service 21c75c
            if limit is not None and len(name) > limit:
Packit Service 21c75c
                name = loginid
Packit Service 21c75c
            return ucd(name)
Packit Service 21c75c
Packit Service 21c75c
        def _safe_split_0(text, *args):
Packit Service 21c75c
            """ Split gives us a [0] for everything _but_ '', this function
Packit Service 21c75c
                returns '' in that case. """
Packit Service 21c75c
            ret = text.split(*args)
Packit Service 21c75c
            if not ret:
Packit Service 21c75c
                return ''
Packit Service 21c75c
            return ret[0]
Packit Service 21c75c
Packit Service 21c75c
        try:
Packit Service 21c75c
            user = pwd.getpwuid(int(uid))
Packit Service 21c75c
            fullname = _safe_split_0(ucd(user.pw_gecos), ';', 2)
Packit Service 21c75c
            user_name = ucd(user.pw_name)
Packit Service 21c75c
            name = "%s <%s>" % (fullname, user_name)
Packit Service 21c75c
            if limit is not None and len(name) > limit:
Packit Service 21c75c
                name = "%s ... <%s>" % (_safe_split_0(fullname), user_name)
Packit Service 21c75c
                if len(name) > limit:
Packit Service 21c75c
                    name = "<%s>" % user_name
Packit Service 21c75c
            return name
Packit Service 21c75c
        except KeyError:
Packit Service 21c75c
            return ucd(uid)
Packit Service 21c75c
Packit Service 21c75c
    def historyListCmd(self, tids, reverse=False):
Packit Service 21c75c
        """Output a list of information about the history of yum
Packit Service 21c75c
        transactions.
Packit Service 21c75c
Packit Service 21c75c
        :param tids: transaction Ids; lists all transactions if empty
Packit Service 21c75c
        """
Packit Service 21c75c
        transactions = self.history.old(tids)
Packit Service 21c75c
        if self.conf.history_list_view == 'users':
Packit Service 21c75c
            uids = [1, 2]
Packit Service 21c75c
        elif self.conf.history_list_view == 'commands':
Packit Service 21c75c
            uids = [1]
Packit Service 21c75c
        else:
Packit Service 21c75c
            assert self.conf.history_list_view == 'single-user-commands'
Packit Service 21c75c
            uids = set()
Packit Service 21c75c
            done = 0
Packit Service 21c75c
            blanks = 0
Packit Service 21c75c
            for transaction in transactions:
Packit Service 21c75c
                done += 1
Packit Service 21c75c
                if transaction.cmdline is None:
Packit Service 21c75c
                    blanks += 1
Packit Service 21c75c
                uids.add(transaction.loginuid)
Packit Service 21c75c
Packit Service 21c75c
        fmt = "%s | %s | %s | %s | %s"
Packit Service 21c75c
        if len(uids) == 1:
Packit Service 21c75c
            name = _("Command line")
Packit Service 21c75c
            real_cols = self.term.real_columns
Packit Service 21c75c
            if real_cols is None:
Packit Service 21c75c
                name_width = (
Packit Service 21c75c
                        24 if not transactions
Packit Service 21c75c
                        else max([len(t.cmdline) for t in transactions])
Packit Service 21c75c
                        )
Packit Service 21c75c
            else:
Packit Service 21c75c
                name_width = real_cols - 55 if real_cols > 79 else 24
Packit Service 21c75c
        else:
Packit Service 21c75c
            # TRANSLATORS: user names who executed transaction in history command output
Packit Service 21c75c
            name = _("User name")
Packit Service 21c75c
            name_width = 24
Packit Service 21c75c
        print(fmt % (fill_exact_width(_("ID"), 6, 6),
Packit Service 21c75c
                     fill_exact_width(name, name_width, name_width),
Packit Service 21c75c
                     fill_exact_width(_("Date and time"), 16, 16),
Packit Service 21c75c
                     fill_exact_width(_("Action(s)"), 14, 14),
Packit Service 21c75c
                     fill_exact_width(_("Altered"), 7, 7)))
Packit Service 21c75c
Packit Service 21c75c
        # total table width: each column length +3 (padding and separator between columns)
Packit Service 21c75c
        table_width = 6 + 3 + name_width + 3 + 16 + 3 + 14 + 3 + 7
Packit Service 21c75c
        print("-" * table_width)
Packit Service 21c75c
        fmt = "%6u | %s | %-16.16s | %s | %4u"
Packit Service 21c75c
Packit Service 21c75c
        if reverse is True:
Packit Service 21c75c
            transactions = reversed(transactions)
Packit Service 21c75c
        for transaction in transactions:
Packit Service 21c75c
            if len(uids) == 1:
Packit Service 21c75c
                name = transaction.cmdline or ''
Packit Service 21c75c
            else:
Packit Service 21c75c
                name = self._pwd_ui_username(transaction.loginuid, 24)
Packit Service 21c75c
            name = ucd(name)
Packit Service 21c75c
            tm = time.strftime("%Y-%m-%d %H:%M",
Packit Service 21c75c
                               time.localtime(transaction.beg_timestamp))
Packit Service 21c75c
            num, uiacts = self._history_uiactions(transaction.data())
Packit Service 21c75c
            name = fill_exact_width(name, name_width, name_width)
Packit Service 21c75c
            uiacts = fill_exact_width(uiacts, 14, 14)
Packit Service 21c75c
            rmark = lmark = ' '
Packit Service 21c75c
            if transaction.return_code is None:
Packit Service 21c75c
                rmark = lmark = '*'
Packit Service 21c75c
            elif transaction.return_code:
Packit Service 21c75c
                rmark = lmark = '#'
Packit Service 21c75c
                # We don't check .errors, because return_code will be non-0
Packit Service 21c75c
            elif transaction.is_output:
Packit Service 21c75c
                rmark = lmark = 'E'
Packit Service 21c75c
            if transaction.altered_lt_rpmdb:
Packit Service 21c75c
                rmark = '<'
Packit Service 21c75c
            if transaction.altered_gt_rpmdb:
Packit Service 21c75c
                lmark = '>'
Packit Service 21c75c
            print(fmt % (transaction.tid, name, tm, uiacts, num), "%s%s" % (lmark, rmark))
Packit Service 21c75c
Packit Service 21c75c
    def historyInfoCmd(self, tids, pats=[], mtids=set()):
Packit Service 21c75c
        """Output information about a transaction in history
Packit Service 21c75c
Packit Service 21c75c
        :param tids: transaction Ids; prints info for the last transaction if empty
Packit Service 21c75c
        :raises dnf.exceptions.Error in case no transactions were found
Packit Service 21c75c
        """
Packit Service 21c75c
        tids = set(tids)
Packit Service 21c75c
        last = self.history.last()
Packit Service 21c75c
        if last is None:
Packit Service 21c75c
            logger.critical(_('No transactions'))
Packit Service 21c75c
            raise dnf.exceptions.Error(_('Failed history info'))
Packit Service 21c75c
Packit Service 21c75c
        lasttid = last.tid
Packit Service 21c75c
        lastdbv = last.end_rpmdb_version
Packit Service 21c75c
Packit Service 21c75c
        transactions = []
Packit Service 21c75c
        if not tids:
Packit Service 21c75c
            last = self.history.last(complete_transactions_only=False)
Packit Service 21c75c
            if last is not None:
Packit Service 21c75c
                tids.add(last.tid)
Packit Service 21c75c
                transactions.append(last)
Packit Service 21c75c
        else:
Packit Service 21c75c
            transactions = self.history.old(tids)
Packit Service 21c75c
Packit Service 21c75c
        if not tids:
Packit Service 21c75c
            logger.critical(_('No transaction ID, or package, given'))
Packit Service 21c75c
            raise dnf.exceptions.Error(_('Failed history info'))
Packit Service 21c75c
Packit Service 21c75c
        bmtid, emtid = -1, -1
Packit Service 21c75c
        mobj = None
Packit Service 21c75c
        done = False
Packit Service 21c75c
Packit Service 21c75c
        if mtids:
Packit Service 21c75c
            mtids = sorted(mtids)
Packit Service 21c75c
            bmtid, emtid = mtids.pop()
Packit Service 21c75c
Packit Service 21c75c
        for trans in transactions:
Packit Service 21c75c
            if lastdbv is not None and trans.tid == lasttid:
Packit Service 21c75c
                #  If this is the last transaction, is good and it doesn't
Packit Service 21c75c
                # match the current rpmdb ... then mark it as bad.
Packit Service 21c75c
                rpmdbv = self.sack._rpmdb_version()
Packit Service 21c75c
                trans.compare_rpmdbv(str(rpmdbv))
Packit Service 21c75c
            lastdbv = None
Packit Service 21c75c
Packit Service 21c75c
            merged = False
Packit Service 21c75c
Packit Service 21c75c
            if trans.tid >= bmtid and trans.tid <= emtid:
Packit Service 21c75c
                if mobj is None:
Packit Service 21c75c
                    mobj = MergedTransactionWrapper(trans)
Packit Service 21c75c
                else:
Packit Service 21c75c
                    mobj.merge(trans)
Packit Service 21c75c
                merged = True
Packit Service 21c75c
            elif mobj is not None:
Packit Service 21c75c
                if done:
Packit Service 21c75c
                    print("-" * 79)
Packit Service 21c75c
                done = True
Packit Service 21c75c
Packit Service 21c75c
                self._historyInfoCmd(mobj)
Packit Service 21c75c
                mobj = None
Packit Service 21c75c
Packit Service 21c75c
                if mtids:
Packit Service 21c75c
                    bmtid, emtid = mtids.pop()
Packit Service 21c75c
                    if trans.tid >= bmtid and trans.tid <= emtid:
Packit Service 21c75c
                        mobj = trans
Packit Service 21c75c
                        merged = True
Packit Service 21c75c
Packit Service 21c75c
            if not merged:
Packit Service 21c75c
                if done:
Packit Service 21c75c
                    print("-" * 79)
Packit Service 21c75c
                done = True
Packit Service 21c75c
                self._historyInfoCmd(trans, pats)
Packit Service 21c75c
Packit Service 21c75c
        if mobj is not None:
Packit Service 21c75c
            if done:
Packit Service 21c75c
                print("-" * 79)
Packit Service 21c75c
            self._historyInfoCmd(mobj)
Packit Service 21c75c
Packit Service 21c75c
    def _historyInfoCmd(self, old, pats=[]):
Packit Service 21c75c
        loginuid = old.loginuid
Packit Service 21c75c
        if isinstance(loginuid, int):
Packit Service 21c75c
            loginuid = [loginuid]
Packit Service 21c75c
        name = [self._pwd_ui_username(uid) for uid in loginuid]
Packit Service 21c75c
Packit Service 21c75c
        _pkg_states_installed = {'i' : _('Installed'), 'e' : _('Erased'),
Packit Service 21c75c
                                 'o' : _('Upgraded'), 'n' : _('Downgraded')}
Packit Service 21c75c
        _pkg_states_available = {'i' : _('Installed'), 'e' : _('Not installed'),
Packit Service 21c75c
                                 'o' : _('Older'), 'n' : _('Newer')}
Packit Service 21c75c
        maxlen = max([len(x) for x in (list(_pkg_states_installed.values()) +
Packit Service 21c75c
                                       list(_pkg_states_available.values()))])
Packit Service 21c75c
        _pkg_states_installed['maxlen'] = maxlen
Packit Service 21c75c
        _pkg_states_available['maxlen'] = maxlen
Packit Service 21c75c
        def _simple_pkg(pkg, prefix_len, was_installed=False, highlight=False,
Packit Service 21c75c
                        pkg_max_len=0, show_repo=True):
Packit Service 21c75c
            prefix = " " * prefix_len
Packit Service 21c75c
            if was_installed:
Packit Service 21c75c
                _pkg_states = _pkg_states_installed
Packit Service 21c75c
            else:
Packit Service 21c75c
                _pkg_states = _pkg_states_available
Packit Service 21c75c
            state = _pkg_states['i']
Packit Service 21c75c
Packit Service 21c75c
            # get installed packages with name = pkg.name
Packit Service 21c75c
            ipkgs = self.sack.query().installed().filterm(name=pkg.name).run()
Packit Service 21c75c
Packit Service 21c75c
            if not ipkgs:
Packit Service 21c75c
                state = _pkg_states['e']
Packit Service 21c75c
            else:
Packit Service 21c75c
                # get latest installed package from software database
Packit Service 21c75c
                inst_pkg = self.history.package(ipkgs[0])
Packit Service 21c75c
                if inst_pkg:
Packit Service 21c75c
                    res = pkg.compare(inst_pkg)
Packit Service 21c75c
                    # res is:
Packit Service 21c75c
                    # 0 if inst_pkg == pkg
Packit Service 21c75c
                    # > 0 when inst_pkg > pkg
Packit Service 21c75c
                    # < 0 when inst_pkg < pkg
Packit Service 21c75c
                    if res == 0:
Packit Service 21c75c
                        pass  # installed
Packit Service 21c75c
                    elif res > 0:
Packit Service 21c75c
                        state = _pkg_states['o']  # updated
Packit Service 21c75c
                    else:
Packit Service 21c75c
                        state = _pkg_states['n']  # downgraded
Packit Service 21c75c
Packit Service 21c75c
            if highlight:
Packit Service 21c75c
                (hibeg, hiend) = self._highlight('bold')
Packit Service 21c75c
            else:
Packit Service 21c75c
                (hibeg, hiend) = self._highlight('normal')
Packit Service 21c75c
            state = fill_exact_width(state, _pkg_states['maxlen'])
Packit Service 21c75c
            ui_repo = ''
Packit Service 21c75c
            if show_repo:
Packit Service 21c75c
                ui_repo = pkg.ui_from_repo()
Packit Service 21c75c
            print("%s%s%s%s %-*s %s" % (prefix, hibeg, state, hiend,
Packit Service 21c75c
                                        pkg_max_len, str(pkg), ui_repo))
Packit Service 21c75c
Packit Service 21c75c
        tids = old.tids()
Packit Service 21c75c
        if len(tids) > 1:
Packit Service 21c75c
            print(_("Transaction ID :"), "%u..%u" % (tids[0], tids[-1]))
Packit Service 21c75c
        else:
Packit Service 21c75c
            print(_("Transaction ID :"), tids[0])
Packit Service 21c75c
        begt = float(old.beg_timestamp)
Packit Service 21c75c
        begtm = time.strftime("%c", time.localtime(begt))
Packit Service 21c75c
        print(_("Begin time     :"), begtm)
Packit Service 21c75c
        if old.beg_rpmdb_version is not None:
Packit Service 21c75c
            if old.altered_lt_rpmdb:
Packit Service 21c75c
                print(_("Begin rpmdb    :"), old.beg_rpmdb_version, "**")
Packit Service 21c75c
            else:
Packit Service 21c75c
                print(_("Begin rpmdb    :"), old.beg_rpmdb_version)
Packit Service 21c75c
        if old.end_timestamp is not None:
Packit Service 21c75c
            endt = old.end_timestamp
Packit Service 21c75c
            endtm = time.strftime("%c", time.localtime(endt))
Packit Service 21c75c
            diff = endt - begt
Packit Service 21c75c
            if diff < 5 * 60:
Packit Service 21c75c
                diff = _("(%u seconds)") % diff
Packit Service 21c75c
            elif diff < 5 * 60 * 60:
Packit Service 21c75c
                diff = _("(%u minutes)") % (diff // 60)
Packit Service 21c75c
            elif diff < 5 * 60 * 60 * 24:
Packit Service 21c75c
                diff = _("(%u hours)") % (diff // (60 * 60))
Packit Service 21c75c
            else:
Packit Service 21c75c
                diff = _("(%u days)") % (diff // (60 * 60 * 24))
Packit Service 21c75c
            print(_("End time       :"), endtm, diff)
Packit Service 21c75c
        if old.end_rpmdb_version is not None:
Packit Service 21c75c
            if old.altered_gt_rpmdb:
Packit Service 21c75c
                print(_("End rpmdb      :"), old.end_rpmdb_version, "**")
Packit Service 21c75c
            else:
Packit Service 21c75c
                print(_("End rpmdb      :"), old.end_rpmdb_version)
Packit Service 21c75c
        if isinstance(name, (list, tuple)):
Packit Service 21c75c
            seen = set()
Packit Service 21c75c
            for i in name:
Packit Service 21c75c
                if i in seen:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                seen.add(i)
Packit Service 21c75c
                print(_("User           :"), i)
Packit Service 21c75c
        else:
Packit Service 21c75c
            print(_("User           :"), name)
Packit Service 21c75c
        if isinstance(old.return_code, (list, tuple)):
Packit Service 21c75c
            codes = old.return_code
Packit Service 21c75c
            if codes[0] is None:
Packit Service 21c75c
                print(_("Return-Code    :"), "**", _("Aborted"), "**")
Packit Service 21c75c
                codes = codes[1:]
Packit Service 21c75c
            elif not all(codes):
Packit Service 21c75c
                print(_("Return-Code    :"), _("Success"))
Packit Service 21c75c
            elif codes:
Packit Service 21c75c
                print(_("Return-Code    :"), _("Failures:"), ", ".join([str(i) for i in codes]))
Packit Service 21c75c
        elif old.return_code is None:
Packit Service 21c75c
            print(_("Return-Code    :"), "**", _("Aborted"), "**")
Packit Service 21c75c
        elif old.return_code:
Packit Service 21c75c
            print(_("Return-Code    :"), _("Failure:"), old.return_code)
Packit Service 21c75c
        else:
Packit Service 21c75c
            print(_("Return-Code    :"), _("Success"))
Packit Service 21c75c
Packit Service 21c75c
        if isinstance(old.releasever, (list, tuple)):
Packit Service 21c75c
            seen = set()
Packit Service 21c75c
            for i in old.releasever:
Packit Service 21c75c
                if i in seen:
Packit Service 21c75c
                    continue
Packit Service 21c75c
                seen.add(i)
Packit Service 21c75c
            print(_("Releasever     :"), i)
Packit Service 21c75c
        else:
Packit Service 21c75c
            print(_("Releasever     :"), old.releasever)
Packit Service 21c75c
Packit Service 21c75c
        if old.cmdline is not None:
Packit Service 21c75c
            if isinstance(old.cmdline, (list, tuple)):
Packit Service 21c75c
                for cmdline in old.cmdline:
Packit Service 21c75c
                    print(_("Command Line   :"), cmdline)
Packit Service 21c75c
            else:
Packit Service 21c75c
                print(_("Command Line   :"), old.cmdline)
Packit Service 21c75c
Packit Service 21c75c
        if old.comment is not None:
Packit Service 21c75c
            if isinstance(old.comment, (list, tuple)):
Packit Service 21c75c
                for comment in old.comment:
Packit Service 21c75c
                    print(_("Comment        :"), comment)
Packit Service 21c75c
            else:
Packit Service 21c75c
                print(_("Comment        :"), old.comment)
Packit Service 21c75c
Packit Service 21c75c
        perf_with = old.performed_with()
Packit Service 21c75c
        if perf_with:
Packit Service 21c75c
            print(_("Transaction performed with:"))
Packit Service 21c75c
        max_len = 0
Packit Service 21c75c
        for with_pkg in perf_with:
Packit Service 21c75c
            str_len = len(str(with_pkg))
Packit Service 21c75c
            if str_len > max_len:
Packit Service 21c75c
                max_len = str_len
Packit Service 21c75c
        for with_pkg in perf_with:
Packit Service 21c75c
            _simple_pkg(with_pkg, 4, was_installed=True, pkg_max_len=max_len)
Packit Service 21c75c
Packit Service 21c75c
        print(_("Packages Altered:"))
Packit Service 21c75c
Packit Service 21c75c
        self.historyInfoCmdPkgsAltered(old, pats)
Packit Service 21c75c
Packit Service 21c75c
        t_out = old.output()
Packit Service 21c75c
        if t_out:
Packit Service 21c75c
            print(_("Scriptlet output:"))
Packit Service 21c75c
            num = 0
Packit Service 21c75c
            for line in t_out:
Packit Service 21c75c
                num += 1
Packit Service 21c75c
                print("%4d" % num, line)
Packit Service 21c75c
        t_err = old.error()
Packit Service 21c75c
        if t_err:
Packit Service 21c75c
            print(_("Errors:"))
Packit Service 21c75c
            num = 0
Packit Service 21c75c
            for line in t_err:
Packit Service 21c75c
                num += 1
Packit Service 21c75c
                print("%4d" % num, line)
Packit Service 21c75c
Packit Service 21c75c
    # TODO: remove
Packit Service 21c75c
    _history_state2uistate = {'True-Install' : _('Install'),
Packit Service 21c75c
                              'Install'      : _('Install'),
Packit Service 21c75c
                              'Dep-Install'  : _('Dep-Install'),
Packit Service 21c75c
                              'Obsoleted'    : _('Obsoleted'),
Packit Service 21c75c
                              'Obsoleting'   : _('Obsoleting'),
Packit Service 21c75c
                              'Erase'        : _('Erase'),
Packit Service 21c75c
                              'Reinstall'    : _('Reinstall'),
Packit Service 21c75c
                              'Downgrade'    : _('Downgrade'),
Packit Service 21c75c
                              'Downgraded'   : _('Downgraded'),
Packit Service 21c75c
                              'Update'       : _('Upgrade'),
Packit Service 21c75c
                              'Updated'      : _('Upgraded'),
Packit Service 21c75c
                              }
Packit Service 21c75c
    def historyInfoCmdPkgsAltered(self, old, pats=[]):
Packit Service 21c75c
        """Print information about how packages are altered in a transaction.
Packit Service 21c75c
Packit Service 21c75c
        :param old: the :class:`DnfSwdbTrans` to
Packit Service 21c75c
           print information about
Packit Service 21c75c
        :param pats: a list of patterns.  Packages that match a patten
Packit Service 21c75c
           in *pats* will be highlighted in the output
Packit Service 21c75c
        """
Packit Service 21c75c
        #  Note that these don't use _simple_pkg() because we are showing what
Packit Service 21c75c
        # happened to them in the transaction ... not the difference between the
Packit Service 21c75c
        # version in the transaction and now.
Packit Service 21c75c
        all_uistates = self._history_state2uistate
Packit Service 21c75c
        maxlen = 0
Packit Service 21c75c
        pkg_max_len = 0
Packit Service 21c75c
Packit Service 21c75c
        packages = old.packages()
Packit Service 21c75c
Packit Service 21c75c
        for pkg in packages:
Packit Service 21c75c
            uistate = all_uistates.get(pkg.action_name, pkg.action_name)
Packit Service 21c75c
            if maxlen < len(uistate):
Packit Service 21c75c
                maxlen = len(uistate)
Packit Service 21c75c
            pkg_len = len(str(pkg))
Packit Service 21c75c
            if pkg_max_len < pkg_len:
Packit Service 21c75c
                pkg_max_len = pkg_len
Packit Service 21c75c
Packit Service 21c75c
        for pkg in packages:
Packit Service 21c75c
            prefix = " " * 4
Packit Service 21c75c
            if pkg.state != libdnf.transaction.TransactionItemState_DONE:
Packit Service 21c75c
                prefix = " ** "
Packit Service 21c75c
Packit Service 21c75c
            highlight = 'normal'
Packit Service 21c75c
            if pats:
Packit Service 21c75c
                if any([pkg.match(pat) for pat in pats]):
Packit Service 21c75c
                    highlight = 'bold'
Packit Service 21c75c
            (hibeg, hiend) = self._highlight(highlight)
Packit Service 21c75c
Packit Service 21c75c
            uistate = all_uistates.get(pkg.action_name, pkg.action_name)
Packit Service 21c75c
            uistate = fill_exact_width(ucd(uistate), maxlen)
Packit Service 21c75c
Packit Service 21c75c
            print("%s%s%s%s %-*s %s" % (prefix, hibeg, uistate, hiend,
Packit Service 21c75c
                                        pkg_max_len, str(pkg),
Packit Service 21c75c
                                        pkg.ui_from_repo()))
Packit Service 21c75c
Packit Service 21c75c
class DepSolveProgressCallBack(dnf.callback.Depsolve):
Packit Service 21c75c
    """Provides text output callback functions for Dependency Solver callback."""
Packit Service 21c75c
Packit Service 21c75c
    def pkg_added(self, pkg, mode):
Packit Service 21c75c
        """Print information about a package being added to the
Packit Service 21c75c
        transaction set.
Packit Service 21c75c
Packit Service 21c75c
        :param pkgtup: tuple containing the package name, arch,
Packit Service 21c75c
           version, and repository
Packit Service 21c75c
        :param mode: a short string indicating why the package is
Packit Service 21c75c
           being added to the transaction set.
Packit Service 21c75c
Packit Service 21c75c
        Valid current values for *mode* are::
Packit Service 21c75c
Packit Service 21c75c
           i = the package will be installed
Packit Service 21c75c
           u = the package will be an update
Packit Service 21c75c
           e = the package will be erased
Packit Service 21c75c
           r = the package will be reinstalled
Packit Service 21c75c
           d = the package will be a downgrade
Packit Service 21c75c
           o = the package will be obsoleting another package
Packit Service 21c75c
           ud = the package will be updated
Packit Service 21c75c
           od = the package will be obsoleted
Packit Service 21c75c
        """
Packit Service 21c75c
        output = None
Packit Service 21c75c
        if mode == 'i':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be installed')
Packit Service 21c75c
        elif mode == 'u':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be an upgrade')
Packit Service 21c75c
        elif mode == 'e':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be erased')
Packit Service 21c75c
        elif mode == 'r':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be reinstalled')
Packit Service 21c75c
        elif mode == 'd':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be a downgrade')
Packit Service 21c75c
        elif mode == 'o':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be obsoleting')
Packit Service 21c75c
        elif mode == 'ud':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be upgraded')
Packit Service 21c75c
        elif mode == 'od':
Packit Service 21c75c
            output = _('---> Package %s.%s %s will be obsoleted')
Packit Service 21c75c
Packit Service 21c75c
        if output:
Packit Service 21c75c
            logger.debug(output, pkg.name, pkg.arch, pkg.evr)
Packit Service 21c75c
Packit Service 21c75c
    def start(self):
Packit Service 21c75c
        """Perform setup at the beginning of the dependency solving
Packit Service 21c75c
        process.
Packit Service 21c75c
        """
Packit Service 21c75c
        logger.debug(_('--> Starting dependency resolution'))
Packit Service 21c75c
Packit Service 21c75c
    def end(self):
Packit Service 21c75c
        """Output a message stating that dependency resolution has finished."""
Packit Service 21c75c
        logger.debug(_('--> Finished dependency resolution'))
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
class CliKeyImport(dnf.callback.KeyImport):
Packit Service 21c75c
    def __init__(self, base, output):
Packit Service 21c75c
        self.base = base
Packit Service 21c75c
        self.output = output
Packit Service 21c75c
Packit Service 21c75c
    def _confirm(self, id, userid, fingerprint, url, timestamp):
Packit Service 21c75c
Packit Service 21c75c
        def short_id(id):
Packit Service 21c75c
            rj = '0' if dnf.pycomp.PY3 else b'0'
Packit Service 21c75c
            return id[-8:].rjust(8, rj)
Packit Service 21c75c
Packit Service 21c75c
        msg = (_('Importing GPG key 0x%s:\n'
Packit Service 21c75c
                 ' Userid     : "%s"\n'
Packit Service 21c75c
                 ' Fingerprint: %s\n'
Packit Service 21c75c
                 ' From       : %s') %
Packit Service 21c75c
               (short_id(id), userid,
Packit Service 21c75c
                dnf.crypto._printable_fingerprint(fingerprint),
Packit Service 21c75c
                url.replace("file://", "")))
Packit Service 21c75c
        logger.critical("%s", msg)
Packit Service 21c75c
Packit Service 21c75c
        if self.base.conf.assumeyes:
Packit Service 21c75c
            return True
Packit Service 21c75c
        if self.base.conf.assumeno:
Packit Service 21c75c
            return False
Packit Service 21c75c
        return self.output.userconfirm()
Packit Service 21c75c
Packit Service 21c75c
Packit Service a86e0b
class CliTransactionDisplay(TransactionDisplay):
Packit Service 21c75c
    """A YUM specific callback class for RPM operations."""
Packit Service 21c75c
Packit Service 21c75c
    width = property(lambda self: dnf.cli.term._term_width())
Packit Service 21c75c
Packit Service 21c75c
    def __init__(self):
Packit Service 21c75c
        super(CliTransactionDisplay, self).__init__()
Packit Service 21c75c
        self.lastmsg = ""
Packit Service 21c75c
        self.lastpackage = None # name of last package we looked at
Packit Service 21c75c
        self.output = True
Packit Service 21c75c
Packit Service 21c75c
        # for a progress bar
Packit Service 21c75c
        self.mark = "="
Packit Service 21c75c
        self.marks = 22
Packit Service 21c75c
Packit Service 21c75c
    def progress(self, package, action, ti_done, ti_total, ts_done, ts_total):
Packit Service 21c75c
        """Output information about an rpm operation.  This may
Packit Service 21c75c
        include a text progress bar.
Packit Service 21c75c
Packit Service 21c75c
        :param package: the package involved in the event
Packit Service 21c75c
        :param action: the type of action that is taking place.  Valid
Packit Service 21c75c
           values are given by
Packit Service a86e0b
           :func:`rpmtrans.TransactionDisplay.action.keys()`
Packit Service 21c75c
        :param ti_done: a number representing the amount of work
Packit Service 21c75c
           already done in the current transaction
Packit Service 21c75c
        :param ti_total: a number representing the total amount of work
Packit Service 21c75c
           to be done in the current transaction
Packit Service 21c75c
        :param ts_done: the number of the current transaction in
Packit Service 21c75c
           transaction set
Packit Service 21c75c
        :param ts_total: the total number of transactions in the
Packit Service 21c75c
           transaction set
Packit Service 21c75c
        """
Packit Service 21c75c
        action_str = dnf.transaction.ACTIONS.get(action)
Packit Service 21c75c
        if action_str is None:
Packit Service 21c75c
            return
Packit Service 21c75c
Packit Service 21c75c
        wid1 = self._max_action_width()
Packit Service 21c75c
Packit Service 21c75c
        pkgname = ucd(package)
Packit Service 21c75c
        self.lastpackage = package
Packit Service 21c75c
        if ti_total == 0:
Packit Service 21c75c
            percent = 0
Packit Service 21c75c
        else:
Packit Service 21c75c
            percent = (ti_done*long(100))//ti_total
Packit Service 21c75c
        self._out_progress(ti_done, ti_total, ts_done, ts_total,
Packit Service 21c75c
                           percent, action_str, pkgname, wid1)
Packit Service 21c75c
Packit Service 21c75c
    def _max_action_width(self):
Packit Service 21c75c
        if not hasattr(self, '_max_action_wid_cache'):
Packit Service 21c75c
            wid1 = 0
Packit Service 21c75c
            for val in dnf.transaction.ACTIONS.values():
Packit Service 21c75c
                wid_val = exact_width(val)
Packit Service 21c75c
                if wid1 < wid_val:
Packit Service 21c75c
                    wid1 = wid_val
Packit Service 21c75c
            self._max_action_wid_cache = wid1
Packit Service 21c75c
        wid1 = self._max_action_wid_cache
Packit Service 21c75c
        return wid1
Packit Service 21c75c
Packit Service 21c75c
    def _out_progress(self, ti_done, ti_total, ts_done, ts_total,
Packit Service 21c75c
                      percent, process, pkgname, wid1):
Packit Service 21c75c
        if self.output and (sys.stdout.isatty() or ti_done == ti_total):
Packit Service 21c75c
            (fmt, wid1, wid2) = self._makefmt(percent, ts_done, ts_total,
Packit Service 21c75c
                                              progress=sys.stdout.isatty(),
Packit Service 21c75c
                                              pkgname=pkgname, wid1=wid1)
Packit Service 21c75c
            pkgname = ucd(pkgname)
Packit Service 21c75c
            msg = fmt % (fill_exact_width(process, wid1, wid1),
Packit Service 21c75c
                         fill_exact_width(pkgname, wid2, wid2))
Packit Service 21c75c
            if msg != self.lastmsg:
Packit Service 21c75c
                dnf.util._terminal_messenger('write_flush', msg, sys.stdout)
Packit Service 21c75c
                self.lastmsg = msg
Packit Service 21c75c
                if ti_done == ti_total:
Packit Service 21c75c
                    print(" ")
Packit Service 21c75c
Packit Service 21c75c
    def _makefmt(self, percent, ts_done, ts_total, progress=True,
Packit Service 21c75c
                 pkgname=None, wid1=15):
Packit Service 21c75c
        l = len(str(ts_total))
Packit Service 21c75c
        size = "%s.%s" % (l, l)
Packit Service 21c75c
        fmt_done = "%" + size + "s/%" + size + "s"
Packit Service 21c75c
        done = fmt_done % (ts_done, ts_total)
Packit Service 21c75c
Packit Service 21c75c
        #  This should probably use TerminLine, but we don't want to dep. on
Packit Service 21c75c
        # that. So we kind do an ok job by hand ... at least it's dynamic now.
Packit Service 21c75c
        if pkgname is None:
Packit Service 21c75c
            pnl = 22
Packit Service 21c75c
        else:
Packit Service 21c75c
            pnl = exact_width(pkgname)
Packit Service 21c75c
Packit Service 21c75c
        overhead = (2 * l) + 2 # Length of done, above
Packit Service 21c75c
        overhead += 2 + wid1 +2 # Length of beginning ("  " action " :")
Packit Service 21c75c
        overhead += 1          # Space between pn and done
Packit Service 21c75c
        overhead += 2          # Ends for progress
Packit Service 21c75c
        overhead += 1          # Space for end
Packit Service 21c75c
        width = self.width
Packit Service 21c75c
        if width < overhead:
Packit Service 21c75c
            width = overhead    # Give up
Packit Service 21c75c
        width -= overhead
Packit Service 21c75c
        if pnl > width // 2:
Packit Service 21c75c
            pnl = width // 2
Packit Service 21c75c
Packit Service 21c75c
        marks = self.width - (overhead + pnl)
Packit Service 21c75c
        width = "%s.%s" % (marks, marks)
Packit Service 21c75c
        fmt_bar = "[%-" + width + "s]"
Packit Service 21c75c
        # pnl = str(28 + marks + 1)
Packit Service 21c75c
        full_pnl = pnl + marks + 1
Packit Service 21c75c
Packit Service 21c75c
        if progress and percent == 100: # Don't chop pkg name on 100%
Packit Service 21c75c
            fmt = "\r  %s: %s   " + done
Packit Service 21c75c
            wid2 = full_pnl
Packit Service 21c75c
        elif progress:
Packit Service 21c75c
            if marks > 5:
Packit Service 21c75c
                bar = fmt_bar % (self.mark * int(marks * (percent / 100.0)), )
Packit Service 21c75c
            else:
Packit Service 21c75c
                bar = ""
Packit Service 21c75c
            fmt = "\r  %s: %s " + bar + " " + done
Packit Service 21c75c
            wid2 = pnl
Packit Service 21c75c
        elif percent == 100:
Packit Service 21c75c
            fmt = "  %s: %s   " + done
Packit Service 21c75c
            wid2 = full_pnl
Packit Service 21c75c
        else:
Packit Service 21c75c
            if marks > 5:
Packit Service 21c75c
                bar = fmt_bar % (self.mark * marks, )
Packit Service 21c75c
            else:
Packit Service 21c75c
                bar = ""
Packit Service 21c75c
            fmt = "  %s: %s " + bar + " " + done
Packit Service 21c75c
            wid2 = pnl
Packit Service 21c75c
        return fmt, wid1, wid2
Packit Service 21c75c
Packit Service 21c75c
def progressbar(current, total, name=None):
Packit Service 21c75c
    """Output the current status to the terminal using a simple
Packit Service 21c75c
    text progress bar consisting of 50 # marks.
Packit Service 21c75c
Packit Service 21c75c
    :param current: a number representing the amount of work
Packit Service 21c75c
       already done
Packit Service 21c75c
    :param total: a number representing the total amount of work
Packit Service 21c75c
       to be done
Packit Service 21c75c
    :param name: a name to label the progress bar with
Packit Service 21c75c
    """
Packit Service 21c75c
Packit Service 21c75c
    mark = '#'
Packit Service 21c75c
    if not sys.stdout.isatty():
Packit Service 21c75c
        return
Packit Service 21c75c
Packit Service 21c75c
    if current == 0:
Packit Service 21c75c
        percent = 0
Packit Service 21c75c
    else:
Packit Service 21c75c
        if total != 0:
Packit Service 21c75c
            percent = float(current) / total
Packit Service 21c75c
        else:
Packit Service 21c75c
            percent = 0
Packit Service 21c75c
Packit Service 21c75c
    width = dnf.cli.term._term_width()
Packit Service 21c75c
Packit Service 21c75c
    if name is None and current == total:
Packit Service 21c75c
        name = '-'
Packit Service 21c75c
Packit Service 21c75c
    end = ' %d/%d' % (current, total)
Packit Service 21c75c
    width -= len(end) + 1
Packit Service 21c75c
    if width < 0:
Packit Service 21c75c
        width = 0
Packit Service 21c75c
    if name is None:
Packit Service 21c75c
        width -= 2
Packit Service 21c75c
        if width < 0:
Packit Service 21c75c
            width = 0
Packit Service 21c75c
        hashbar = mark * int(width * percent)
Packit Service 21c75c
        output = '\r[%-*s]%s' % (width, hashbar, end)
Packit Service 21c75c
    elif current == total: # Don't chop name on 100%
Packit Service 21c75c
        output = '\r%s%s' % (fill_exact_width(name, width, width), end)
Packit Service 21c75c
    else:
Packit Service 21c75c
        width -= 4
Packit Service 21c75c
        if width < 0:
Packit Service 21c75c
            width = 0
Packit Service 21c75c
        nwid = width // 2
Packit Service 21c75c
        if nwid > exact_width(name):
Packit Service 21c75c
            nwid = exact_width(name)
Packit Service 21c75c
        width -= nwid
Packit Service 21c75c
        hashbar = mark * int(width * percent)
Packit Service 21c75c
        output = '\r%s: [%-*s]%s' % (fill_exact_width(name, nwid, nwid), width,
Packit Service 21c75c
                                     hashbar, end)
Packit Service 21c75c
Packit Service 21c75c
    if current <= total:
Packit Service 21c75c
        dnf.util._terminal_messenger('write', output, sys.stdout)
Packit Service 21c75c
Packit Service 21c75c
    if current == total:
Packit Service 21c75c
        dnf.util._terminal_messenger('write', '\n', sys.stdout)
Packit Service 21c75c
Packit Service 21c75c
    dnf.util._terminal_messenger('flush', out=sys.stdout)