Eg. yum histry merge 1..2 => Will show the first two transactions as though they were a single transaction. All the complicated bits are in YumMergedTransaction.merge(), this is just a UI patch. Adds this to the man page.
Also changes transaction time to have minutes/hours/days. Also fixes info's package name chopping to dtrt. for Obsoleting packages. Also makes "history info" report an error if there are no transactions. --- docs/yum.8 | 9 ++++- output.py | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 125 insertions(+), 17 deletions(-) diff --git a/docs/yum.8 b/docs/yum.8 index 7ac9772..4158453 100644 --- a/docs/yum.8 +++ b/docs/yum.8 @@ -247,7 +247,14 @@ and new to start a new history file. The info/list/summary commands take either a transactions id or a package (with wildcards, as in \fBSpecifying package names\fP), all three can also be passed no arguments. list can be passed the keyword "all" to list all the transactions. -undo/redo just take a transaction id. +undo/redo just take a transaction id\&. + +The info command can also take ranges of transaction ids, of the form +start..end, which will then display a merged history as if all the +transactions in the range had happened at once\&. +.br +Eg. "history info 1..4" will merge the first four transactions and display them +as a single transaction. .IP .IP "\fBhelp\fP" Produces help, either for all commands or if given a command name then the help diff --git a/output.py b/output.py index 4a94bc4..25076f3 100755 --- a/output.py +++ b/output.py @@ -43,6 +43,8 @@ from yum.rpmtrans import RPMBaseCallback from yum.packageSack import packagesNewestByNameArch import yum.packages +import yum.history + from yum.i18n import utf8_width, utf8_width_fill, utf8_text_fill def _term_width(): @@ -1198,6 +1200,9 @@ to exit. return count, "".join(list(actions)) def _pwd_ui_username(self, uid, limit=None): + if type(uid) == type([]): + return [self._pwd_ui_username(u, limit) for u in uid] + # loginuid is set to -1 on init. if uid is None or uid == 0xFFFFFFFF: loginid = _("<unset>") @@ -1317,21 +1322,58 @@ to exit. return old[0] def historyInfoCmd(self, extcmds): + def str2int(x): + try: + return int(x) + except ValueError: + return None + tids = set() + mtids = set() pats = [] + old = self.history.last() + if old is None: + self.logger.critical(_('No transactions')) + return 1, ['Failed history info'] + for tid in extcmds[1:]: - try: - int(tid) - tids.add(tid) - except ValueError: - pats.append(tid) + if '..' in tid: + btid, etid = tid.split('..', 2) + btid = str2int(btid) + if btid > old.tid: + btid = None + elif btid <= 0: + btid = None + etid = str2int(etid) + if etid > old.tid: + etid = None + if btid is not None and etid is not None: + # Have a range ... do a "merged" transaction. + if btid > etid: + btid, etid = etid, btid + mtids.add((btid, etid)) + continue + elif str2int(tid) is not None: + tids.add(str2int(tid)) + continue + pats.append(tid) if pats: tids.update(self.history.search(pats)) + utids = tids.copy() + if mtids: + mtids = sorted(mtids) + last_end = -1 # This just makes displaying it easier... + for mtid in mtids: + if mtid[0] < last_end: + self.logger.warn(_('Skipping merged transaction %d to %d, as it overlaps', mtid[0], mtid[1])) + continue # Don't do overlapping + last_end = mtid[1] + for num in range(mtid[0], mtid[1] + 1): + tids.add(num) if not tids and len(extcmds) < 2: - old = self.history.last() - if old is not None: - tids.add(old.tid) + tids.add(old.tid) + utids.add(old.tid) if not tids: self.logger.critical(_('No transaction ID, or package, given')) @@ -1343,6 +1385,10 @@ to exit. lastdbv = lastdbv.end_rpmdbversion done = False + bmtid, emtid = -1, -1 + mobj = None + if mtids: + bmtid, emtid = mtids.pop(0) for tid in self.history.old(tids): if lastdbv is not None and tid.tid == lasttid: # If this is the last transaction, is good and it doesn't @@ -1352,15 +1398,43 @@ to exit. tid.altered_gt_rpmdb = True lastdbv = None + if tid.tid >= bmtid and tid.tid <= emtid: + if mobj is None: + mobj = yum.history.YumMergedHistoryTransaction(tid) + else: + mobj.merge(tid) + elif mobj is not None: + if done: + print "-" * 79 + done = True + + self._historyInfoCmd(mobj) + mobj = None + if mtids: + bmtid, emtid = mtids.pop(0) + if tid.tid >= bmtid and tid.tid <= emtid: + mobj = yum.history.YumMergedHistoryTransaction(tid) + + if tid.tid in utids: + if done: + print "-" * 79 + done = True + + self._historyInfoCmd(tid, pats) + + if mobj is not None: if done: print "-" * 79 - done = True - self._historyInfoCmd(tid, pats) + + self._historyInfoCmd(mobj) def _historyInfoCmd(self, old, pats=[]): name = self._pwd_ui_username(old.loginuid) - print _("Transaction ID :"), old.tid + if type(old.tid) == type([]): + print _("Transaction ID :"), "%u..%u" % (old.tid[0], old.tid[-1]) + else: + print _("Transaction ID :"), old.tid begtm = time.ctime(old.beg_timestamp) print _("Begin time :"), begtm if old.beg_rpmdbversion is not None: @@ -1381,15 +1455,34 @@ to exit. break sofar += len(begtms[i]) + 1 endtm = (' ' * sofar) + endtm[sofar:] - diff = _("(%s seconds)") % (old.end_timestamp - old.beg_timestamp) + diff = old.end_timestamp - old.beg_timestamp + if diff < 5 * 60: + diff = _("(%u seconds)") % diff + elif diff < 5 * 60 * 60: + diff = _("(%u minutes)") % (diff / 60) + elif diff < 5 * 60 * 60 * 24: + diff = _("(%u hours)") % (diff / (60 * 60)) + else: + diff = _("(%u days)") % (diff / (60 * 60 * 24)) print _("End time :"), endtm, diff if old.end_rpmdbversion is not None: if old.altered_gt_rpmdb: print _("End rpmdb :"), old.end_rpmdbversion, "**" else: print _("End rpmdb :"), old.end_rpmdbversion - print _("User :"), name - if old.return_code is None: + if type(name) == type([]): + for name in name: + print _("User :"), name + else: + print _("User :"), name + if type(old.return_code) == type([]): + codes = old.return_code + if codes[0] is None: + print _("Return-Code :"), "**", _("Aborted"), "**" + codes = codes[1:] + if codes: + print _("Return-Code :"), _("Failures:"), ", ".join(codes) + elif old.return_code is None: print _("Return-Code :"), "**", _("Aborted"), "**" elif old.return_code: print _("Return-Code :"), _("Failure:"), old.return_code @@ -1428,6 +1521,7 @@ to exit. print "%4d" % num, line def historyInfoCmdPkgsAltered(self, old, pats=[]): + last = None for hpkg in old.trans_data: prefix = " " * 4 if not hpkg.done: @@ -1459,15 +1553,22 @@ to exit. uistate = utf8_width_fill(uistate, 12, 12) # Should probably use columns here... if False: pass - elif hpkg.state == 'Update': + elif (last is not None and + last.state == 'Updated' and last.name == hpkg.name and + hpkg.state == 'Update'): ln = len(hpkg.name) + 1 cn = (" " * ln) + cn[ln:] print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn) - elif hpkg.state == 'Downgraded': + elif (last is not None and + last.state == 'Downgrade' and last.name == hpkg.name and + hpkg.state == 'Downgraded'): ln = len(hpkg.name) + 1 cn = (" " * ln) + cn[ln:] print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn) else: + last = None + if hpkg.state in ('Updated', 'Downgrade'): + last = hpkg print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn) def historySummaryCmd(self, extcmds): -- 1.6.2.5 _______________________________________________ Yum-devel mailing list Yum-devel@lists.baseurl.org http://lists.baseurl.org/mailman/listinfo/yum-devel