Changeset 516 for yum/trunk/output.py


Ignore:
Timestamp:
Feb 3, 2015, 9:39:54 AM (11 years ago)
Author:
Yuri Dario
Message:

yum: update trunk to 3.4.3.

Location:
yum/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • yum/trunk

  • yum/trunk/output.py

    r2 r516  
    3939from yum.constants import *
    4040
    41 from yum import logginglevels, _
     41from yum import logginglevels, _, P_
    4242from yum.rpmtrans import RPMBaseCallback
    4343from yum.packageSack import packagesNewestByNameArch
    4444import yum.packages
     45
     46import yum.history
    4547
    4648from yum.i18n import utf8_width, utf8_width_fill, utf8_text_fill
     
    380382            data[d] = sorted(pdata[d].items())
    381383
     384        #  We start allocating 1 char to everything but the last column, and a
     385        # space between each (again, except for the last column). Because
     386        # at worst we are better with:
     387        # |one two three|
     388        # | four        |
     389        # ...than:
     390        # |one two three|
     391        # |            f|
     392        # |our          |
     393        # ...the later being what we get if we pre-allocate the last column, and
     394        # thus. the space, due to "three" overflowing it's column by 2 chars.
    382395        if columns is None:
    383             columns = [1] * cols
     396            columns = [1] * (cols - 1)
     397            columns.append(0)
    384398
    385399        total_width -= (sum(columns) + (cols - 1) + utf8_width(indent))
     400        if not columns[-1]:
     401            total_width += 1
    386402        while total_width > 0:
    387403            # Find which field all the spaces left will help best
     
    407423            if helps:
    408424                diff = data[val].pop(0)[0] - columns[val]
     425                if not columns[val] and (val == (cols - 1)):
     426                    #  If we are going from 0 => N on the last column, take 1
     427                    # for the space before the column.
     428                    total_width  -= 1
    409429                columns[val] += diff
    410430                total_width  -= diff
     
    453473        return (val, width, hibeg, hiend)
    454474
    455     def fmtColumns(self, columns, msg=u'', end=u''):
    456         """ Return a string for columns of data, which can overflow."""
     475    def fmtColumns(self, columns, msg=u'', end=u'', text_width=utf8_width):
     476        """ Return a string for columns of data, which can overflow.
     477            text_width parameter finds the width of columns, this defaults to
     478            utf8 but can be changed to len() if you know it'll be fine. """
    457479
    458480        total_width = len(msg)
     
    467489
    468490            (align, width) = self._fmt_column_align_width(width)
    469             if utf8_width(val) <= width:
    470                 msg += u"%s "
    471                 val = utf8_width_fill(val, width, left=(align == u'-'),
    472                                       prefix=hibeg, suffix=hiend)
    473                 data.append(val)
     491            val_width = text_width(val)
     492            if val_width <= width:
     493                #  Don't use utf8_width_fill() because it sucks performance
     494                # wise for 1,000s of rows. Also allows us to use len(), when
     495                # we can.
     496                msg += u"%s%s%s%s "
     497                if (align == u'-'):
     498                    data.extend([hibeg, val, " " * (width - val_width), hiend])
     499                else:
     500                    data.extend([hibeg, " " * (width - val_width), val, hiend])
    474501            else:
    475502                msg += u"%s%s%s\n" + " " * (total_width + width + 1)
     
    496523        rid = pkg.ui_from_repo
    497524        columns = zip((na, ver, rid), columns, hi_cols)
    498         print self.fmtColumns(columns)
     525        print self.fmtColumns(columns, text_width=len)
    499526
    500527    def simpleEnvraList(self, pkg, ui_overflow=False,
     
    509536        rid = pkg.ui_from_repo
    510537        columns = zip((envra, rid), columns, hi_cols)
    511         print self.fmtColumns(columns)
     538        print self.fmtColumns(columns, text_width=len)
    512539
    513540    def fmtKeyValFill(self, key, val):
     
    552579    def infoOutput(self, pkg, highlight=False):
    553580        (hibeg, hiend) = self._highlight(highlight)
    554         print _("Name       : %s%s%s") % (hibeg, to_unicode(pkg.name), hiend)
    555         print _("Arch       : %s") % to_unicode(pkg.arch)
     581        print _("Name        : %s%s%s") % (hibeg, to_unicode(pkg.name), hiend)
     582        print _("Arch        : %s") % to_unicode(pkg.arch)
    556583        if pkg.epoch != "0":
    557             print _("Epoch      : %s") % to_unicode(pkg.epoch)
    558         print _("Version    : %s") % to_unicode(pkg.version)
    559         print _("Release    : %s") % to_unicode(pkg.release)
    560         print _("Size       : %s") % self.format_number(float(pkg.size))
    561         print _("Repo       : %s") % to_unicode(pkg.repoid)
     584            print _("Epoch       : %s") % to_unicode(pkg.epoch)
     585        print _("Version     : %s") % to_unicode(pkg.version)
     586        print _("Release     : %s") % to_unicode(pkg.release)
     587        print _("Size        : %s") % self.format_number(float(pkg.size))
     588        print _("Repo        : %s") % to_unicode(pkg.repoid)
    562589        if pkg.repoid == 'installed' and 'from_repo' in pkg.yumdb_info:
    563             print _("From repo  : %s") % to_unicode(pkg.yumdb_info.from_repo)
     590            print _("From repo   : %s") % to_unicode(pkg.yumdb_info.from_repo)
    564591        if self.verbose_logger.isEnabledFor(logginglevels.DEBUG_3):
    565             print _("Committer  : %s") % to_unicode(pkg.committer)
    566             print _("Committime : %s") % time.ctime(pkg.committime)
    567             print _("Buildtime  : %s") % time.ctime(pkg.buildtime)
     592            print _("Committer   : %s") % to_unicode(pkg.committer)
     593            print _("Committime  : %s") % time.ctime(pkg.committime)
     594            print _("Buildtime   : %s") % time.ctime(pkg.buildtime)
    568595            if hasattr(pkg, 'installtime'):
    569                 print _("Installtime: %s") % time.ctime(pkg.installtime)
    570         print self.fmtKeyValFill(_("Summary    : "), self._enc(pkg.summary))
     596                print _("Install time: %s") % time.ctime(pkg.installtime)
     597            if pkg.repoid == 'installed':
     598                uid = None
     599                if 'installed_by' in pkg.yumdb_info:
     600                    try:
     601                        uid = int(pkg.yumdb_info.installed_by)
     602                    except ValueError: # In case int() fails
     603                        uid = None
     604                print _("Installed by: %s") % self._pwd_ui_username(uid)
     605                uid = None
     606                if 'changed_by' in pkg.yumdb_info:
     607                    try:
     608                        uid = int(pkg.yumdb_info.changed_by)
     609                    except ValueError: # In case int() fails
     610                        uid = None
     611                print _("Changed by  : %s") % self._pwd_ui_username(uid)
     612        print self.fmtKeyValFill(_("Summary     : "), self._enc(pkg.summary))
    571613        if pkg.url:
    572             print _("URL        : %s") % to_unicode(pkg.url)
    573         print self.fmtKeyValFill(_("License    : "), to_unicode(pkg.license))
    574         print self.fmtKeyValFill(_("Description: "), self._enc(pkg.description))
     614            print _("URL         : %s") % to_unicode(pkg.url)
     615        print self.fmtKeyValFill(_("License     : "), to_unicode(pkg.license))
     616        print self.fmtKeyValFill(_("Description : "),self._enc(pkg.description))
    575617        print ""
    576618   
     
    743785        if group.ui_description:
    744786            print _(' Description: %s') % to_unicode(group.ui_description)
     787        if group.langonly:
     788            print _(' Language: %s') % group.langonly
    745789
    746790        sections = ((_(' Mandatory Packages:'),   group.mandatory_packages),
     
    766810        """take a list of findDeps results and 'pretty print' the output"""
    767811       
    768         for pkg in results:
     812        verb = self.verbose_logger.isEnabledFor(logginglevels.DEBUG_3)
     813        for pkg in sorted(results):
    769814            print _("package: %s") % pkg.compactPrint()
    770815            if len(results[pkg]) == 0:
     
    772817                continue
    773818
    774             for req in results[pkg]:
     819            for req in sorted(results[pkg]):
    775820                reqlist = results[pkg][req]
    776821                print _("  dependency: %s") % prco_tuple_to_string(req)
     
    779824                    continue
    780825               
    781                 for po in reqlist:
     826                seen = {}
     827                for po in reversed(sorted(reqlist)):
     828                    key = (po.name, po.arch)
     829                    if not verb and key in seen:
     830                        continue
     831                    seen[key] = po
    782832                    print "   provider: %s" % po.compactPrint()
    783833
     
    848898            return
    849899
    850         print _("Repo        : %s") % po.repoid
    851         print _('Matched from:')
     900        print _("Repo        : %s") % po.ui_from_repo
     901        done = False
    852902        for item in yum.misc.unique(values):
    853903            item = to_utf8(item)
     
    855905                continue # Skip double name/summary printing
    856906
     907            if not done:
     908                print _('Matched from:')
     909                done = True
    857910            can_overflow = True
    858911            if False: pass
     
    928981                                        _("Installed size: %s"),
    929982                                        self.format_number(insize))
     983
     984    def reportRemoveSize(self, packages):
     985        """Report the total size of packages being removed. """
     986        totsize = 0
     987        error = False
     988        for pkg in packages:
     989            # Just to be on the safe side, if for some reason getting
     990            # the package size fails, log the error and don't report download
     991            # size
     992            try:
     993                size = int(pkg.size)
     994                totsize += size
     995            except:
     996                error = True
     997                self.logger.error(_('There was an error calculating installed size'))
     998                break
     999        if (not error):
     1000            self.verbose_logger.log(logginglevels.INFO_1,
     1001                                    _("Installed size: %s"),
     1002                                    self.format_number(totsize))
    9301003           
    9311004    def listTransaction(self):
     
    9791052
    9801053        for (action, pkglist) in [(_('Skipped (dependency problems)'),
    981                                    self.skipped_packages),]:
     1054                                   self.skipped_packages),
     1055                                  (_('Not installed'), self._not_found_i.values()),
     1056                                  (_('Not available'), self._not_found_a.values())]:
    9821057            lines = []
    9831058            for po in pkglist:
     
    10241099                out.append(totalmsg)
    10251100
    1026         summary = _("""
     1101        out.append(_("""
    10271102Transaction Summary
    10281103%s
    1029 """) % ('=' * self.term.columns,)
    1030         out.append(summary)
    1031         num_in = len(self.tsInfo.installed + self.tsInfo.depinstalled)
    1032         num_up = len(self.tsInfo.updated + self.tsInfo.depupdated)
    1033         summary = _("""\
    1034 Install   %5.5s Package(s)
    1035 Upgrade   %5.5s Package(s)
    1036 """) % (num_in, num_up,)
    1037         if num_in or num_up: # Always do this?
    1038             out.append(summary)
    1039         num_rm = len(self.tsInfo.removed + self.tsInfo.depremoved)
    1040         num_re = len(self.tsInfo.reinstalled)
    1041         num_dg = len(self.tsInfo.downgraded)
    1042         summary = _("""\
    1043 Remove    %5.5s Package(s)
    1044 Reinstall %5.5s Package(s)
    1045 Downgrade %5.5s Package(s)
    1046 """) % (num_rm, num_re, num_dg)
    1047         if num_rm or num_re or num_dg:
    1048             out.append(summary)
    1049        
     1104""") % ('=' * self.term.columns))
     1105        for action, count in (
     1106            (_('Install'), len(self.tsInfo.installed) + len(self.tsInfo.depinstalled)),
     1107            (_('Upgrade'), len(self.tsInfo.updated) + len(self.tsInfo.depupdated)),
     1108            (_('Remove'), len(self.tsInfo.removed) + len(self.tsInfo.depremoved)),
     1109            (_('Reinstall'), len(self.tsInfo.reinstalled)),
     1110            (_('Downgrade'), len(self.tsInfo.downgraded)),
     1111        ):
     1112            if count: out.append('%-9s %5d %s\n' % (
     1113                action, count, P_('Package', 'Packages', count),
     1114            ))
    10501115        return ''.join(out)
    10511116       
     
    11221187        # One of these is a download
    11231188        if self.conf.debuglevel < 2 or not sys.stdout.isatty():
    1124             self.repos.setProgressBar(None)
    1125             self.repos.callback = None
     1189            progressbar = None
     1190            callback = None
    11261191        else:
    1127             self.repos.setProgressBar(YumTextMeter(fo=sys.stdout))
    1128             self.repos.callback = CacheProgressCallback()
     1192            progressbar = YumTextMeter(fo=sys.stdout)
     1193            callback = CacheProgressCallback()
    11291194
    11301195        # setup our failure report for failover
    11311196        freport = (self.failureReport,(),{})
    1132         self.repos.setFailureCallback(freport)
     1197        failure_callback = freport
    11331198
    11341199        # setup callback for CTRL-C's
    1135         self.repos.setInterruptCallback(self.interrupt_callback)
    1136        
     1200        interrupt_callback = self.interrupt_callback
     1201        if hasattr(self, 'prerepoconf'):
     1202            self.prerepoconf.progressbar = progressbar
     1203            self.prerepoconf.callback = callback
     1204            self.prerepoconf.failure_callback = failure_callback
     1205            self.prerepoconf.interrupt_callback = interrupt_callback
     1206        else:
     1207            #  Just in case some API user decides to do self.repos before
     1208            # calling us.
     1209            self.repos.setProgressBar(progressbar)
     1210            self.repos.callback = callback
     1211            self.repos.setFailureCallback(failure_callback)
     1212            self.repos.setInterruptCallback(interrupt_callback)
     1213
    11371214        # setup our depsolve progress callback
    11381215        dscb = DepSolveProgressCallBack(weakref(self))
     
    11441221   
    11451222    def setupKeyImportCallbacks(self):
    1146         self.repos.confirm_func = self._cli_confirm_gpg_key_import
    1147         self.repos.gpg_import_func = self.getKeyForRepo
     1223        confirm_func = self._cli_confirm_gpg_key_import
     1224        gpg_import_func = self.getKeyForRepo
     1225        gpgca_import_func = self.getCAKeyForRepo
     1226        if hasattr(self, 'prerepoconf'):
     1227            self.prerepoconf.confirm_func = confirm_func
     1228            self.prerepoconf.gpg_import_func = gpg_import_func
     1229            self.prerepoconf.gpgca_import_func = gpgca_import_func
     1230        else:
     1231            self.repos.confirm_func = confirm_func
     1232            self.repos.gpg_import_func = gpg_import_func
     1233            self.repos.gpgca_import_func = gpgca_import_func
    11481234
    11491235    def interrupt_callback(self, cbobj):
     
    12331319
    12341320    def _pwd_ui_username(self, uid, limit=None):
    1235         # loginuid is set to -1 on init.
    1236         if uid is None or uid == 0xFFFFFFFF:
     1321        if type(uid) == type([]):
     1322            return [self._pwd_ui_username(u, limit) for u in uid]
     1323
     1324        # loginuid is set to      -1 (0xFFFF_FFFF) on init, in newer kernels.
     1325        # loginuid is set to INT_MAX (0x7FFF_FFFF) on init, in older kernels.
     1326        if uid is None or uid in (0xFFFFFFFF, 0x7FFFFFFF):
    12371327            loginid = _("<unset>")
    12381328            name = _("System") + " " + loginid
     
    12411331            return to_unicode(name)
    12421332
     1333        def _safe_split_0(text, *args):
     1334            """ Split gives us a [0] for everything _but_ '', this function
     1335                returns '' in that case. """
     1336            ret = text.split(*args)
     1337            if not ret:
     1338                return ''
     1339            return ret[0]
     1340
    12431341        try:
    12441342            user = pwd.getpwuid(uid)
    1245             fullname = user.pw_gecos.split(';', 2)[0]
     1343            fullname = _safe_split_0(user.pw_gecos, ';', 2)
    12461344            name = "%s <%s>" % (fullname, user.pw_name)
    12471345            if limit is not None and len(name) > limit:
    1248                 name = "%s ... <%s>" % (fullname.split()[0], user.pw_name)
     1346                name = "%s ... <%s>" % (_safe_split_0(fullname), user.pw_name)
    12491347                if len(name) > limit:
    12501348                    name = "<%s>" % user.pw_name
     
    12531351            return to_unicode(str(uid))
    12541352
     1353    @staticmethod
     1354    def _historyRangeRTIDs(old, tid):
     1355        ''' Convert a user "TID" string of 2..4 into: (2, 4). '''
     1356        def str2int(x):
     1357            try:
     1358                if x == 'last' or x.startswith('last-'):
     1359                    tid = old.tid
     1360                    if x.startswith('last-'):
     1361                        off = int(x[len('last-'):])
     1362                        if off <= 0:
     1363                            int("z")
     1364                        tid -= off
     1365                    return tid
     1366                return int(x)
     1367            except ValueError:
     1368                return None
     1369
     1370        if '..' not in tid:
     1371            return None
     1372        btid, etid = tid.split('..', 2)
     1373        btid = str2int(btid)
     1374        if btid > old.tid:
     1375            return None
     1376        elif btid <= 0:
     1377            return None
     1378        etid = str2int(etid)
     1379        if etid > old.tid:
     1380            return None
     1381
     1382        if btid is None or etid is None:
     1383            return None
     1384
     1385        # Have a range ... do a "merged" transaction.
     1386        if btid > etid:
     1387            btid, etid = etid, btid
     1388        return (btid, etid)
     1389
     1390    def _historyRangeTIDs(self, rtids):
     1391        ''' Convert a list of ranged tid typles into all the tids needed, Eg.
     1392            [(2,4), (6,8)] == [2, 3, 4, 6, 7, 8]. '''
     1393        tids = set()
     1394        last_end = -1 # This just makes displaying it easier...
     1395        for mtid in sorted(rtids):
     1396            if mtid[0] < last_end:
     1397                self.logger.warn(_('Skipping merged transaction %d to %d, as it overlaps' % (mtid[0], mtid[1])))
     1398                continue # Don't do overlapping
     1399            last_end = mtid[1]
     1400            for num in range(mtid[0], mtid[1] + 1):
     1401                tids.add(num)
     1402        return tids
     1403
    12551404    def _history_list_transactions(self, extcmds):
     1405        old = self.history.last()
     1406        if old is None:
     1407            self.logger.critical(_('No transactions'))
     1408            return None, None
     1409
    12561410        tids = set()
    12571411        pats = []
     
    12671421                tids.add(tid)
    12681422            except ValueError:
     1423                rtid = self._historyRangeRTIDs(old, tid)
     1424                if rtid:
     1425                    tids.update(self._historyRangeTIDs([rtid]))
     1426                    continue
    12691427                pats.append(tid)
    12701428        if pats:
     
    12811439        tids, printall = self._history_list_transactions(extcmds)
    12821440        if tids is None:
    1283             return 1, ['Failed history info']
     1441            return 1, ['Failed history list']
     1442
     1443        limit = 20
     1444        if printall:
     1445            limit = None
     1446
     1447        old_tids = self.history.old(tids, limit=limit)
     1448        done = 0
     1449        if self.conf.history_list_view == 'users':
     1450            uids = [1,2]
     1451        elif self.conf.history_list_view == 'commands':
     1452            uids = [1]
     1453        else:
     1454            assert self.conf.history_list_view == 'single-user-commands'
     1455            uids = set()
     1456            blanks = 0
     1457            for old in old_tids:
     1458                if not printall and done >= limit:
     1459                    break
     1460
     1461                done += 1
     1462                if old.cmdline is None:
     1463                    blanks += 1
     1464                uids.add(old.loginuid)
     1465            if len(uids) == 1 and blanks > (done / 2):
     1466                uids.add('blah')
    12841467
    12851468        fmt = "%s | %s | %s | %s | %s"
     1469        if len(uids) == 1:
     1470            name = _("Command line")
     1471        else:
     1472            name = _("Login user")
    12861473        print fmt % (utf8_width_fill(_("ID"), 6, 6),
    1287                      utf8_width_fill(_("Login user"), 22, 22),
     1474                     utf8_width_fill(name, 24, 24),
    12881475                     utf8_width_fill(_("Date and time"), 16, 16),
    12891476                     utf8_width_fill(_("Action(s)"), 14, 14),
     
    12921479        fmt = "%6u | %s | %-16.16s | %s | %4u"
    12931480        done = 0
    1294         limit = 20
    1295         if printall:
    1296             limit = None
    1297         for old in self.history.old(tids, limit=limit):
     1481        for old in old_tids:
    12981482            if not printall and done >= limit:
    12991483                break
    13001484
    13011485            done += 1
    1302             name = self._pwd_ui_username(old.loginuid, 22)
     1486            if len(uids) == 1:
     1487                name = old.cmdline or ''
     1488            else:
     1489                name = self._pwd_ui_username(old.loginuid, 24)
    13031490            tm = time.strftime("%Y-%m-%d %H:%M",
    13041491                               time.localtime(old.beg_timestamp))
    13051492            num, uiacts = self._history_uiactions(old.trans_data)
    1306             name   = utf8_width_fill(name,   22, 22)
     1493            name   = utf8_width_fill(name,   24, 24)
    13071494            uiacts = utf8_width_fill(uiacts, 14, 14)
    13081495            rmark = lmark = ' '
     
    13111498            elif old.return_code:
    13121499                rmark = lmark = '#'
     1500                # We don't check .errors, because return_code will be non-0
     1501            elif old.output:
     1502                rmark = lmark = 'E'
     1503            elif old.rpmdb_problems:
     1504                rmark = lmark = 'P'
     1505            elif old.trans_skip:
     1506                rmark = lmark = 's'
    13131507            if old.altered_lt_rpmdb:
    13141508                rmark = '<'
     
    13711565
    13721566    def historyInfoCmd(self, extcmds):
     1567        def str2int(x):
     1568            try:
     1569                return int(x)
     1570            except ValueError:
     1571                return None
     1572
    13731573        tids = set()
     1574        mtids = set()
    13741575        pats = []
     1576        old = self.history.last()
     1577        if old is None:
     1578            self.logger.critical(_('No transactions'))
     1579            return 1, ['Failed history info']
     1580
    13751581        for tid in extcmds[1:]:
    1376             try:
    1377                 int(tid)
    1378                 tids.add(tid)
    1379             except ValueError:
    1380                 pats.append(tid)
     1582            if self._historyRangeRTIDs(old, tid):
     1583                # Have a range ... do a "merged" transaction.
     1584                mtids.add(self._historyRangeRTIDs(old, tid))
     1585                continue
     1586            elif str2int(tid) is not None:
     1587                tids.add(str2int(tid))
     1588                continue
     1589            pats.append(tid)
    13811590        if pats:
    13821591            tids.update(self.history.search(pats))
     1592        utids = tids.copy()
     1593        if mtids:
     1594            mtids = sorted(mtids)
     1595            tids.update(self._historyRangeTIDs(mtids))
    13831596
    13841597        if not tids and len(extcmds) < 2:
     
    13861599            if old is not None:
    13871600                tids.add(old.tid)
     1601                utids.add(old.tid)
    13881602
    13891603        if not tids:
     
    13971611
    13981612        done = False
     1613        bmtid, emtid = -1, -1
     1614        mobj = None
     1615        if mtids:
     1616            bmtid, emtid = mtids.pop(0)
    13991617        for tid in self.history.old(tids):
    14001618            if lastdbv is not None and tid.tid == lasttid:
     
    14061624            lastdbv = None
    14071625
     1626            if tid.tid >= bmtid and tid.tid <= emtid:
     1627                if mobj is None:
     1628                    mobj = yum.history.YumMergedHistoryTransaction(tid)
     1629                else:
     1630                    mobj.merge(tid)
     1631            elif mobj is not None:
     1632                if done:
     1633                    print "-" * 79
     1634                done = True
     1635
     1636                self._historyInfoCmd(mobj)
     1637                mobj = None
     1638                if mtids:
     1639                    bmtid, emtid = mtids.pop(0)
     1640                    if tid.tid >= bmtid and tid.tid <= emtid:
     1641                        mobj = yum.history.YumMergedHistoryTransaction(tid)
     1642
     1643            if tid.tid in utids:
     1644                if done:
     1645                    print "-" * 79
     1646                done = True
     1647
     1648                self._historyInfoCmd(tid, pats)
     1649
     1650        if mobj is not None:
    14081651            if done:
    14091652                print "-" * 79
    1410             done = True
    1411             self._historyInfoCmd(tid, pats)
     1653
     1654            self._historyInfoCmd(mobj)
     1655
     1656    def _hpkg2from_repo(self, hpkg):
     1657        """ Given a pkg, find the ipkg.ui_from_repo ... if none, then
     1658            get an apkg. ... and put a ? in there. """
     1659        ipkgs = self.rpmdb.searchPkgTuple(hpkg.pkgtup)
     1660        if not ipkgs:
     1661            apkgs = self.pkgSack.searchPkgTuple(hpkg.pkgtup)
     1662            if not apkgs:
     1663                return '?'
     1664            return '@?' + str(apkgs[0].repoid)
     1665
     1666        return ipkgs[0].ui_from_repo
    14121667
    14131668    def _historyInfoCmd(self, old, pats=[]):
    14141669        name = self._pwd_ui_username(old.loginuid)
    14151670
    1416         print _("Transaction ID :"), old.tid
     1671        _pkg_states_installed = {'i' : _('Installed'), 'e' : _('Erased'),
     1672                                 'o' : _('Updated'), 'n' : _('Downgraded')}
     1673        _pkg_states_available = {'i' : _('Installed'), 'e' : _('Not installed'),
     1674                                 'o' : _('Older'), 'n' : _('Newer')}
     1675        # max() only in 2.5.z
     1676        maxlen = sorted([len(x) for x in (_pkg_states_installed.values() +
     1677                                          _pkg_states_available.values())])[-1]
     1678        _pkg_states_installed['maxlen'] = maxlen
     1679        _pkg_states_available['maxlen'] = maxlen
     1680        def _simple_pkg(pkg, prefix_len, was_installed=False, highlight=False,
     1681                        pkg_max_len=0):
     1682            prefix = " " * prefix_len
     1683            if was_installed:
     1684                _pkg_states = _pkg_states_installed
     1685            else:
     1686                _pkg_states = _pkg_states_available
     1687            state  = _pkg_states['i']
     1688            ipkgs = self.rpmdb.searchNames([hpkg.name])
     1689            ipkgs.sort()
     1690            if not ipkgs:
     1691                state  = _pkg_states['e']
     1692            elif hpkg.pkgtup in (ipkg.pkgtup for ipkg in ipkgs):
     1693                pass
     1694            elif ipkgs[-1] > hpkg:
     1695                state  = _pkg_states['o']
     1696            elif ipkgs[0] < hpkg:
     1697                state  = _pkg_states['n']
     1698            else:
     1699                assert False, "Impossible, installed not newer and not older"
     1700            if highlight:
     1701                (hibeg, hiend) = self._highlight('bold')
     1702            else:
     1703                (hibeg, hiend) = self._highlight('normal')
     1704            state = utf8_width_fill(state, _pkg_states['maxlen'])
     1705            print "%s%s%s%s %-*s %s" % (prefix, hibeg, state, hiend,
     1706                                        pkg_max_len, hpkg,
     1707                                        self._hpkg2from_repo(hpkg))
     1708
     1709        if type(old.tid) == type([]):
     1710            print _("Transaction ID :"), "%u..%u" % (old.tid[0], old.tid[-1])
     1711        else:
     1712            print _("Transaction ID :"), old.tid
    14171713        begtm = time.ctime(old.beg_timestamp)
    14181714        print _("Begin time     :"), begtm
     
    14351731                    sofar += len(begtms[i]) + 1
    14361732                endtm = (' ' * sofar) + endtm[sofar:]
    1437             diff = _("(%s seconds)") % (old.end_timestamp - old.beg_timestamp)
     1733            diff = old.end_timestamp - old.beg_timestamp
     1734            if diff < 5 * 60:
     1735                diff = _("(%u seconds)") % diff
     1736            elif diff < 5 * 60 * 60:
     1737                diff = _("(%u minutes)") % (diff / 60)
     1738            elif diff < 5 * 60 * 60 * 24:
     1739                diff = _("(%u hours)") % (diff / (60 * 60))
     1740            else:
     1741                diff = _("(%u days)") % (diff / (60 * 60 * 24))
    14381742            print _("End time       :"), endtm, diff
    14391743        if old.end_rpmdbversion is not None:
     
    14421746            else:
    14431747                print _("End rpmdb      :"), old.end_rpmdbversion
    1444         print _("User           :"), name
    1445         if old.return_code is None:
     1748        if type(name) == type([]):
     1749            for name in name:
     1750                print _("User           :"), name
     1751        else:
     1752            print _("User           :"), name
     1753        if type(old.return_code) == type([]):
     1754            codes = old.return_code
     1755            if codes[0] is None:
     1756                print _("Return-Code    :"), "**", _("Aborted"), "**"
     1757                codes = codes[1:]
     1758            if codes:
     1759                print _("Return-Code    :"), _("Failures:"), ", ".join(codes)
     1760        elif old.return_code is None:
    14461761            print _("Return-Code    :"), "**", _("Aborted"), "**"
    14471762        elif old.return_code:
     
    14491764        else:
    14501765            print _("Return-Code    :"), _("Success")
    1451         print _("Transaction performed with:")
     1766           
     1767        if old.cmdline is not None:
     1768            if type(old.cmdline) == type([]):
     1769                for cmdline in old.cmdline:
     1770                    print _("Command Line   :"), cmdline
     1771            else:
     1772                print _("Command Line   :"), old.cmdline
     1773
     1774        if type(old.tid) != type([]):
     1775            addon_info = self.history.return_addon_data(old.tid)
     1776
     1777            # for the ones we create by default - don't display them as there
     1778            default_addons = set(['config-main', 'config-repos', 'saved_tx'])
     1779            non_default = set(addon_info).difference(default_addons)
     1780            if len(non_default) > 0:
     1781                    print _("Additional non-default information stored: %d"
     1782                                % len(non_default))
     1783
     1784        if old.trans_with:
     1785            # This is _possible_, but not common
     1786            print _("Transaction performed with:")
     1787            pkg_max_len = max((len(str(hpkg)) for hpkg in old.trans_with))
    14521788        for hpkg in old.trans_with:
    1453             prefix = " " * 4
    1454             state  = _('Installed')
    1455             ipkgs = self.rpmdb.searchNames([hpkg.name])
    1456             ipkgs.sort()
    1457             if not ipkgs:
    1458                 state  = _('Erased')
    1459             elif hpkg.pkgtup in (ipkg.pkgtup for ipkg in ipkgs):
    1460                 pass
    1461             elif ipkgs[-1] > hpkg:
    1462                 state  = _('Updated')
    1463             elif ipkgs[0] < hpkg:
    1464                 state  = _('Downgraded')
    1465             else: # multiple versions installed, both older and newer
    1466                 state  = _('Weird')
    1467             print "%s%s %s" % (prefix, utf8_width_fill(state, 12), hpkg)
     1789            _simple_pkg(hpkg, 4, was_installed=True, pkg_max_len=pkg_max_len)
    14681790        print _("Packages Altered:")
    14691791        self.historyInfoCmdPkgsAltered(old, pats)
     1792
     1793        if old.trans_skip:
     1794            print _("Packages Skipped:")
     1795            pkg_max_len = max((len(str(hpkg)) for hpkg in old.trans_skip))
     1796        for hpkg in old.trans_skip:
     1797            _simple_pkg(hpkg, 4, pkg_max_len=pkg_max_len)
     1798
     1799        if old.rpmdb_problems:
     1800            print _("Rpmdb Problems:")
     1801        for prob in old.rpmdb_problems:
     1802            key = "%s%s: " % (" " * 4, prob.problem)
     1803            print self.fmtKeyValFill(key, prob.text)
     1804            if prob.packages:
     1805                pkg_max_len = max((len(str(hpkg)) for hpkg in prob.packages))
     1806            for hpkg in prob.packages:
     1807                _simple_pkg(hpkg, 8, was_installed=True, highlight=hpkg.main,
     1808                            pkg_max_len=pkg_max_len)
     1809
    14701810        if old.output:
    14711811            print _("Scriptlet output:")
     
    14811821                print "%4d" % num, line
    14821822
     1823    _history_state2uistate = {'True-Install' : _('Install'),
     1824                              'Install'      : _('Install'),
     1825                              'Dep-Install'  : _('Dep-Install'),
     1826                              'Obsoleted'    : _('Obsoleted'),
     1827                              'Obsoleting'   : _('Obsoleting'),
     1828                              'Erase'        : _('Erase'),
     1829                              'Reinstall'    : _('Reinstall'),
     1830                              'Downgrade'    : _('Downgrade'),
     1831                              'Downgraded'   : _('Downgraded'),
     1832                              'Update'       : _('Update'),
     1833                              'Updated'      : _('Updated'),
     1834                              }
    14831835    def historyInfoCmdPkgsAltered(self, old, pats=[]):
    14841836        last = None
     1837        #  Note that these don't use _simple_pkg() because we are showing what
     1838        # happened to them in the transaction ... not the difference between the
     1839        # version in the transaction and now.
     1840        all_uistates = self._history_state2uistate
     1841        maxlen = 0
     1842        pkg_max_len = 0
     1843        for hpkg in old.trans_data:
     1844            uistate = all_uistates.get(hpkg.state, hpkg.state)
     1845            if maxlen < len(uistate):
     1846                maxlen = len(uistate)
     1847            if pkg_max_len < len(str(hpkg)):
     1848                pkg_max_len = len(str(hpkg))
     1849
    14851850        for hpkg in old.trans_data:
    14861851            prefix = " " * 4
     
    14991864            cn = hpkg.ui_nevra
    15001865
    1501             uistate = {'True-Install' : _('Install'),
    1502                        'Install'      : _('Install'),
    1503                        'Dep-Install'  : _('Dep-Install'),
    1504                        'Obsoleted'    : _('Obsoleted'),
    1505                        'Obsoleting'   : _('Obsoleting'),
    1506                        'Erase'        : _('Erase'),
    1507                        'Reinstall'    : _('Reinstall'),
    1508                        'Downgrade'    : _('Downgrade'),
    1509                        'Downgraded'   : _('Downgraded'),
    1510                        'Update'       : _('Update'),
    1511                        'Updated'      : _('Updated'),
    1512                        }.get(hpkg.state, hpkg.state)
    1513             uistate = utf8_width_fill(uistate, 12, 12)
     1866            uistate = all_uistates.get(hpkg.state, hpkg.state)
     1867            uistate = utf8_width_fill(uistate, maxlen)
    15141868            # Should probably use columns here...
    15151869            if False: pass
     
    15191873                ln = len(hpkg.name) + 1
    15201874                cn = (" " * ln) + cn[ln:]
    1521                 print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn)
    15221875            elif (last is not None and
    15231876                  last.state == 'Downgrade' and last.name == hpkg.name and
     
    15251878                ln = len(hpkg.name) + 1
    15261879                cn = (" " * ln) + cn[ln:]
    1527                 print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn)
    15281880            else:
    15291881                last = None
    15301882                if hpkg.state in ('Updated', 'Downgrade'):
    15311883                    last = hpkg
    1532                 print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn)
     1884            print "%s%s%s%s %-*s %s" % (prefix, hibeg, uistate, hiend,
     1885                                        pkg_max_len, cn,
     1886                                        self._hpkg2from_repo(hpkg))
    15331887
    15341888    def historySummaryCmd(self, extcmds):
     
    15881942                uperiod = _period2user[period]
    15891943                # Should probably use columns here, esp. for uiacts?
    1590                 print fmt % (utf8_width_fill(name, 22, 22),
     1944                print fmt % (utf8_width_fill(name, 26, 26),
    15911945                             utf8_width_fill(uperiod, 19, 19),
    15921946                             utf8_width_fill(uiacts, 16, 16), count)
     1947
     1948    def historyAddonInfoCmd(self, extcmds):
     1949        tid = None
     1950        if len(extcmds) > 1:
     1951            tid = extcmds[1]
     1952            if tid == 'last':
     1953                tid = None
     1954        if tid is not None:
     1955            try:
     1956                int(tid)
     1957            except ValueError:
     1958                self.logger.critical(_('Bad transaction ID given'))
     1959                return 1, ['Failed history addon-info']
     1960
     1961        if tid is not None:
     1962            old = self.history.old(tids=[tid])
     1963        else:
     1964            old = [self.history.last(complete_transactions_only=False)]
     1965            if old[0] is None:
     1966                self.logger.critical(_('No transaction ID, or package, given'))
     1967                return 1, ['Failed history addon-info']
     1968
     1969        if not old:
     1970            self.logger.critical(_('No Transaction %s found') % tid)
     1971            return 1, ['Failed history addon-info']
     1972           
     1973        hist_data = old[0]
     1974        addon_info = self.history.return_addon_data(hist_data.tid)
     1975        if len(extcmds) <= 2:
     1976            print _("Transaction ID:"), hist_data.tid
     1977            print _('Available additional history information:')
     1978            for itemname in self.history.return_addon_data(hist_data.tid):
     1979                print '  %s' % itemname
     1980            print ''
     1981           
     1982            return 0, ['history addon-info']
     1983       
     1984        for item in extcmds[2:]:
     1985            if item in addon_info:
     1986                print '%s:' % item
     1987                print self.history.return_addon_data(hist_data.tid, item)
     1988            else:
     1989                print _('%s: No additional data found by this name') % item
     1990
     1991            print ''
     1992
     1993    def historyPackageListCmd(self, extcmds):
     1994        """ Shows the user a list of data about the history, from the point
     1995            of a package(s) instead of via. transactions. """
     1996        tids = self.history.search(extcmds)
     1997        limit = None
     1998        if extcmds and not tids:
     1999            self.logger.critical(_('Bad transaction IDs, or package(s), given'))
     2000            return 1, ['Failed history packages-list']
     2001        if not tids:
     2002            limit = 20
     2003
     2004        all_uistates = self._history_state2uistate
     2005
     2006        fmt = "%s | %s | %s"
     2007        # REALLY Needs to use columns!
     2008        print fmt % (utf8_width_fill(_("ID"), 6, 6),
     2009                     utf8_width_fill(_("Action(s)"), 14, 14),
     2010                     utf8_width_fill(_("Package"), 53, 53))
     2011        print "-" * 79
     2012        fmt = "%6u | %s | %-50s"
     2013        num = 0
     2014        for old in self.history.old(tids, limit=limit):
     2015            if limit is not None and num and (num +len(old.trans_data)) > limit:
     2016                break
     2017            last = None
     2018
     2019            # Copy and paste from list ... uh.
     2020            rmark = lmark = ' '
     2021            if old.return_code is None:
     2022                rmark = lmark = '*'
     2023            elif old.return_code:
     2024                rmark = lmark = '#'
     2025                # We don't check .errors, because return_code will be non-0
     2026            elif old.output:
     2027                rmark = lmark = 'E'
     2028            elif old.rpmdb_problems:
     2029                rmark = lmark = 'P'
     2030            elif old.trans_skip:
     2031                rmark = lmark = 's'
     2032            if old.altered_lt_rpmdb:
     2033                rmark = '<'
     2034            if old.altered_gt_rpmdb:
     2035                lmark = '>'
     2036
     2037            for hpkg in old.trans_data: # Find a pkg to go with each cmd...
     2038                if limit is None:
     2039                    x,m,u = yum.packages.parsePackages([hpkg], extcmds)
     2040                    if not x and not m:
     2041                        continue
     2042
     2043                uistate = all_uistates.get(hpkg.state, hpkg.state)
     2044                uistate = utf8_width_fill(uistate, 14)
     2045
     2046                #  To chop the name off we need nevra strings, str(pkg) gives
     2047                # envra so we have to do it by hand ... *sigh*.
     2048                cn = hpkg.ui_nevra
     2049
     2050                # Should probably use columns here...
     2051                if False: pass
     2052                elif (last is not None and
     2053                      last.state == 'Updated' and last.name == hpkg.name and
     2054                      hpkg.state == 'Update'):
     2055                    ln = len(hpkg.name) + 1
     2056                    cn = (" " * ln) + cn[ln:]
     2057                elif (last is not None and
     2058                      last.state == 'Downgrade' and last.name == hpkg.name and
     2059                      hpkg.state == 'Downgraded'):
     2060                    ln = len(hpkg.name) + 1
     2061                    cn = (" " * ln) + cn[ln:]
     2062                else:
     2063                    last = None
     2064                    if hpkg.state in ('Updated', 'Downgrade'):
     2065                        last = hpkg
     2066
     2067                num += 1
     2068                print fmt % (old.tid, uistate, cn), "%s%s" % (lmark,rmark)
     2069
     2070        # And, again, copy and paste...
     2071        lastdbv = self.history.last()
     2072        if lastdbv is None:
     2073            self._rpmdb_warn_checks(warn=False)
     2074        else:
     2075            #  If this is the last transaction, is good and it doesn't
     2076            # match the current rpmdb ... then mark it as bad.
     2077            rpmdbv  = self.rpmdb.simpleVersion(main_only=True)[0]
     2078            if lastdbv.end_rpmdbversion != rpmdbv:
     2079                self._rpmdb_warn_checks()
    15932080
    15942081
     
    16042091    def pkgAdded(self, pkgtup, mode):
    16052092        modedict = { 'i': _('installed'),
    1606                      'u': _('updated'),
    1607                      'o': _('obsoleted'),
    1608                      'e': _('erased')}
     2093                     'u': _('an update'),
     2094                     'e': _('erased'),
     2095                     'r': _('reinstalled'),
     2096                     'd': _('a downgrade'),
     2097                     'o': _('obsoleting'),
     2098                     'ud': _('updated'),
     2099                     'od': _('obsoleted'),}
    16092100        (n, a, e, v, r) = pkgtup
    16102101        modeterm = modedict[mode]
    16112102        self.verbose_logger.log(logginglevels.INFO_2,
    1612             _('---> Package %s.%s %s:%s-%s set to be %s'), n, a, e, v, r,
     2103            _('---> Package %s.%s %s:%s-%s will be %s'), n, a, e, v, r,
    16132104            modeterm)
    16142105       
     
    16402131            po)
    16412132   
     2133    def groupRemoveReq(self, po, hits):
     2134        self.verbose_logger.log(logginglevels.INFO_2,
     2135            _('---> Keeping package: %s'), po)
     2136
    16422137    def unresolved(self, msg):
    16432138        self.verbose_logger.log(logginglevels.INFO_2, _('--> Unresolved Dependency: %s'),
     
    16612156            return msg
    16622157       
    1663         ipkgs = set()
    1664         for pkg in sorted(yb.rpmdb.getProvides(needname)):
    1665             ipkgs.add(pkg.pkgtup)
     2158        def _msg_pkg(action, pkg, needname):
     2159            " Add a package to the message, including any provides matches. "
     2160            msg = _('\n    %s: %s (%s)') % (action, pkg, pkg.ui_from_repo)
     2161            needtup = (needname, None, (None, None, None))
     2162            done = False
     2163            for pkgtup in pkg.matchingPrcos('provides', needtup):
     2164                done = True
     2165                msg += _('\n        %s') % yum.misc.prco_tuple_to_string(pkgtup)
     2166            if not done:
     2167                msg += _('\n        Not found')
     2168            return msg
     2169
     2170        def _run_inst_pkg(pkg, msg):
     2171            nevr = (pkg.name, pkg.epoch, pkg.version, pkg.release)
     2172            if nevr in seen_pkgs or (pkg.verEQ(last) and pkg.arch == last.arch):
     2173                return msg
     2174
     2175            seen_pkgs.add(nevr)
    16662176            action = _('Installed')
    1667             if yb.tsInfo.getMembersWithState(pkg.pkgtup, TS_REMOVE_STATES):
     2177            rmed = yb.tsInfo.getMembersWithState(pkg.pkgtup, TS_REMOVE_STATES)
     2178            if rmed:
    16682179                action = _('Removing')
    1669             msg += _('\n    %s: %s (%s)') % (action, pkg, pkg.ui_from_repo)
    1670         last = None
    1671         for pkg in sorted(yb.pkgSack.getProvides(needname)):
     2180            msg += _msg_pkg(action, pkg, needname)
     2181            # These should be the only three things we care about:
     2182            relmap = {'updatedby' : _('Updated By'),
     2183                      'downgradedby' : _('Downgraded By'),
     2184                      'obsoletedby' :  _('Obsoleted By'),
     2185                      }
     2186            for txmbr in rmed:
     2187                for (rpkg, rtype) in txmbr.relatedto:
     2188                    if rtype not in relmap:
     2189                        continue
     2190                    nevr = (rpkg.name, rpkg.epoch, rpkg.version, rpkg.release)
     2191                    seen_pkgs.add(nevr)
     2192                    msg += _msg_pkg(relmap[rtype], rpkg, needname)
     2193            return msg
     2194
     2195        def _run_avail_pkg(pkg, msg):
    16722196            #  We don't want to see installed packages, or N packages of the
    16732197            # same version, from different repos.
    1674             if pkg.pkgtup in ipkgs or pkg.verEQ(last):
    1675                 continue
    1676             last = pkg
     2198            nevr = (pkg.name, pkg.epoch, pkg.version, pkg.release)
     2199            if nevr in seen_pkgs or (pkg.verEQ(last) and pkg.arch == last.arch):
     2200                return False, last, msg
     2201            seen_pkgs.add(nevr)
    16772202            action = _('Available')
    16782203            if yb.tsInfo.getMembersWithState(pkg.pkgtup, TS_INSTALL_STATES):
    16792204                action = _('Installing')
    1680             msg += _('\n    %s: %s (%s)') % (action, pkg, pkg.repoid)
     2205            msg += _msg_pkg(action, pkg, needname)
     2206            return True, pkg, msg
     2207
     2208        last = None
     2209        seen_pkgs = set()
     2210        for pkg in sorted(yb.rpmdb.getProvides(needname)):
     2211            msg = _run_inst_pkg(pkg, msg)
     2212
     2213        available_names = set()
     2214        for pkg in sorted(yb.pkgSack.getProvides(needname)):
     2215            tst, last, msg = _run_avail_pkg(pkg, msg)
     2216            if tst:
     2217                available_names.add(pkg.name)
     2218
     2219        last = None
     2220        for pkg in sorted(yb.rpmdb.searchNames(available_names)):
     2221            msg = _run_inst_pkg(pkg, msg)
     2222        last = None
     2223        for pkg in sorted(yb.pkgSack.searchNames(available_names)):
     2224            tst, last, msg = _run_avail_pkg(pkg, msg)
    16812225        return msg
    16822226   
     
    17332277        #  Note 'd' is a placeholder for downgrade, and
    17342278        # 'r' is a placeholder for reinstall. Neither exist atm.
    1735         ts_states = ('d', 'e', 'i', 'r', 'u')
     2279        ts_states = ('d', 'e', 'i', 'r', 'u', 'od', 'ud')
    17362280
    17372281    matches = []
     
    17932337    #  Installing things have pkg objects passed to the events, so only need to
    17942338    # lookup for erased/obsoleted.
    1795     def pkgname_ui(self, pkgname, ts_states=('e', None)):
     2339    def pkgname_ui(self, pkgname, ts_states=('e', 'od', 'ud', None)):
    17962340        """ Get more information on a simple pkgname, if we can. """
    17972341        return _pkgname_ui(self.ayum, pkgname, ts_states)
     
    18002344        # this is where a progress bar would be called
    18012345        process = self.action[action]
     2346
     2347        if not hasattr(self, '_max_action_wid'):
     2348            wid1 = 0
     2349            for val in self.action.values():
     2350                wid_val = utf8_width(val)
     2351                if wid1 < wid_val:
     2352                    wid1 = wid_val
     2353            self._max_action_wid = wid1
     2354        wid1 = self._max_action_wid
    18022355       
    18032356        if type(package) not in types.StringTypes:
     
    18142367        if self.output and (sys.stdout.isatty() or te_current == te_total):
    18152368            (fmt, wid1, wid2) = self._makefmt(percent, ts_current, ts_total,
    1816                                               pkgname=pkgname)
     2369                                              pkgname=pkgname, wid1=wid1)
    18172370            msg = fmt % (utf8_width_fill(process, wid1, wid1),
    18182371                         utf8_width_fill(pkgname, wid2, wid2))
     
    18302383
    18312384    def _makefmt(self, percent, ts_current, ts_total, progress = True,
    1832                  pkgname=None):
     2385                 pkgname=None, wid1=15):
    18332386        l = len(str(ts_total))
    18342387        size = "%s.%s" % (l, l)
     
    18442397
    18452398        overhead  = (2 * l) + 2 # Length of done, above
    1846         overhead += 19          # Length of begining
     2399        overhead +=  2+ wid1 +2 # Length of begining ("  " action " :")
    18472400        overhead +=  1          # Space between pn and done
    18482401        overhead +=  2          # Ends for progress
     
    18752428            fmt = "  %s: %s " + bar + " " + done
    18762429            wid2 = pnl
    1877         return fmt, 15, wid2
     2430        return fmt, wid1, wid2
    18782431
    18792432
Note: See TracChangeset for help on using the changeset viewer.