diff --git a/cli.py b/cli.py
index 615a1f6..332be99 100644
--- a/cli.py
+++ b/cli.py
@@ -100,6 +100,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
self.registerCommand(yumcommands.ReInstallCommand())
self.registerCommand(yumcommands.DowngradeCommand())
self.registerCommand(yumcommands.VersionCommand())
+ self.registerCommand(yumcommands.HistoryCommand())
def registerCommand(self, command):
for name in command.getNames():
@@ -206,8 +207,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
if opts.version:
self.conf.cache = 1
- yum_progs = ['yum', 'yum-metadata-parser', 'rpm',
- 'yum-rhn-plugin']
+ yum_progs = self.run_with_package_names
done = False
def sm_ui_time(x):
return time.strftime("%Y-%m-%d %H:%M", time.gmtime(x))
diff --git a/docs/yum.8 b/docs/yum.8
index 3520912..d0dfb79 100644
--- a/docs/yum.8
+++ b/docs/yum.8
@@ -67,6 +67,10 @@ gnome\-packagekit application\&.
.br
.I \fR * repolist [all|enabled|disabled]
.br
+.I \fR * version [all]
+.br
+.I \fR * history [info|list|summary|redo|undo|new]
+.br
.I \fR * help [command]
.br
.PP
@@ -225,6 +229,25 @@ Produces a list of configured repositories. The default is to list all
enabled repositories. If you pass \-v, for verbose mode, more information is
listed.
.IP
+.IP "\fBversion\fP"
+Produces a "version" of the rpmdb, and of the enabled repositories if "all" is
+given as the first argument. If you pass \-v, for verbose mode, more
+information is listed. The version is calculated by taking a sha1 hash of the
+packages (in sorted order), and the checksum_type/checksum_data entries from
+the yumdb. Note that this rpmdb version is now also used significantly within
+yum (esp. in yum history).
+.IP
+.IP "\fBhistory\fP"
+The history command allows the user to view what has happened in past
+transactions (assuming the history_record config. option is set). You can use
+info/list/summary to view what happend, undo/redo to act on that information
+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.
+.IP
.IP "\fBhelp\fP"
Produces help, either for all commands or if given a command name then the help
for that particular command\&.
@@ -266,7 +289,8 @@ Sets the maximum amount of time yum will wait before performing a command \- it
Tells yum to run entirely from cache - does not download or update any
headers unless it has to to perform the requested action.
.IP "\fB\-\-version\fP"
-Reports the \fByum\fP version number and exits.
+Reports the \fByum\fP version number and installed package versions for
+everything in history_record_packages (can be added to by plugins).
.IP "\fB\-\-showduplicates\fP"
Doesn't limit packages to their latest versions in the info, list and search
commands (will also affect plugins which use the doPackageLists() API).
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
index 69b601d..6295b1e 100644
--- a/docs/yum.conf.5
+++ b/docs/yum.conf.5
@@ -274,6 +274,21 @@ Path to the ssl client key yum should use to connect to repos/remote sites
Defaults to none.
.IP
+\fBhistory_record \fR
+Boolean - should yum record history entries for transactions. This takes some
+disk space, and some extra time in the transactions. But it allos how to know a
+lot of information about what has happened before, and display it to the user
+with the history info/list/summary commands. yum also provides the
+history undo/redo commands. Defaults to True.
+
+.IP
+\fBhistory_record_packages \fR
+This is a list of package names that should be recorded as having helped the
+transaction. yum plugins have an API to add themself to this, so it should not
+normally be necessary to add packages here. Not that this is also used for the
+packages to look for in --version. Defaults to rpm, yum, yum-metadata-parser.
+
+.IP
\fBcommands\fR
List of functional commands to run if no functional commands are specified
on the command line (eg. "update foo bar baz quux"). None of the short options
diff --git a/output.py b/output.py
index 2299a9c..d0b9f7f 100755
--- a/output.py
+++ b/output.py
@@ -22,6 +22,7 @@ import time
import logging
import types
import gettext
+import pwd
import rpm
import re # For YumTerm
@@ -40,6 +41,7 @@ from yum.constants import *
from yum import logginglevels, _
from yum.rpmtrans import RPMBaseCallback
from yum.packageSack import packagesNewestByNameArch
+import yum.packages
from yum.i18n import utf8_width, utf8_width_fill, utf8_text_fill
@@ -1172,6 +1174,328 @@ to exit.
ui_bs, ui_size, ui_time, ui_end)
self.verbose_logger.log(logginglevels.INFO_2, msg)
+ def _history_uiactions(self, hpkgs):
+ actions = set()
+ count = 0
+ for hpkg in hpkgs:
+ st = hpkg.state
+ if st == 'True-Install':
+ st = 'Install'
+ if st == 'Obsoleted': # This is just a UI tweak, as we can't have
+ # just one but we need to count them all.
+ st = 'Obsoleting'
+ if st in ('Install', 'Update', 'Erase', 'Reinstall', 'Downgrade',
+ 'Obsoleting'):
+ actions.add(st)
+ count += 1
+ assert len(actions) <= 6
+ if len(actions) > 1:
+ return count, ", ".join([x[0] for x in sorted(actions)])
+
+ # So empty transactions work, although that "shouldn't" really happen
+ return count, "".join(list(actions))
+
+ def _pwd_ui_username(self, uid, limit=None):
+ # loginuid is set to -1 on init.
+ if uid is None or uid == 0xFFFFFFFF:
+ loginid = _("<unset>")
+ name = _("System") + " " + loginid
+ if limit is not None and len(name) > limit:
+ name = loginid
+ return name
+
+ try:
+ user = pwd.getpwuid(uid)
+ fullname = user.pw_gecos.split(';', 2)[0]
+ name = "%s <%s>" % (fullname, user.pw_name)
+ if limit is not None and len(name) > limit:
+ name = "%s ... <%s>" % (fullname.split()[0], user.pw_name)
+ if len(name) > limit:
+ name = "<%s>" % user.pw_name
+ return name
+ except KeyError:
+ return str(uid)
+
+ def _history_list_transactions(self, extcmds):
+ tids = set()
+ pats = []
+ usertids = extcmds[1:]
+ printall = False
+ if usertids:
+ printall = True
+ if usertids[0] == 'all':
+ usertids.pop(0)
+ for tid in usertids:
+ try:
+ int(tid)
+ tids.add(tid)
+ except ValueError:
+ pats.append(tid)
+ if pats:
+ tids.update(self.history.search(pats))
+
+ if not tids and usertids:
+ self.logger.critical(_('Bad transaction IDs, or package(s), given'))
+ return None, None
+ return tids, printall
+
+ def historyListCmd(self, extcmds):
+ """ Shows the user a list of data about the history. """
+
+ tids, printall = self._history_list_transactions(extcmds)
+ if tids is None:
+ return 1, ['Failed history info']
+
+ fmt = "%-6s | %-22s | %-16s | %-14s | %-7s"
+ print fmt % ("ID", "Login user", "Date and time", "Action(s)","Altered")
+ print "-" * 79
+ fmt = "%6u | %-22.22s | %-16s | %-14s | %4u"
+ done = 0
+ limit = 20
+ if printall:
+ limit = None
+ for old in self.history.old(tids, limit=limit):
+ if not printall and done >= limit:
+ break
+
+ done += 1
+ name = self._pwd_ui_username(old.loginuid, 22)
+ tm = time.strftime("%Y-%m-%d %H:%M",
+ time.localtime(old.beg_timestamp))
+ num, uiacts = self._history_uiactions(old.trans_data)
+ if old.altered_lt_rpmdb and old.altered_gt_rpmdb:
+ print fmt % (old.tid, name, tm, uiacts, num), "><"
+ elif old.return_code is None:
+ print fmt % (old.tid, name, tm, uiacts, num), "**"
+ elif old.altered_lt_rpmdb:
+ print fmt % (old.tid, name, tm, uiacts, num), " <"
+ elif old.altered_gt_rpmdb:
+ print fmt % (old.tid, name, tm, uiacts, num), "> "
+ else:
+ print fmt % (old.tid, name, tm, uiacts, num)
+ lastdbv = self.history.last()
+ if lastdbv is not None:
+ # If this is the last transaction, is good and it doesn't
+ # match the current rpmdb ... then mark it as bad.
+ rpmdbv = self.rpmdb.simpleVersion(main_only=True)[0]
+ if lastdbv.end_rpmdbversion != rpmdbv:
+ errstring = _('Warning: RPMDB has been altered since the last yum transaction.')
+ self.logger.warning(errstring)
+
+ def _history_get_transactions(self, extcmds):
+ if len(extcmds) < 2:
+ self.logger.critical(_('No transaction ID given'))
+ return None
+
+ tids = []
+ try:
+ int(extcmds[1])
+ tids.append(extcmds[1])
+ except ValueError:
+ self.logger.critical(_('Bad transaction ID given'))
+ return None
+
+ old = self.history.old(tids)
+ if not old:
+ self.logger.critical(_('Not found given transaction ID'))
+ return None
+ return old
+ def _history_get_transaction(self, extcmds):
+ old = self._history_get_transactions(extcmds)
+ if old is None:
+ return None
+ if len(old) > 1:
+ self.logger.critical(_('Found more than one transaction ID!'))
+ return old[0]
+
+ def historyInfoCmd(self, extcmds):
+ tids = set()
+ pats = []
+ for tid in extcmds[1:]:
+ try:
+ int(tid)
+ tids.add(tid)
+ except ValueError:
+ pats.append(tid)
+ if pats:
+ tids.update(self.history.search(pats))
+
+ if not tids and len(extcmds) < 2:
+ old = self.history.last()
+ if old is not None:
+ tids.add(old.tid)
+
+ if not tids:
+ self.logger.critical(_('No transaction ID, or package, given'))
+ return 1, ['Failed history info']
+
+ lastdbv = self.history.last()
+ if lastdbv is not None:
+ lasttid = lastdbv.tid
+ lastdbv = lastdbv.end_rpmdbversion
+
+ done = False
+ 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
+ # match the current rpmdb ... then mark it as bad.
+ rpmdbv = self.rpmdb.simpleVersion(main_only=True)[0]
+ if lastdbv != rpmdbv:
+ tid.altered_gt_rpmdb = True
+ lastdbv = None
+
+ if done:
+ print "-" * 79
+ done = True
+ self._historyInfoCmd(tid, pats)
+
+ def _historyInfoCmd(self, old, pats=[]):
+ name = self._pwd_ui_username(old.loginuid)
+
+ print _("Transaction ID :"), old.tid
+ begtm = time.ctime(old.beg_timestamp)
+ print _("Begin time :"), begtm
+ if old.beg_rpmdbversion is not None:
+ if old.altered_lt_rpmdb:
+ print _("Begin rpmdb :"), old.beg_rpmdbversion, "**"
+ else:
+ print _("Begin rpmdb :"), old.beg_rpmdbversion
+ if old.end_timestamp is not None:
+ endtm = time.ctime(old.end_timestamp)
+ endtms = endtm.split()
+ if begtm.startswith(endtms[0]): # Chop uninteresting prefix
+ begtms = begtm.split()
+ sofar = 0
+ for i in range(len(endtms)):
+ if i > len(begtms):
+ break
+ if begtms[i] != endtms[i]:
+ break
+ sofar += len(begtms[i]) + 1
+ endtm = (' ' * sofar) + endtm[sofar:]
+ diff = _("(%s seconds)") % (old.end_timestamp - old.beg_timestamp)
+ 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:
+ print _("Return-Code :"), "**", _("Aborted"), "**"
+ elif old.return_code:
+ print _("Return-Code :"), _("Failure:"), old.return_code
+ else:
+ print _("Return-Code :"), _("Success")
+ print _("Transaction performed with :")
+ for hpkg in old.trans_with:
+ prefix = " " * 4
+ state = _('Installed')
+ ipkgs = self.rpmdb.searchNames([hpkg.name])
+ ipkgs.sort()
+ if not ipkgs:
+ state = _('Erased')
+ elif hpkg.pkgtup in (ipkg.pkgtup for ipkg in ipkgs):
+ pass
+ elif ipkgs[-1] > hpkg:
+ state = _('Updated')
+ elif ipkgs[0] < hpkg:
+ state = _('Downgraded')
+ else: # multiple versions installed, both older and newer
+ state = _('Weird')
+ print "%s%-12s %s" % (prefix, state, hpkg)
+ print _("Packages Altered:")
+ self.historyInfoCmdPkgsAltered(old, pats)
+
+ def historyInfoCmdPkgsAltered(self, old, pats=[]):
+ for hpkg in old.trans_data:
+ prefix = " " * 4
+ if not hpkg.done:
+ prefix = " ** "
+
+ highlight = 'normal'
+ if pats:
+ x,m,u = yum.packages.parsePackages([hpkg], pats)
+ if x or m:
+ highlight = 'bold'
+ (hibeg, hiend) = self._highlight(highlight)
+
+ # To chop the name off we need nevra strings, str(pkg) gives envra
+ # so we have to do it by hand ... *sigh*.
+ if hpkg.epoch == '0':
+ cn = str(hpkg)
+ else:
+ cn = "%s-%s:%s-%s.%s" % (hpkg.name, hpkg.epoch,
+ hpkg.version, hpkg.release, hpkg.arch)
+
+ if False: pass
+ elif hpkg.state == 'Update':
+ ln = len(hpkg.name) + 1
+ cn = (" " * ln) + cn[ln:]
+ print "%s%s%-12s%s %s" % (prefix, hibeg, hpkg.state, hiend, cn)
+ elif hpkg.state == 'Downgraded':
+ ln = len(hpkg.name) + 1
+ cn = (" " * ln) + cn[ln:]
+ print "%s%s%-12s%s %s" % (prefix, hibeg, hpkg.state, hiend, cn)
+ elif hpkg.state == 'True-Install':
+ print "%s%s%-12s%s %s" % (prefix, hibeg, "Install", hiend, cn)
+ else:
+ print "%s%s%-12s%s %s" % (prefix, hibeg, hpkg.state, hiend, cn)
+
+ def historySummaryCmd(self, extcmds):
+ tids, printall = self._history_list_transactions(extcmds)
+ if tids is None:
+ return 1, ['Failed history info']
+
+ fmt = "%-26s | %-19s | %-16s | %-8s"
+ print fmt % ("Login user", "Time", "Action(s)", "Altered")
+ print "-" * 79
+ fmt = "%-26.26s | %-19.19s | %-16s | %8u"
+ data = {'day' : {}, 'week' : {},
+ 'fortnight' : {}, 'quarter' : {}, 'half' : {},
+ 'year' : {}, 'all' : {}}
+ for old in self.history.old(tids):
+ name = self._pwd_ui_username(old.loginuid, 26)
+ period = 'all'
+ now = time.time()
+ if False: pass
+ elif old.beg_timestamp > (now - (24 * 60 * 60)):
+ period = 'day'
+ elif old.beg_timestamp > (now - (24 * 60 * 60 * 7)):
+ period = 'week'
+ elif old.beg_timestamp > (now - (24 * 60 * 60 * 14)):
+ period = 'fortnight'
+ elif old.beg_timestamp > (now - (24 * 60 * 60 * 7 * 13)):
+ period = 'quarter'
+ elif old.beg_timestamp > (now - (24 * 60 * 60 * 7 * 26)):
+ period = 'half'
+ elif old.beg_timestamp > (now - (24 * 60 * 60 * 365)):
+ period = 'year'
+ data[period].setdefault(name, []).append(old)
+ _period2user = {'day' : _("Last day"),
+ 'week' : _("Last week"),
+ 'fortnight' : _("Last 2 weeks"), # US default :p
+ 'quarter' : _("Last 3 months"),
+ 'half' : _("Last 6 months"),
+ 'year' : _("Last year"),
+ 'all' : _("Over a year ago")}
+ done = 0
+ for period in ('day', 'week', 'fortnight', 'quarter', 'half', 'year',
+ 'all'):
+ if not data[period]:
+ continue
+ for name in sorted(data[period]):
+ if not printall and done > 19:
+ break
+ done += 1
+
+ hpkgs = []
+ for old in data[period][name]:
+ hpkgs.extend(old.trans_data)
+ count, uiacts = self._history_uiactions(hpkgs)
+ uperiod = _period2user[period]
+ print fmt % (name, uperiod, uiacts, count)
+
class DepSolveProgressCallBack:
"""provides text output callback functions for Dependency Solver callback"""
diff --git a/po/ca.po b/po/ca.po
index 3bef4b5..1869dc2 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -5,6 +5,7 @@
#
# Josep Maria Brunetti Fernández <josepb@gmail.com>, 2008
# Xavier Conde Rueda <xavi.conde@gmail.com>, 2008
+# Josep Torné Llavall <josep.torne@gmail.com>, 2009
#
# This file is translated according to the glossary and style guide of
# Softcatalà. If you plan to modify this file, please read first the page
@@ -21,8 +22,8 @@ msgid ""
msgstr ""
"Project-Id-Version: yum\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-03-27 19:24+0000\n"
-"PO-Revision-Date: 2009-03-31 22:25+0100\n"
+"POT-Creation-Date: 2009-09-05 08:55+0000\n"
+"PO-Revision-Date: 2009-09-06 22:25+0100\n"
"Last-Translator: Agustí Grau <fedora@softcatala.org>\n"
"Language-Team: Catalan <fedora@softcatala.net>\n"
"MIME-Version: 1.0\n"
@@ -31,46 +32,32 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Poedit-Language: Catalan\n"
-#: ../callback.py:48
-#: ../output.py:922
-#: ../yum/rpmtrans.py:71
+#: ../callback.py:48 ../output.py:938 ../yum/rpmtrans.py:71
msgid "Updating"
msgstr "Actualitzant"
-#: ../callback.py:49
-#: ../yum/rpmtrans.py:72
+#: ../callback.py:49 ../yum/rpmtrans.py:72
msgid "Erasing"
-msgstr "S'està esborrant"
-
-#: ../callback.py:50
-#: ../callback.py:51
-#: ../callback.py:53
-#: ../output.py:921
-#: ../yum/rpmtrans.py:73
-#: ../yum/rpmtrans.py:74
-#: ../yum/rpmtrans.py:76
+msgstr "Suprimint"
+
+#: ../callback.py:50 ../callback.py:51 ../callback.py:53 ../output.py:937
+#: ../yum/rpmtrans.py:73 ../yum/rpmtrans.py:74 ../yum/rpmtrans.py:76
msgid "Installing"
msgstr "Instal·lant"
-#: ../callback.py:52
-#: ../callback.py:58
-#: ../yum/rpmtrans.py:75
+#: ../callback.py:52 ../callback.py:58 ../yum/rpmtrans.py:75
msgid "Obsoleted"
msgstr "Obsolet"
-#: ../callback.py:54
-#: ../output.py:1029
+#: ../callback.py:54 ../output.py:1061
msgid "Updated"
msgstr "Actualitzat"
#: ../callback.py:55
msgid "Erased"
-msgstr "Esborrat"
+msgstr "Suprimit"
-#: ../callback.py:56
-#: ../callback.py:57
-#: ../callback.py:59
-#: ../output.py:1027
+#: ../callback.py:56 ../callback.py:57 ../callback.py:59 ../output.py:1059
msgid "Installed"
msgstr "Instal·lat"
@@ -90,75 +77,70 @@ msgstr "Error: estat de sortida invàlid: %s per a %s"
#: ../callback.py:212
#, python-format
msgid "Erased: %s"
-msgstr "Esborrat: %s"
+msgstr "Suprimit: %s"
-#: ../callback.py:217
-#: ../output.py:923
+#: ../callback.py:217 ../output.py:939
msgid "Removing"
-msgstr "S'està esborrant"
+msgstr "Suprimint"
-#: ../callback.py:219
-#: ../yum/rpmtrans.py:77
+#: ../callback.py:219 ../yum/rpmtrans.py:77
msgid "Cleanup"
msgstr "Neteja"
-#: ../cli.py:106
+#: ../cli.py:107
#, python-format
msgid "Command \"%s\" already defined"
msgstr "L'ordre «%s» ja està definida"
-#: ../cli.py:118
+#: ../cli.py:119
msgid "Setting up repositories"
msgstr "Configurant repositoris"
-#: ../cli.py:129
+#: ../cli.py:130
msgid "Reading repository metadata in from local files"
msgstr "S'estan llegint les metadades de repositoris des de fitxers locals"
-#: ../cli.py:192
-#: ../utils.py:79
+#: ../cli.py:193 ../utils.py:87
#, python-format
msgid "Config Error: %s"
msgstr "Error de configuració: %s"
-#: ../cli.py:195
-#: ../cli.py:1224
-#: ../utils.py:82
+#: ../cli.py:196 ../cli.py:1253 ../utils.py:90
#, python-format
msgid "Options Error: %s"
msgstr "Error d'opcions: %s"
-#: ../cli.py:223
+#: ../cli.py:225
#, python-format
msgid " Installed: %s-%s at %s"
msgstr " Instal·lat: %s-%s a %s"
-#: ../cli.py:225
+#: ../cli.py:227
#, python-format
msgid " Built : %s at %s"
msgstr " Muntat : %s a %s"
-#: ../cli.py:227
+#: ../cli.py:229
#, python-format
msgid " Committed: %s at %s"
msgstr " Pujat: %s a %s"
-#: ../cli.py:266
+#: ../cli.py:268
msgid "You need to give some command"
msgstr "Cal que doneu alguna ordre"
-#: ../cli.py:309
+#: ../cli.py:311
msgid "Disk Requirements:\n"
msgstr "Requeriments de disc:\n"
-#: ../cli.py:311
+#: ../cli.py:313
#, python-format
msgid " At least %dMB needed on the %s filesystem.\n"
msgstr " Es necessiten almenys %dMB al sistema de fitxers %s.\n"
#. TODO: simplify the dependency errors?
#. Fixup the summary
-#: ../cli.py:316
+#: ../cli.py:318
msgid ""
"Error Summary\n"
"-------------\n"
@@ -166,58 +148,66 @@ msgstr ""
"Resum d'errors\n"
"-------------\n"
-#: ../cli.py:359
+#: ../cli.py:361
msgid "Trying to run the transaction but nothing to do. Exiting."
-msgstr "S'ha intentat executar la transacció però no hi ha cap tasca a fer. S'està sortint."
+msgstr ""
+"S'ha intentat executar la transacció però no hi ha cap tasca a fer. S'està "
+"sortint."
-#: ../cli.py:395
+#: ../cli.py:397
msgid "Exiting on user Command"
msgstr "S'està sortint de l'ordre de l'usuari"
-#: ../cli.py:399
+#: ../cli.py:401
msgid "Downloading Packages:"
-msgstr "S'estan descarregant els següents paquets:"
+msgstr "S'estan baixant els següents paquets:"
-#: ../cli.py:404
+#: ../cli.py:406
msgid "Error Downloading Packages:\n"
-msgstr "S'ha produït un error descarregant els següents paquets:\n"
+msgstr "S'ha produït un error baixant els següents paquets:\n"
-#: ../cli.py:418
-#: ../yum/__init__.py:3520
+#: ../cli.py:420 ../yum/__init__.py:3854
msgid "Running rpm_check_debug"
msgstr "S'està executant rpm_check_debug"
-#: ../cli.py:421
-#: ../yum/__init__.py:3523
+#: ../cli.py:429 ../yum/__init__.py:3863
+msgid "ERROR You need to update rpm to handle:"
+msgstr "S'ha produït un error. Necessiteu actualitzar el gestor rpm:"
+
+#: ../cli.py:431 ../yum/__init__.py:3866
msgid "ERROR with rpm_check_debug vs depsolve:"
msgstr "S'ha produït un error amb rpm_check_debug contra depsolve:"
-#: ../cli.py:425
+#: ../cli.py:437
+msgid "RPM needs to be updated"
+msgstr "Cal actualitzar l'RPM"
+
+#: ../cli.py:438
#, python-format
msgid "Please report this error in %s"
msgstr "Siusplau, informeu d'aquest error a %s"
-#: ../cli.py:431
+#: ../cli.py:444
msgid "Running Transaction Test"
msgstr "S'està executant la transacció de prova"
-#: ../cli.py:447
+#: ../cli.py:460
msgid "Finished Transaction Test"
msgstr "Ha acabat la transacció de prova"
-#: ../cli.py:449
+#: ../cli.py:462
msgid "Transaction Check Error:\n"
msgstr "S'ha produït un error en la transacció de prova:\n"
-#: ../cli.py:456
+#: ../cli.py:469
msgid "Transaction Test Succeeded"
msgstr "La transacció de prova ha acabat amb èxit"
-#: ../cli.py:477
+#: ../cli.py:491
msgid "Running Transaction"
msgstr "S'està executant la transacció"
-#: ../cli.py:507
+#: ../cli.py:521
msgid ""
"Refusing to automatically import keys when running unattended.\n"
"Use \"-y\" to override."
@@ -225,184 +215,191 @@ msgstr ""
"No s'importaran automàticament les claus en una execució desatesa.\n"
"Feu servir \"-y\" per a importar les claus."
-#: ../cli.py:526
-#: ../cli.py:560
+#: ../cli.py:540 ../cli.py:574
msgid " * Maybe you meant: "
msgstr " * Potser volíeu dir: "
-#: ../cli.py:543
-#: ../cli.py:551
+#: ../cli.py:557 ../cli.py:565
#, python-format
msgid "Package(s) %s%s%s available, but not installed."
msgstr "Paquets %s%s%s disponibles, però no instal·lats."
-#: ../cli.py:557
-#: ../cli.py:588
-#: ../cli.py:668
+#: ../cli.py:571 ../cli.py:602 ../cli.py:680
#, python-format
msgid "No package %s%s%s available."
msgstr "El paquet %s%s%s no està disponible."
-#: ../cli.py:593
-#: ../cli.py:695
+#: ../cli.py:607 ../cli.py:740
msgid "Package(s) to install"
msgstr "Paquets a instal·lar"
-#: ../cli.py:594
-#: ../cli.py:674
-#: ../cli.py:696
-#: ../yumcommands.py:159
-#: ../yumcommands.py:1013
+#: ../cli.py:608 ../cli.py:686 ../cli.py:719 ../cli.py:741
+#: ../yumcommands.py:157
msgid "Nothing to do"
msgstr "Res a fer"
-#: ../cli.py:627
+#: ../cli.py:641
#, python-format
msgid "%d packages marked for Update"
msgstr "%d paquets marcats per a actualitzar"
-#: ../cli.py:630
+#: ../cli.py:644
msgid "No Packages marked for Update"
msgstr "No hi ha cap paquet marcat per a actualitzar"
-#: ../cli.py:644
+#: ../cli.py:658
#, python-format
msgid "%d packages marked for removal"
-msgstr "%d paquets marcats per a esborrar"
+msgstr "%d paquets marcats per a suprimir"
-#: ../cli.py:647
+#: ../cli.py:661
msgid "No Packages marked for removal"
-msgstr "No hi ha cap paquet marcat per a esborrar"
+msgstr "No hi ha cap paquet marcat per a suprimir"
-#: ../cli.py:673
+#: ../cli.py:685
msgid "Package(s) to downgrade"
msgstr "Paquets per a desactualitzar"
-#: ../cli.py:686
+#: ../cli.py:709
+#, python-format
+msgid " (from %s)"
+msgstr " (des de %s)"
+
+#: ../cli.py:711
+#, python-format
+msgid "Installed package %s%s%s%s not available."
+msgstr "El paquet instal·lat %s%s%s%s no està disponible."
+
+#: ../cli.py:718
+msgid "Package(s) to reinstall"
+msgstr "Paquets a reinstal·lar"
+
+#: ../cli.py:731
msgid "No Packages Provided"
msgstr "No s'ha proporcionat cap paquet"
-#: ../cli.py:741
-msgid "Matching packages for package list to user args"
-msgstr "S'està comparant els paquets per a la llista de paquets amb els arguments de l'usuari"
-
-#: ../cli.py:790
+#: ../cli.py:815
#, python-format
msgid "Warning: No matches found for: %s"
msgstr "Avís: no s'ha trobat cap coincidència per a: %s"
-#: ../cli.py:793
+#: ../cli.py:818
msgid "No Matches found"
msgstr "No s'ha trobat cap coincidència"
-#: ../cli.py:832
+#: ../cli.py:857
#, python-format
msgid ""
"Warning: 3.0.x versions of yum would erroneously match against filenames.\n"
" You can use \"%s*/%s%s\" and/or \"%s*bin/%s%s\" to get that behaviour"
msgstr ""
-"Avís: les versions 3.0.x del yum comproven incorrectament els noms de fitxer.\n"
+"Avís: les versions 3.0.x del yum comproven incorrectament els noms de "
+"fitxer.\n"
" Podeu usar \"%s*/%s%s\" i/o \"%s*bin/%s%s\" per obtenir aquest comportament"
-#: ../cli.py:848
+#: ../cli.py:873
#, python-format
msgid "No Package Found for %s"
msgstr "No s'ha trobat cap paquet per a %s"
-#: ../cli.py:860
+#: ../cli.py:885
msgid "Cleaning up Everything"
msgstr "S'està netejant tot"
-#: ../cli.py:874
+#: ../cli.py:899
msgid "Cleaning up Headers"
msgstr "S'estan netejant les capçaleres"
-#: ../cli.py:877
+#: ../cli.py:902
msgid "Cleaning up Packages"
msgstr "S'estan netejant els paquets"
-#: ../cli.py:880
+#: ../cli.py:905
msgid "Cleaning up xml metadata"
msgstr "S'estan netejant les metadades xml"
-#: ../cli.py:883
+#: ../cli.py:908
msgid "Cleaning up database cache"
msgstr "S'està netejant la memòria cau de la base de dades"
-#: ../cli.py:886
+#: ../cli.py:911
msgid "Cleaning up expire-cache metadata"
msgstr "S'està netejant la memòria cau de metadades que han vençut"
-#: ../cli.py:889
+#: ../cli.py:914
msgid "Cleaning up plugins"
msgstr "S'estan netejant els connectors"
-#: ../cli.py:914
+#: ../cli.py:939
msgid "Installed Groups:"
msgstr "Grups instal·lats:"
-#: ../cli.py:926
+#: ../cli.py:951
msgid "Available Groups:"
msgstr "Grups disponibles:"
-#: ../cli.py:936
+#: ../cli.py:961
msgid "Done"
msgstr "Fet"
-#: ../cli.py:947
-#: ../cli.py:965
-#: ../cli.py:971
-#: ../yum/__init__.py:2421
+#: ../cli.py:972 ../cli.py:990 ../cli.py:996 ../yum/__init__.py:2560
#, python-format
msgid "Warning: Group %s does not exist."
msgstr "Avís: El grup %s no existeix."
-#: ../cli.py:975
+#: ../cli.py:1000
msgid "No packages in any requested group available to install or update"
-msgstr "No hi ha cap paquet disponible per a instal·lar o actualitzar en els grups sol·licitats"
+msgstr ""
+"No hi ha cap paquet disponible per a instal·lar o actualitzar en els grups "
+"sol·licitats"
-#: ../cli.py:977
+#: ../cli.py:1002
#, python-format
msgid "%d Package(s) to Install"
msgstr "%d paquets a instal·lar"
-#: ../cli.py:987
-#: ../yum/__init__.py:2433
+#: ../cli.py:1012 ../yum/__init__.py:2572
#, python-format
msgid "No group named %s exists"
msgstr "No existeix cap grup anomenat %s"
-#: ../cli.py:993
+#: ../cli.py:1018
msgid "No packages to remove from groups"
-msgstr "No hi ha cap paquet a esborrar dels grups"
+msgstr "No hi ha cap paquet a suprimir dels grups"
-#: ../cli.py:995
+#: ../cli.py:1020
#, python-format
msgid "%d Package(s) to remove"
-msgstr "%d paquets a esborrar"
+msgstr "%d paquets a suprimir"
-#: ../cli.py:1037
+#: ../cli.py:1062
#, python-format
msgid "Package %s is already installed, skipping"
msgstr "El paquet %s ja està instal·lat, s'ometrà"
-#: ../cli.py:1048
+#: ../cli.py:1073
#, python-format
msgid "Discarding non-comparable pkg %s.%s"
msgstr "S'està descartant el paquet no comparable %s.%s"
#. we've not got any installed that match n or n+a
-#: ../cli.py:1074
+#: ../cli.py:1099
#, python-format
msgid "No other %s installed, adding to list for potential install"
-msgstr "No hi ha cap altre %s instal·lat, s'afegeix a la llista per a una possible instal·lació"
+msgstr ""
+"No hi ha cap altre %s instal·lat, s'afegeix a la llista per a una possible "
+"instal·lació"
-#: ../cli.py:1093
+#: ../cli.py:1119
+msgid "Plugin Options"
+msgstr "Opcions del connector"
+
+#: ../cli.py:1127
#, python-format
msgid "Command line error: %s"
msgstr "Error en la línia d'ordres: %s"
-#: ../cli.py:1106
+#: ../cli.py:1140
#, python-format
msgid ""
"\n"
@@ -413,253 +410,259 @@ msgstr ""
"\n"
"%s: l'opció %s necessita un argument"
-#: ../cli.py:1164
+#: ../cli.py:1193
msgid "--color takes one of: auto, always, never"
msgstr "--color pren un valor d'entre: auto, always, never"
-#: ../cli.py:1266
+#: ../cli.py:1300
msgid "show this help message and exit"
msgstr "mostra el missatge d'ajuda i surt"
-#: ../cli.py:1270
+#: ../cli.py:1304
msgid "be tolerant of errors"
msgstr "sigues tolerant amb els errors"
-#: ../cli.py:1272
+#: ../cli.py:1306
msgid "run entirely from cache, don't update cache"
msgstr "executa totalment des de la memòria cau, no l'actualitzis"
-#: ../cli.py:1274
+#: ../cli.py:1308
msgid "config file location"
msgstr "ubicació del fitxer de configuració"
-#: ../cli.py:1276
+#: ../cli.py:1310
msgid "maximum command wait time"
msgstr "temps màxim d'espera d'ordres"
-#: ../cli.py:1278
+#: ../cli.py:1312
msgid "debugging output level"
msgstr "nivell de sortida de depuració"
-#: ../cli.py:1282
+#: ../cli.py:1316
msgid "show duplicates, in repos, in list/search commands"
msgstr "mostra duplicats, en repositoris, en les ordres per llistar i cercar"
-#: ../cli.py:1284
+#: ../cli.py:1318
msgid "error output level"
msgstr "nivell de sortida d'error"
-#: ../cli.py:1287
+#: ../cli.py:1321
msgid "quiet operation"
msgstr "operació silenciosa"
-#: ../cli.py:1289
+#: ../cli.py:1323
msgid "verbose operation"
msgstr "operació descriptiva"
-#: ../cli.py:1291
+#: ../cli.py:1325
msgid "answer yes for all questions"
msgstr "respon sí a totes les preguntes"
-#: ../cli.py:1293
+#: ../cli.py:1327
msgid "show Yum version and exit"
msgstr "mostra la versió del Yum i surt"
-#: ../cli.py:1294
+#: ../cli.py:1328
msgid "set install root"
msgstr "estableix l'arrel de la instal·lació"
-#: ../cli.py:1298
+#: ../cli.py:1332
msgid "enable one or more repositories (wildcards allowed)"
msgstr "habilita un o més repositoris (es permeten caràcters de reemplaçament)"
-#: ../cli.py:1302
+#: ../cli.py:1336
msgid "disable one or more repositories (wildcards allowed)"
-msgstr "deshabilita un o més repositoris (es permeten caràcters de reemplaçament)"
+msgstr ""
+"deshabilita un o més repositoris (es permeten caràcters de reemplaçament)"
-#: ../cli.py:1305
+#: ../cli.py:1339
msgid "exclude package(s) by name or glob"
msgstr "exclou els paquets per nom o expressió regular del glob"
-#: ../cli.py:1307
+#: ../cli.py:1341
msgid "disable exclude from main, for a repo or for everything"
msgstr "inhabilita l'exclusió des de l'inici, per a un repositori o per a tot"
-#: ../cli.py:1310
+#: ../cli.py:1344
msgid "enable obsoletes processing during updates"
msgstr "habilita el processament d'obsolets durant les actualitzacions"
-#: ../cli.py:1312
+#: ../cli.py:1346
msgid "disable Yum plugins"
msgstr "inhabilita els connectors de Yum"
-#: ../cli.py:1314
+#: ../cli.py:1348
msgid "disable gpg signature checking"
msgstr "inhabilita la comprobació de signatures gpg"
-#: ../cli.py:1316
+#: ../cli.py:1350
msgid "disable plugins by name"
msgstr "inhabilita els connectors pel seu nom"
-#: ../cli.py:1319
+#: ../cli.py:1353
msgid "enable plugins by name"
msgstr "habilita els connectors pel seu nom"
-#: ../cli.py:1322
+#: ../cli.py:1356
msgid "skip packages with depsolving problems"
msgstr "omet paquets amb problemes de resolució de dependències"
-#: ../cli.py:1324
+#: ../cli.py:1358
msgid "control whether color is used"
msgstr "controla sempre que s'usi color"
-#: ../output.py:298
+#: ../output.py:303
msgid "Jan"
msgstr "Gen"
-#: ../output.py:298
+#: ../output.py:303
msgid "Feb"
msgstr "Feb"
-#: ../output.py:298
+#: ../output.py:303
msgid "Mar"
msgstr "Mar"
-#: ../output.py:298
+#: ../output.py:303
msgid "Apr"
msgstr "Abr"
-#: ../output.py:298
+#: ../output.py:303
msgid "May"
msgstr "Mai"
-#: ../output.py:298
+#: ../output.py:303
msgid "Jun"
msgstr "Jun"
-#: ../output.py:299
+#: ../output.py:304
msgid "Jul"
msgstr "Jul"
-#: ../output.py:299
+#: ../output.py:304
msgid "Aug"
msgstr "Ago"
-#: ../output.py:299
+#: ../output.py:304
msgid "Sep"
msgstr "Set"
-#: ../output.py:299
+#: ../output.py:304
msgid "Oct"
msgstr "Oct"
-#: ../output.py:299
+#: ../output.py:304
msgid "Nov"
msgstr "Nov"
-#: ../output.py:299
+#: ../output.py:304
msgid "Dec"
msgstr "Des"
-#: ../output.py:309
+#: ../output.py:314
msgid "Trying other mirror."
msgstr "S'està intentant un altre servidor rèplica."
-#: ../output.py:525
+#: ../output.py:536
#, python-format
msgid "Name : %s%s%s"
msgstr "Nom : %s%s%s"
-#: ../output.py:526
+#: ../output.py:537
#, python-format
msgid "Arch : %s"
msgstr "Arq : %s"
-#: ../output.py:528
+#: ../output.py:539
#, python-format
msgid "Epoch : %s"
msgstr "Època : %s"
-#: ../output.py:529
+#: ../output.py:540
#, python-format
msgid "Version : %s"
msgstr "Versió : %s"
-#: ../output.py:530
+#: ../output.py:541
#, python-format
msgid "Release : %s"
msgstr "Release : %s"
-#: ../output.py:531
+#: ../output.py:542
#, python-format
msgid "Size : %s"
msgstr "Mida : %s"
-#: ../output.py:532
+#: ../output.py:543
#, python-format
msgid "Repo : %s"
msgstr "Repo : %s"
-#: ../output.py:534
+#: ../output.py:545
+#, python-format
+msgid "From repo : %s"
+msgstr "Des del repo : %s"
+
+#: ../output.py:547
#, python-format
msgid "Committer : %s"
msgstr "Desenvolupador : %s"
-#: ../output.py:535
+#: ../output.py:548
#, python-format
msgid "Committime : %s"
msgstr "Pujat : %s"
-#: ../output.py:536
+#: ../output.py:549
#, python-format
msgid "Buildtime : %s"
msgstr "Temps de creació : %s"
-#: ../output.py:538
+#: ../output.py:551
#, python-format
msgid "Installtime: %s"
msgstr "Temps d'instal·lació: %s"
-#: ../output.py:539
+#: ../output.py:552
msgid "Summary : "
msgstr "Resum : "
-#: ../output.py:541
+#: ../output.py:554
#, python-format
msgid "URL : %s"
msgstr "URL : %s"
-#: ../output.py:542
+#: ../output.py:555
#, python-format
msgid "License : %s"
msgstr "Llicència : %s"
-#: ../output.py:543
+#: ../output.py:556
msgid "Description: "
msgstr "Descripció: "
-#: ../output.py:611
+#: ../output.py:624
msgid "y"
msgstr "s"
-#: ../output.py:611
+#: ../output.py:624
msgid "yes"
msgstr "sí"
-#: ../output.py:612
+#: ../output.py:625
msgid "n"
msgstr "n"
-#: ../output.py:612
+#: ../output.py:625
msgid "no"
msgstr "no"
# REMEMBER to Translate [Y/N] to the current locale
-#: ../output.py:616
+#: ../output.py:629
msgid "Is this ok [y/N]: "
msgstr "És correcte [s/N]: "
-#: ../output.py:704
+#: ../output.py:720
#, python-format
msgid ""
"\n"
@@ -668,134 +671,142 @@ msgstr ""
"\n"
"Grup: %s"
-#: ../output.py:708
+#: ../output.py:724
#, python-format
msgid " Group-Id: %s"
msgstr " Id de Grup: %s"
-#: ../output.py:713
+#: ../output.py:729
#, python-format
msgid " Description: %s"
msgstr " Descripció: %s"
-#: ../output.py:715
+#: ../output.py:731
msgid " Mandatory Packages:"
msgstr " Paquets obligatoris:"
-#: ../output.py:716
+#: ../output.py:732
msgid " Default Packages:"
msgstr " Paquets per defecte:"
-#: ../output.py:717
+#: ../output.py:733
msgid " Optional Packages:"
msgstr " Paquets opcionals:"
-#: ../output.py:718
+#: ../output.py:734
msgid " Conditional Packages:"
msgstr " Paquets condicionals:"
-#: ../output.py:738
+#: ../output.py:754
#, python-format
msgid "package: %s"
msgstr "paquet: %s"
-#: ../output.py:740
+#: ../output.py:756
msgid " No dependencies for this package"
msgstr " No hi ha dependències per a aquest paquet"
-#: ../output.py:745
+#: ../output.py:761
#, python-format
msgid " dependency: %s"
msgstr " dependència: %s"
-#: ../output.py:747
+#: ../output.py:763
msgid " Unsatisfied dependency"
msgstr " Dependència insatisfeta"
-#: ../output.py:819
+#: ../output.py:835
#, python-format
msgid "Repo : %s"
msgstr "Repo : %s"
-#: ../output.py:820
+#: ../output.py:836
msgid "Matched from:"
msgstr "Coincidències amb:"
-#: ../output.py:828
+#: ../output.py:845
msgid "Description : "
msgstr "Descripció : "
-#: ../output.py:831
+#: ../output.py:848
#, python-format
msgid "URL : %s"
msgstr "URL : %s"
-#: ../output.py:834
+#: ../output.py:851
#, python-format
msgid "License : %s"
msgstr "Llicència : %s"
-#: ../output.py:837
+#: ../output.py:854
#, python-format
msgid "Filename : %s"
msgstr "Fitxer : %s"
-#: ../output.py:841
+#: ../output.py:858
msgid "Other : "
msgstr "Altre : "
-#: ../output.py:874
+#: ../output.py:891
msgid "There was an error calculating total download size"
msgstr "S'ha produït un error en calcular la mida total de la descàrrega"
-#: ../output.py:879
+#: ../output.py:896
#, python-format
msgid "Total size: %s"
msgstr "Mida total: %s"
-#: ../output.py:882
+#: ../output.py:899
#, python-format
msgid "Total download size: %s"
msgstr "Mida total de la descàrrega: %s"
-#: ../output.py:924
+#: ../output.py:940
+#,
+msgid "Reinstalling"
+msgstr "Tornant a instal·lar"
+
+#: ../output.py:941
+msgid "Downgrading"
+msgstr "Desfent l'actualització"
+
+#: ../output.py:942
msgid "Installing for dependencies"
msgstr "S'està instal·lant per dependències"
-#: ../output.py:925
+#: ../output.py:943
msgid "Updating for dependencies"
msgstr "S'està actualitzant degut a les dependències"
-#: ../output.py:926
+#: ../output.py:944
msgid "Removing for dependencies"
-msgstr "S'està esborrant degut a les dependències"
+msgstr "S'està suprimint degut a les dependències"
-#: ../output.py:933
-#: ../output.py:1031
+#: ../output.py:951 ../output.py:1063
msgid "Skipped (dependency problems)"
msgstr "Ignorat degut a problemes de dependències:"
-#: ../output.py:954
+#: ../output.py:974
msgid "Package"
msgstr "Paquet"
-#: ../output.py:954
+#: ../output.py:974
msgid "Arch"
msgstr "Arq"
-#: ../output.py:955
+#: ../output.py:975
msgid "Version"
msgstr "Versió"
-#: ../output.py:955
+#: ../output.py:975
msgid "Repository"
msgstr "Repositori"
-#: ../output.py:956
+#: ../output.py:976
msgid "Size"
msgstr "Mida"
-#: ../output.py:968
+#: ../output.py:988
#, python-format
msgid ""
" replacing %s%s%s.%s %s\n"
@@ -804,135 +815,164 @@ msgstr ""
" s'està reemplaçant %s%s%s.%s %s\n"
"\n"
-#: ../output.py:977
+#: ../output.py:997
#, python-format
msgid ""
"\n"
"Transaction Summary\n"
"%s\n"
-"Install %5.5s Package(s) \n"
-"Update %5.5s Package(s) \n"
-"Remove %5.5s Package(s) \n"
msgstr ""
"\n"
-"Resum de transaccions\n"
+"Resum de la transacció\n"
"%s\n"
-"Instal·la %5.5s paquets \n"
-"Actualitza %5.5s paquets \n"
-"Esborra %5.5s paquets \n"
-#: ../output.py:1025
+#: ../output.py:1004
+#, python-format
+msgid ""
+"Install %5.5s Package(s)\n"
+"Upgrade %5.5s Package(s)\n"
+msgstr ""
+"Instal·la %5.5s paquets\n"
+"Actualitza %5.5s paquets\n"
+
+
+#: ../output.py:1013
+#, python-format //paraula downgrade
+msgid ""
+"Remove %5.5s Package(s)\n"
+"Reinstall %5.5s Package(s)\n"
+"Downgrade %5.5s Package(s)\n"
+msgstr ""
+"Suprimeix %5.5s paquets\n"
+"Reinstal·la %5.5s paquets\n"
+"Desactualitza %5.5s paquets\n"
+
+#: ../output.py:1057
msgid "Removed"
-msgstr "Esborrat"
+msgstr "Suprimit"
-#: ../output.py:1026
+#: ../output.py:1058
msgid "Dependency Removed"
-msgstr "Dependència esborrada"
+msgstr "Dependència suprimida"
-#: ../output.py:1028
+#: ../output.py:1060
msgid "Dependency Installed"
msgstr "Dependència instal·lada"
-#: ../output.py:1030
+#: ../output.py:1062
msgid "Dependency Updated"
msgstr "Dependència actualitzada"
-#: ../output.py:1032
+#: ../output.py:1064
msgid "Replaced"
msgstr "Reemplaçat"
-#: ../output.py:1033
+#: ../output.py:1065
msgid "Failed"
msgstr "Ha fallat"
#. Delta between C-c's so we treat as exit
-#: ../output.py:1099
+#: ../output.py:1131
msgid "two"
msgstr "dos"
-#: ../output.py:1106
+#. For translators: This is output like:
+#. Current download cancelled, interrupt (ctrl-c) again within two seconds
+#. to exit.
+#. Where "interupt (ctrl-c) again" and "two" are highlighted.
+#: ../output.py:1142
#, python-format
msgid ""
"\n"
-" Current download cancelled, %sinterrupt (ctrl-c) again%s within %s%s%s seconds to exit.\n"
+" Current download cancelled, %sinterrupt (ctrl-c) again%s within %s%s%s "
+"seconds\n"
+"to exit.\n"
msgstr ""
"\n"
-" S'ha cancel·lat la descàrrega actual, %sinterromp (crtl-c) de nou%s en %s%s%s segons per a sortir.\n"
+" S'ha cancel·lat la descàrrega actual, %sinterromp (crtl-c) de nou%s en %s%s%s "
+"segons\n"
+"per a sortir.\n"
-#: ../output.py:1116
+#: ../output.py:1153
msgid "user interrupt"
msgstr "interrupció de l'usuari"
-#: ../output.py:1132
+#: ../output.py:1171
msgid "Total"
msgstr "Total"
-#: ../output.py:1146
+#: ../output.py:1186
msgid "installed"
msgstr "instal·lat"
-#: ../output.py:1147
+#: ../output.py:1187
msgid "updated"
msgstr "actualitzat"
-#: ../output.py:1148
+#: ../output.py:1188
msgid "obsoleted"
msgstr "obsolet"
-#: ../output.py:1149
+#: ../output.py:1189
msgid "erased"
-msgstr "esborrat"
+msgstr "suprimit"
-#: ../output.py:1153
+#: ../output.py:1193
#, python-format
msgid "---> Package %s.%s %s:%s-%s set to be %s"
msgstr "---> Paquet %s.%s %s:%s-%s passarà a ser %s"
-#: ../output.py:1160
+#: ../output.py:1200
msgid "--> Running transaction check"
msgstr "--> S'està executant la transacció de prova"
-#: ../output.py:1165
+#: ../output.py:1205
msgid "--> Restarting Dependency Resolution with new changes."
-msgstr "--> Tornant a calcular la resolució de dependències amb els nous canvis."
+msgstr ""
+"--> Tornant a calcular la resolució de dependències amb els nous canvis."
-#: ../output.py:1170
+#: ../output.py:1210
msgid "--> Finished Dependency Resolution"
msgstr "--> Ha finalitzat la resolució de dependències"
-#: ../output.py:1175
+#: ../output.py:1215 ../output.py:1220
#, python-format
msgid "--> Processing Dependency: %s for package: %s"
msgstr "--> S'està processant la dependència %s per al paquet: %s"
-#: ../output.py:1180
+#: ../output.py:1224
#, python-format
msgid "--> Unresolved Dependency: %s"
msgstr "--> Dependència no resolta: %s"
-#: ../output.py:1186
+#: ../output.py:1230 ../output.py:1235
#, python-format
msgid "--> Processing Conflict: %s conflicts %s"
msgstr "--> S'està processant el conflicte: %s té un conflicte amb %s"
-#: ../output.py:1189
+#: ../output.py:1239
msgid "--> Populating transaction set with selected packages. Please wait."
-msgstr "--> S'està poblant la transacció amb els paquets sel·leccionats. Si us plau, espereu."
+msgstr ""
+"--> S'està poblant la transacció amb els paquets sel·leccionats. Si us plau, "
+"espereu."
-#: ../output.py:1193
+#: ../output.py:1243
#, python-format
msgid "---> Downloading header for %s to pack into transaction set."
-msgstr "---> S'està descarregant la capçalera per a %s per a empaquetar dins de la transacció de prova."
+msgstr ""
+"---> S'està baixant la capçalera per a %s per a empaquetar dins de la "
+"transacció de prova."
-#: ../yumcommands.py:41
+#: ../yumcommands.py:40
msgid "You need to be root to perform this command."
msgstr "Heu de ser root per a executar aquesta ordre."
-#: ../yumcommands.py:48
+#: ../yumcommands.py:47
msgid ""
"\n"
"You have enabled checking of packages via GPG keys. This is a good thing. \n"
-"However, you do not have any GPG public keys installed. You need to download\n"
+"However, you do not have any GPG public keys installed. You need to "
+"download\n"
"the keys for packages you wish to install and install them.\n"
"You can do that by running the command:\n"
" rpm --import public.gpg.key\n"
@@ -945,8 +985,10 @@ msgid ""
"For more information contact your distribution or package provider.\n"
msgstr ""
"\n"
-"Heu habilitat la comprovació de paquets utilitzant claus GPG. És una bona opció. \n"
-"No obstant, no teniu cap clau pública GPG instal·lada. Necessiteu descarregar\n"
+"Heu habilitat la comprovació de paquets utilitzant claus GPG. És una bona "
+"opció. \n"
+"No obstant, no teniu cap clau pública GPG instal·lada. Necessiteu "
+"baixar\n"
"les claus per als paquets que desitgeu instal·lar i instal·lar-les.\n"
"Podeu fer-ho executant l'ordre:\n"
" rpm --import clau.pública.gpg\n"
@@ -956,163 +998,164 @@ msgstr ""
"per a un repositori en l'opció 'gpgkey' en la secció d'un repositori i yum \n"
"la instal·larà per vosaltres.\n"
"\n"
-"Per a més informació contacteu el vostre distribuïdor o proveïdor de paquets.\n"
+"Per a més informació contacteu el vostre distribuïdor o proveïdor de "
+"paquets.\n"
-#: ../yumcommands.py:68
+#: ../yumcommands.py:67
#, python-format
msgid "Error: Need to pass a list of pkgs to %s"
msgstr "Error: es necessita passar una llista de paquets a %s"
-#: ../yumcommands.py:74
+#: ../yumcommands.py:73
msgid "Error: Need an item to match"
msgstr "Error: es necessita algun element per comparar"
-#: ../yumcommands.py:80
+#: ../yumcommands.py:79
msgid "Error: Need a group or list of groups"
msgstr "Error: es necessita un grup o una llista de grups"
-#: ../yumcommands.py:89
+#: ../yumcommands.py:88
#, python-format
msgid "Error: clean requires an option: %s"
msgstr "Error: la neteja requereix una opció: %s"
-#: ../yumcommands.py:94
+#: ../yumcommands.py:93
#, python-format
msgid "Error: invalid clean argument: %r"
msgstr "Error: argument invàlid per a la neteja: %r"
-#: ../yumcommands.py:107
+#: ../yumcommands.py:106
msgid "No argument to shell"
msgstr "No hi ha arguments per a l'intèrpret d'ordres"
-#: ../yumcommands.py:110
+#: ../yumcommands.py:108
#, python-format
msgid "Filename passed to shell: %s"
msgstr "Nom del fitxer passat a l'intèrpret d'ordres: %s"
-#: ../yumcommands.py:114
+#: ../yumcommands.py:112
#, python-format
msgid "File %s given as argument to shell does not exist."
msgstr "El fitxer %s donat com a argument a l'intèrpret d'ordres no existeix."
-#: ../yumcommands.py:120
+#: ../yumcommands.py:118
msgid "Error: more than one file given as argument to shell."
-msgstr "Error: s'ha donat més d'un fitxer com a argument per a l'intèrpret d'ordres."
+msgstr ""
+"Error: s'ha donat més d'un fitxer com a argument per a l'intèrpret d'ordres."
-#: ../yumcommands.py:169
+#: ../yumcommands.py:167
msgid "PACKAGE..."
msgstr "PAQUET..."
-#: ../yumcommands.py:172
+#: ../yumcommands.py:170
msgid "Install a package or packages on your system"
msgstr "Instal·la un o més paquets al vostre sistema"
-#: ../yumcommands.py:180
+#: ../yumcommands.py:178
msgid "Setting up Install Process"
msgstr "S'està preparant el procés d'instal·lació"
-#: ../yumcommands.py:191
+#: ../yumcommands.py:189
msgid "[PACKAGE...]"
msgstr "[PAQUET...]"
-#: ../yumcommands.py:194
+#: ../yumcommands.py:192
msgid "Update a package or packages on your system"
msgstr "S'ha actualitzat un o més paquets al vostre sistema"
-#: ../yumcommands.py:201
+#: ../yumcommands.py:199
msgid "Setting up Update Process"
msgstr "S'està preparant el procés d'actualització"
-#: ../yumcommands.py:243
+#: ../yumcommands.py:244
msgid "Display details about a package or group of packages"
msgstr "Mostra detalls sobre un paquet o un grup de paquets"
-#: ../yumcommands.py:292
+#: ../yumcommands.py:293
msgid "Installed Packages"
msgstr "Paquets instal·lats"
-#: ../yumcommands.py:300
+#: ../yumcommands.py:301
msgid "Available Packages"
msgstr "Paquets disponibles"
-#: ../yumcommands.py:304
+#: ../yumcommands.py:305
msgid "Extra Packages"
msgstr "Paquets extra"
-#: ../yumcommands.py:308
+#: ../yumcommands.py:309
msgid "Updated Packages"
msgstr "Paquets actualitzats"
#. This only happens in verbose mode
-#: ../yumcommands.py:316
-#: ../yumcommands.py:323
-#: ../yumcommands.py:600
+#: ../yumcommands.py:317 ../yumcommands.py:324 ../yumcommands.py:600
msgid "Obsoleting Packages"
msgstr "Paquets obsolets"
-#: ../yumcommands.py:325
+#: ../yumcommands.py:326
msgid "Recently Added Packages"
msgstr "Paquets recentment afegits"
-#: ../yumcommands.py:332
+#: ../yumcommands.py:333
msgid "No matching Packages to list"
msgstr "No hi ha paquets coincidents per llistar"
-#: ../yumcommands.py:346
+#: ../yumcommands.py:347
msgid "List a package or groups of packages"
msgstr "Llista un paquet o un grup de paquets"
-#: ../yumcommands.py:358
+#: ../yumcommands.py:359
msgid "Remove a package or packages from your system"
-msgstr "Esborra un o més paquets del vostre sistema"
+msgstr "Suprimeix un o més paquets del vostre sistema"
-#: ../yumcommands.py:365
+#: ../yumcommands.py:366
msgid "Setting up Remove Process"
-msgstr "S'està preparant el procés d'esborrat"
+msgstr "S'està preparant el procés de supressió"
-#: ../yumcommands.py:379
+#: ../yumcommands.py:380
msgid "Setting up Group Process"
msgstr "S'està preparant el procés de grup"
-#: ../yumcommands.py:385
+#: ../yumcommands.py:386
msgid "No Groups on which to run command"
msgstr "No hi ha cap grup on executar l'ordre"
-#: ../yumcommands.py:398
+#: ../yumcommands.py:399
msgid "List available package groups"
msgstr "Llista els grups de paquets disponibles"
-#: ../yumcommands.py:415
+#: ../yumcommands.py:416
msgid "Install the packages in a group on your system"
msgstr "Instal·la els paquets en un grup en el vostre sistema"
-#: ../yumcommands.py:437
+#: ../yumcommands.py:438
msgid "Remove the packages in a group from your system"
-msgstr "Esborra els paquets en un grup en el vostre sistema"
+msgstr "Suprimeix els paquets en un grup en el vostre sistema"
-#: ../yumcommands.py:464
+#: ../yumcommands.py:465
msgid "Display details about a package group"
msgstr "Mostra detalls sobre un grup de paquets"
-#: ../yumcommands.py:488
+#: ../yumcommands.py:489
msgid "Generate the metadata cache"
msgstr "Genera les metadades de la memòria cau"
-#: ../yumcommands.py:494
+#: ../yumcommands.py:495
msgid "Making cache files for all metadata files."
-msgstr "S'estan fent els fitxers de memòria cau per a tots els fitxers de metadades."
+msgstr ""
+"S'estan fent els fitxers de memòria cau per a tots els fitxers de metadades."
-#: ../yumcommands.py:495
+#: ../yumcommands.py:496
msgid "This may take a while depending on the speed of this computer"
msgstr "Això pot trigar una estona depenent de la velocitat d'aquest ordinador"
-#: ../yumcommands.py:516
+#: ../yumcommands.py:517
msgid "Metadata Cache Created"
msgstr "S'han creat les metadades per a la memòria cau"
-#: ../yumcommands.py:530
+#: ../yumcommands.py:531
msgid "Remove cached data"
-msgstr "S'han esborrat les dades de la memòria cau"
+msgstr "S'han suprimit les dades de la memòria cau"
#: ../yumcommands.py:551
msgid "Find what package provides the given value"
@@ -1174,99 +1217,122 @@ msgstr "S'estan trobant dependències: "
msgid "Display the configured software repositories"
msgstr "Mostra els repositoris de programari configurats"
-#: ../yumcommands.py:803
-#: ../yumcommands.py:804
+#: ../yumcommands.py:803 ../yumcommands.py:804
msgid "enabled"
msgstr "habilitat"
-#: ../yumcommands.py:812
-#: ../yumcommands.py:813
+#: ../yumcommands.py:812 ../yumcommands.py:813
msgid "disabled"
msgstr "deshabilitat"
#: ../yumcommands.py:827
-msgid "Repo-id : "
-msgstr "Id-repo : "
+msgid "Repo-id : "
+msgstr "Id-repo : "
#: ../yumcommands.py:828
-msgid "Repo-name : "
-msgstr "Nom-repo : "
+msgid "Repo-name : "
+msgstr "Nom-repo : "
#: ../yumcommands.py:829
-msgid "Repo-status : "
-msgstr "Estat-repo : "
+msgid "Repo-status : "
+msgstr "Estat-repo : "
#: ../yumcommands.py:831
msgid "Repo-revision: "
-msgstr "Repo-revisió : "
+msgstr "Repo-revisió : "
#: ../yumcommands.py:835
-msgid "Repo-tags : "
-msgstr "Repo-etiquetes : "
+msgid "Repo-tags : "
+msgstr "Repo-etiquetes : "
#: ../yumcommands.py:841
msgid "Repo-distro-tags: "
-msgstr "Repo-etiq-dist : "
+msgstr "Repo-etiq-dist : "
#: ../yumcommands.py:846
-msgid "Repo-updated: "
-msgstr "Repo-actualitzat: "
+msgid "Repo-updated : "
+msgstr "Repo-actualitzat : "
#: ../yumcommands.py:848
-msgid "Repo-pkgs : "
-msgstr "Paquets-repo : "
+msgid "Repo-pkgs : "
+msgstr "Paquets-repo : "
#: ../yumcommands.py:849
-msgid "Repo-size : "
-msgstr "Mida-repo : "
+msgid "Repo-size : "
+msgstr "Mida-repo : "
#: ../yumcommands.py:856
-msgid "Repo-baseurl: "
-msgstr "URL-base-repo : "
+msgid "Repo-baseurl : "
+msgstr "URL-base-repo : "
-#: ../yumcommands.py:860
+#: ../yumcommands.py:864
msgid "Repo-metalink: "
-msgstr "Repo-metaenllaç : "
-
-#: ../yumcommands.py:863
-msgid "Repo-mirrors: "
-msgstr "Miralls-repo : "
+msgstr "Repo-metaenllaç : "
-#: ../yumcommands.py:867
-msgid "Repo-exclude: "
-msgstr "Repo-exclou : "
+#: ../yumcommands.py:868
+#,
+msgid " Updated : "
+msgstr " Actualitzat : "
#: ../yumcommands.py:871
-msgid "Repo-include: "
-msgstr "Repo-inclou : "
+msgid "Repo-mirrors : "
+msgstr "Miralls-repo : "
+
+#: ../yumcommands.py:875 ../yummain.py:133
+msgid "Unknown"
+msgstr "Desconegut"
+
+#: ../yumcommands.py:881
+#, python-format
+msgid "Never (last: %s)"
+msgstr "Mai (últim: %s)"
+
+#: ../yumcommands.py:883
+#, python-format
+msgid "Instant (last: %s)"
+msgstr "Temps d'instal·lació (últim: %s)"
+
+#: ../yumcommands.py:886
+#, python-format
+msgid "%s second(s) (last: %s)"
+msgstr "%s segons (últim: %s)"
+
+#: ../yumcommands.py:888
+msgid "Repo-expire : "
+msgstr "Venç-repo : "
+
+#: ../yumcommands.py:891
+msgid "Repo-exclude : "
+msgstr "Repo-exclou : "
+
+#: ../yumcommands.py:895
+msgid "Repo-include : "
+msgstr "Repo-inclou : "
#. Work out the first (id) and last (enabled/disalbed/count),
#. then chop the middle (name)...
-#: ../yumcommands.py:881
-#: ../yumcommands.py:907
+#: ../yumcommands.py:905 ../yumcommands.py:931
msgid "repo id"
msgstr "id repo"
-#: ../yumcommands.py:895
-#: ../yumcommands.py:896
-#: ../yumcommands.py:910
+#: ../yumcommands.py:919 ../yumcommands.py:920 ../yumcommands.py:934
msgid "status"
msgstr "estat"
-#: ../yumcommands.py:908
+#: ../yumcommands.py:932
msgid "repo name"
msgstr "nom repo"
-#: ../yumcommands.py:934
+#: ../yumcommands.py:958
msgid "Display a helpful usage message"
msgstr "Mostra un missatge d'ajuda d'ús"
-#: ../yumcommands.py:968
+#: ../yumcommands.py:992
#, python-format
msgid "No help available for %s"
msgstr "No hi ha ajuda disponible per a %s"
-#: ../yumcommands.py:973
+#: ../yumcommands.py:997
msgid ""
"\n"
"\n"
@@ -1276,7 +1342,7 @@ msgstr ""
"\n"
"àlies: "
-#: ../yumcommands.py:975
+#: ../yumcommands.py:999
msgid ""
"\n"
"\n"
@@ -1286,26 +1352,36 @@ msgstr ""
"\n"
"àlies: "
-#: ../yumcommands.py:1003
+#: ../yumcommands.py:1027
msgid "Setting up Reinstall Process"
msgstr "S'està preparant el procés de reinstal·lació"
-#: ../yumcommands.py:1012
-msgid "Package(s) to reinstall"
-msgstr "Paquets a reinstal·lar"
-
-#: ../yumcommands.py:1019
+#: ../yumcommands.py:1035
msgid "reinstall a package"
msgstr "reinstal·la un paquet"
-#: ../yumcommands.py:1037
+#: ../yumcommands.py:1053
msgid "Setting up Downgrade Process"
msgstr "S'està preparant el procés de desactualització"
-#: ../yumcommands.py:1044
+#: ../yumcommands.py:1060
msgid "downgrade a package"
msgstr "desactualitza un paquet"
+#: ../yumcommands.py:1074
+msgid "Display a version for the machine and/or available repos."
+msgstr "Mostra una versió per a la màquina i/o repositoris disponibles"
+
+#: ../yumcommands.py:1101
+#,
+msgid "Installed:"
+msgstr "Instal·lat:"
+
+#: ../yumcommands.py:1110
+#,
+msgid "Available:"
+msgstr "Disponible:"
+
#: ../yummain.py:42
msgid ""
"\n"
@@ -1326,80 +1402,87 @@ msgstr ""
"\n"
"S'està sortint en trobar la canonada trencada"
-#: ../yummain.py:126
+#: ../yummain.py:50
+#, python-format
+msgid ""
+"\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"\n"
+"%s"
+
+#: ../yummain.py:128
msgid "Running"
msgstr "S'està executant"
-#: ../yummain.py:127
+#: ../yummain.py:129
msgid "Sleeping"
msgstr "Està dormint"
-#: ../yummain.py:128
+#: ../yummain.py:130
msgid "Uninteruptable"
msgstr "Ininterrumpible"
-#: ../yummain.py:129
+#: ../yummain.py:131
msgid "Zombie"
msgstr "Zombi"
-#: ../yummain.py:130
+#: ../yummain.py:132
msgid "Traced/Stopped"
msgstr "Traçat/aturat"
-#: ../yummain.py:131
-msgid "Unknown"
-msgstr "Desconegut"
-
-#: ../yummain.py:135
+#: ../yummain.py:137
msgid " The other application is: PackageKit"
msgstr " L'altre aplicatiu és: PackageKit"
-#: ../yummain.py:137
+#: ../yummain.py:139
#, python-format
msgid " The other application is: %s"
msgstr " L'altre aplicatiu és: %s"
-#: ../yummain.py:140
+#: ../yummain.py:142
#, python-format
msgid " Memory : %5s RSS (%5sB VSZ)"
msgstr " Memòria : %5s RSS (%5sB VSZ)"
-#: ../yummain.py:144
+#: ../yummain.py:146
#, python-format
msgid " Started: %s - %s ago"
msgstr " Iniciat: fa %s-%s"
-#: ../yummain.py:146
+#: ../yummain.py:148
#, python-format
msgid " State : %s, pid: %d"
msgstr " Estat : %s, pid: %d"
-#: ../yummain.py:171
-msgid "Another app is currently holding the yum lock; waiting for it to exit..."
-msgstr "Alguna altra aplicació té el bloqueig del yum; s'està esperant a que surti..."
+#: ../yummain.py:173
+msgid ""
+"Another app is currently holding the yum lock; waiting for it to exit..."
+msgstr ""
+"Alguna altra aplicació té el bloqueig del yum; s'està esperant a que surti..."
-#: ../yummain.py:199
-#: ../yummain.py:238
+#: ../yummain.py:201 ../yummain.py:240
#, python-format
msgid "Error: %s"
msgstr "Error: %s"
-#: ../yummain.py:209
-#: ../yummain.py:250
+#: ../yummain.py:211 ../yummain.py:253
#, python-format
msgid "Unknown Error(s): Exit Code: %d:"
msgstr "Errors desconeguts: Codi de sortida: %d:"
#. Depsolve stage
-#: ../yummain.py:216
+#: ../yummain.py:218
msgid "Resolving Dependencies"
msgstr "S'estan resolent dependències"
-#: ../yummain.py:240
+#: ../yummain.py:242
msgid " You could try using --skip-broken to work around the problem"
msgstr " Hauríeu de provar utilitzant --skip-broken per evitar el problema"
-#: ../yummain.py:241
+#: ../yummain.py:243
msgid ""
" You could try running: package-cleanup --problems\n"
" package-cleanup --dupes\n"
@@ -1409,7 +1492,7 @@ msgstr ""
" package-cleanup --dupes\n"
" rpm -Va --nofiles --nodigest"
-#: ../yummain.py:256
+#: ../yummain.py:259
msgid ""
"\n"
"Dependencies Resolved"
@@ -1417,11 +1500,11 @@ msgstr ""
"\n"
"Dependències resoltes"
-#: ../yummain.py:270
+#: ../yummain.py:273
msgid "Complete!"
msgstr "Completat!"
-#: ../yummain.py:317
+#: ../yummain.py:320
msgid ""
"\n"
"\n"
@@ -1431,201 +1514,205 @@ msgstr ""
"\n"
"S'està sortint de l'ordre de l'usuari."
-#: ../yum/depsolve.py:84
+#: ../yum/depsolve.py:83
msgid "doTsSetup() will go away in a future version of Yum.\n"
msgstr "doTsSetup() desapareixerà en una futura versió de Yum.\n"
-#: ../yum/depsolve.py:99
+#: ../yum/depsolve.py:98
msgid "Setting up TransactionSets before config class is up"
-msgstr "S'està configurant TransactionSets abans que la classe de configuració estigui iniciada"
+msgstr ""
+"S'està configurant TransactionSets abans que la classe de configuració "
+"estigui iniciada"
-#: ../yum/depsolve.py:150
+#: ../yum/depsolve.py:149
#, python-format
msgid "Invalid tsflag in config file: %s"
msgstr "Tsflag invàlid en el fitxer de configuració: %s"
-#: ../yum/depsolve.py:161
+#: ../yum/depsolve.py:160
#, python-format
msgid "Searching pkgSack for dep: %s"
msgstr "S'està buscant pkgSack per a la dependència: %s"
-#: ../yum/depsolve.py:184
+#: ../yum/depsolve.py:183
#, python-format
msgid "Potential match for %s from %s"
msgstr "Coincidència potencial per a %s de %s"
-#: ../yum/depsolve.py:192
+#: ../yum/depsolve.py:191
#, python-format
msgid "Matched %s to require for %s"
msgstr "La coincidència %s es requereix per a %s"
-#: ../yum/depsolve.py:233
+#: ../yum/depsolve.py:232
#, python-format
msgid "Member: %s"
msgstr "Membre: %s"
-#: ../yum/depsolve.py:247
-#: ../yum/depsolve.py:739
+#: ../yum/depsolve.py:246 ../yum/depsolve.py:756
#, python-format
msgid "%s converted to install"
msgstr "%s convertits per a instal·lar"
-#: ../yum/depsolve.py:254
+#: ../yum/depsolve.py:253
#, python-format
msgid "Adding Package %s in mode %s"
msgstr "S'està afegint el paquet %s en mode %s"
-#: ../yum/depsolve.py:264
+#: ../yum/depsolve.py:263
#, python-format
msgid "Removing Package %s"
-msgstr "S'està esborrant el paquet %s"
+msgstr "S'està suprimint el paquet %s"
-#: ../yum/depsolve.py:275
+#: ../yum/depsolve.py:285
#, python-format
msgid "%s requires: %s"
msgstr "%s requereix: %s"
-#: ../yum/depsolve.py:333
+#: ../yum/depsolve.py:343
msgid "Needed Require has already been looked up, cheating"
-msgstr "El requeriment necessari ja s'ha buscat anteriorment, s'estan fent trampes"
+msgstr ""
+"El requeriment necessari ja s'ha buscat anteriorment, s'estan fent trampes"
-#: ../yum/depsolve.py:343
+#: ../yum/depsolve.py:353
#, python-format
msgid "Needed Require is not a package name. Looking up: %s"
msgstr "El requeriment necessari no és un nom de paquet. S'està buscant: %s"
-#: ../yum/depsolve.py:350
+#: ../yum/depsolve.py:360
#, python-format
msgid "Potential Provider: %s"
msgstr "Proveïdor potencial: %s"
-#: ../yum/depsolve.py:373
+#: ../yum/depsolve.py:383
#, python-format
msgid "Mode is %s for provider of %s: %s"
msgstr "El mode és %s per al proveïdor de %s: %s"
-#: ../yum/depsolve.py:377
+#: ../yum/depsolve.py:387
#, python-format
msgid "Mode for pkg providing %s: %s"
msgstr "Mode per al paquet que proporciona %s: %s"
-#: ../yum/depsolve.py:381
+#: ../yum/depsolve.py:391
#, python-format
msgid "TSINFO: %s package requiring %s marked as erase"
-msgstr "TSINFO: el paquet %s requereix %s marcat per a esborrar"
+msgstr "TSINFO: el paquet %s requereix %s marcat per a suprimir"
-#: ../yum/depsolve.py:394
+#: ../yum/depsolve.py:404
#, python-format
msgid "TSINFO: Obsoleting %s with %s to resolve dep."
-msgstr "TSINFO: S'està marcant com a obsolet %s amb %s per resoldre dependències."
+msgstr ""
+"TSINFO: S'està marcant com a obsolet %s amb %s per resoldre dependències."
-#: ../yum/depsolve.py:397
+#: ../yum/depsolve.py:407
#, python-format
msgid "TSINFO: Updating %s to resolve dep."
msgstr "TSINFO: S'està actualitzant %s per a resoldre dependències."
-#: ../yum/depsolve.py:405
+#: ../yum/depsolve.py:415
#, python-format
msgid "Cannot find an update path for dep for: %s"
msgstr "No es pot trobar un camí d'actualització de dependències per a: %s"
-#: ../yum/depsolve.py:415
+#: ../yum/depsolve.py:425
#, python-format
msgid "Unresolvable requirement %s for %s"
msgstr "No es pot resoldre el requeriment %s per a %s"
-#: ../yum/depsolve.py:438
+#: ../yum/depsolve.py:448
#, python-format
msgid "Quick matched %s to require for %s"
msgstr "La coincidència %s es requereix per a %s"
#. is it already installed?
-#: ../yum/depsolve.py:480
+#: ../yum/depsolve.py:490
#, python-format
msgid "%s is in providing packages but it is already installed, removing."
-msgstr "%s es troba en els paquets proporcionats però ja es troba instal·lat, s'està esborrant."
+msgstr ""
+"%s es troba en els paquets proporcionats però ja es troba instal·lat, s'està "
+"suprimint."
-#: ../yum/depsolve.py:496
+#: ../yum/depsolve.py:506
#, python-format
msgid "Potential resolving package %s has newer instance in ts."
-msgstr "El paquet potencial que resol dependències %s té una instància nova a ts"
+msgstr ""
+"El paquet potencial que resol dependències %s té una instància nova a ts"
-#: ../yum/depsolve.py:507
+#: ../yum/depsolve.py:517
#, python-format
msgid "Potential resolving package %s has newer instance installed."
-msgstr "El paquet potencial que resol dependències %s té una nova instància insta·lada."
+msgstr ""
+"El paquet potencial que resol dependències %s té una nova instància "
+"insta·lada."
-#: ../yum/depsolve.py:515
-#: ../yum/depsolve.py:564
+#: ../yum/depsolve.py:525 ../yum/depsolve.py:571
#, python-format
msgid "Missing Dependency: %s is needed by package %s"
msgstr "Manca una dependència: %s es necessita per al paquet %s"
-#: ../yum/depsolve.py:528
+#: ../yum/depsolve.py:538
#, python-format
msgid "%s already in ts, skipping this one"
msgstr "%s ja es troba en ts, s'està ometent"
-#: ../yum/depsolve.py:574
+#: ../yum/depsolve.py:581
#, python-format
msgid "TSINFO: Marking %s as update for %s"
msgstr "TSINFO: S'està marcant %s com a actualització per a %s"
-#: ../yum/depsolve.py:582
+#: ../yum/depsolve.py:589
#, python-format
msgid "TSINFO: Marking %s as install for %s"
msgstr "TSINFO: S'està marcant %s com a instal·lació per a %s"
-#: ../yum/depsolve.py:675
-#: ../yum/depsolve.py:757
+#: ../yum/depsolve.py:692 ../yum/depsolve.py:774
msgid "Success - empty transaction"
msgstr "Èxit - transacció buida"
-#: ../yum/depsolve.py:714
-#: ../yum/depsolve.py:729
+#: ../yum/depsolve.py:731 ../yum/depsolve.py:746
msgid "Restarting Loop"
msgstr "S'està recomençant el bucle"
-#: ../yum/depsolve.py:745
+#: ../yum/depsolve.py:762
msgid "Dependency Process ending"
msgstr "Està acabant el procés de dependències"
-#: ../yum/depsolve.py:751
+#: ../yum/depsolve.py:768
#, python-format
msgid "%s from %s has depsolving problems"
msgstr "%s de %s té problemes resolent dependències"
-#: ../yum/depsolve.py:758
+#: ../yum/depsolve.py:775
msgid "Success - deps resolved"
msgstr "Èxit - dependències resoltes"
-#: ../yum/depsolve.py:772
+#: ../yum/depsolve.py:789
#, python-format
msgid "Checking deps for %s"
msgstr "S'estan comprobant les dependències per a %s"
-#: ../yum/depsolve.py:855
+#: ../yum/depsolve.py:872
#, python-format
msgid "looking for %s as a requirement of %s"
msgstr "s'està buscant %s com a requeriment de %s"
-#: ../yum/depsolve.py:997
+#: ../yum/depsolve.py:1014
#, python-format
msgid "Running compare_providers() for %s"
msgstr "S'està executant compare_providers() per a %s"
-#: ../yum/depsolve.py:1025
-#: ../yum/depsolve.py:1031
+#: ../yum/depsolve.py:1048 ../yum/depsolve.py:1054
#, python-format
msgid "better arch in po %s"
msgstr "millor arq en el po %s"
-#: ../yum/depsolve.py:1092
+#: ../yum/depsolve.py:1140
#, python-format
msgid "%s obsoletes %s"
msgstr "%s fa obsolet %s"
-#: ../yum/depsolve.py:1108
+#: ../yum/depsolve.py:1152
#, python-format
msgid ""
"archdist compared %s to %s on %s\n"
@@ -1634,112 +1721,121 @@ msgstr ""
"archdist ha comparat %s amb %s a %s\n"
" Ha guanyat: %s"
-#: ../yum/depsolve.py:1115
+#: ../yum/depsolve.py:1159
#, python-format
msgid "common sourcerpm %s and %s"
msgstr "rpm font comú %s i %s"
-#: ../yum/depsolve.py:1121
+#: ../yum/depsolve.py:1165
#, python-format
msgid "common prefix of %s between %s and %s"
msgstr "prefix comú de %s entre %s i %s"
-#: ../yum/depsolve.py:1129
+#: ../yum/depsolve.py:1173
#, python-format
msgid "Best Order: %s"
msgstr "Millor ordre: %s"
-#: ../yum/__init__.py:158
+#: ../yum/__init__.py:180
msgid "doConfigSetup() will go away in a future version of Yum.\n"
msgstr "doConfigsetup() desapareixerà en una futura versió de Yum.\n"
-#: ../yum/__init__.py:367
+#: ../yum/__init__.py:401
#, python-format
msgid "Repository %r is missing name in configuration, using id"
msgstr "Falta el nom del repositori %r en la configuració, s'utilitzarà l'id"
-#: ../yum/__init__.py:405
+#: ../yum/__init__.py:439
msgid "plugins already initialised"
msgstr "els connectors ja estan inicialitzats"
-#: ../yum/__init__.py:412
+#: ../yum/__init__.py:446
msgid "doRpmDBSetup() will go away in a future version of Yum.\n"
msgstr "doRpmDBSetup() desapareixerà en una futura versió de Yum.\n"
-#: ../yum/__init__.py:423
+#: ../yum/__init__.py:457
msgid "Reading Local RPMDB"
msgstr "S'està llegint un RPMDB local"
-#: ../yum/__init__.py:441
+#: ../yum/__init__.py:478
msgid "doRepoSetup() will go away in a future version of Yum.\n"
msgstr "doRepoSetup() desapareixerà en una futura versió de Yum.\n"
-#: ../yum/__init__.py:461
+#: ../yum/__init__.py:498
msgid "doSackSetup() will go away in a future version of Yum.\n"
msgstr "doSackSetup() desapareixerà en una versió futura de Yum.\n"
-#: ../yum/__init__.py:478
+#: ../yum/__init__.py:528
msgid "Setting up Package Sacks"
msgstr "S'estan configurant els sacs de paquets"
-#: ../yum/__init__.py:521
+#: ../yum/__init__.py:573
#, python-format
msgid "repo object for repo %s lacks a _resetSack method\n"
msgstr "l'objecte repositori per al repositori %s no té un mètode _resetSack\n"
-#: ../yum/__init__.py:522
+#: ../yum/__init__.py:574
msgid "therefore this repo cannot be reset.\n"
msgstr "Aquest repositori no es pot reiniciar.\n"
-#: ../yum/__init__.py:527
+#: ../yum/__init__.py:579
msgid "doUpdateSetup() will go away in a future version of Yum.\n"
msgstr "doUpdateSetup() desapareixerà en una futura versió de Yum.\n"
-#: ../yum/__init__.py:539
+#: ../yum/__init__.py:591
msgid "Building updates object"
msgstr "S'està construint l'objecte d'actualitzacions"
-#: ../yum/__init__.py:570
+#: ../yum/__init__.py:626
msgid "doGroupSetup() will go away in a future version of Yum.\n"
msgstr "doGroupSetup() desapareixerà en una futura versió de Yum.\n"
-#: ../yum/__init__.py:595
+#: ../yum/__init__.py:651
msgid "Getting group metadata"
msgstr "S'estan obtenint les metadades del grup"
-#: ../yum/__init__.py:621
+#: ../yum/__init__.py:677
#, python-format
msgid "Adding group file from repository: %s"
msgstr "S'està afegint el fitxer del grup des del repositori: %s"
-#: ../yum/__init__.py:630
+#: ../yum/__init__.py:686
#, python-format
msgid "Failed to add groups file for repository: %s - %s"
msgstr "No s'ha pogut afegir el fitxer dels grups des del repositori: %s - %s"
-#: ../yum/__init__.py:636
+#: ../yum/__init__.py:692
msgid "No Groups Available in any repository"
msgstr "No hi ha cap grup disponible en cap repositori"
-#: ../yum/__init__.py:686
+#: ../yum/__init__.py:742
msgid "Importing additional filelist information"
msgstr "S'està important informació adicional de la llista de fitxers"
-#: ../yum/__init__.py:695
-msgid "There are unfinished transactions remaining. You might consider running yum-complete-transaction first to finish them."
-msgstr "Encara hi ha transaccions sense acabar. Hauríeu de considerar executar yum-complete-transaction abans per acabar-les."
+#: ../yum/__init__.py:756
+#, python-format
+msgid "The program %s%s%s is found in the yum-utils package."
+msgstr "El programa %s%s%s es troba en el paquet yum-utils."
+
+#: ../yum/__init__.py:764
+msgid ""
+"There are unfinished transactions remaining. You might consider running yum-"
+"complete-transaction first to finish them."
+msgstr ""
+"Encara hi ha transaccions sense acabar. Hauríeu de considerar executar yum-"
+"complete-transaction abans per acabar-les."
-#: ../yum/__init__.py:761
+#: ../yum/__init__.py:832
#, python-format
msgid "Skip-broken round %i"
msgstr "Intent %i d'omissió dels paquets trencats"
-#: ../yum/__init__.py:813
+#: ../yum/__init__.py:884
#, python-format
msgid "Skip-broken took %i rounds "
msgstr "L'omissió dels paquets trencats ha necessitat %i intents"
-#: ../yum/__init__.py:814
+#: ../yum/__init__.py:885
msgid ""
"\n"
"Packages skipped because of dependency problems:"
@@ -1747,89 +1843,74 @@ msgstr ""
"\n"
"Paquets omesos degut a problemes de dependències:"
-#: ../yum/__init__.py:818
+#: ../yum/__init__.py:889
#, python-format
msgid " %s from %s"
msgstr " %s des de %s"
-#: ../yum/__init__.py:958
-msgid "Warning: scriptlet or other non-fatal errors occurred during transaction."
-msgstr "Avís: ha fallat l'scriptlet o s'han produït altre tipus d'errors no fatals durant la transacció."
+#: ../yum/__init__.py:1027
+msgid ""
+"Warning: scriptlet or other non-fatal errors occurred during transaction."
+msgstr ""
+"Avís: ha fallat l'scriptlet o s'han produït altre tipus d'errors no fatals "
+"durant la transacció."
-#: ../yum/__init__.py:973
+#: ../yum/__init__.py:1042
#, python-format
msgid "Failed to remove transaction file %s"
-msgstr "No s'ha pogut esborrar el fitxer de transaccions %s"
+msgstr "No s'ha pogut suprimir el fitxer de transaccions %s"
-#: ../yum/__init__.py:1015
+#. maybe a file log here, too
+#. but raising an exception is not going to do any good
+#: ../yum/__init__.py:1071
#, python-format
-msgid "excluding for cost: %s from %s"
-msgstr "s'està excloent per cost: %s de %s"
-
-#: ../yum/__init__.py:1046
-msgid "Excluding Packages in global exclude list"
-msgstr "S'estan excloent paquets en la llista global d'exclusió"
+msgid "%s was supposed to be installed but is not!"
+msgstr "S'havia d'instal·lar %s però no s'ha realitzat!"
-#: ../yum/__init__.py:1048
+#. maybe a file log here, too
+#. but raising an exception is not going to do any good
+#: ../yum/__init__.py:1110
#, python-format
-msgid "Excluding Packages from %s"
-msgstr "S'estan excloent paquets de %s"
-
-#: ../yum/__init__.py:1077
-#, python-format
-msgid "Reducing %s to included packages only"
-msgstr "S'està reduint %s únicament a paquets inclosos."
-
-#: ../yum/__init__.py:1083
-#, python-format
-msgid "Keeping included package %s"
-msgstr "S'està mantenint el paquet inclòs %s"
-
-#: ../yum/__init__.py:1089
-#, python-format
-msgid "Removing unmatched package %s"
-msgstr "S'està esborrant el paquet sense coincidències %s"
-
-#: ../yum/__init__.py:1092
-msgid "Finished"
-msgstr "Finalitzat"
+msgid "%s was supposed to be removed but is not!"
+msgstr "S'havia de suprimir %s però no s'ha realitzat!"
#. Whoa. What the heck happened?
-#: ../yum/__init__.py:1122
+#: ../yum/__init__.py:1225
#, python-format
msgid "Unable to check if PID %s is active"
msgstr "No s'ha pogut comprovar si el PID %s es troba actiu"
#. Another copy seems to be running.
-#: ../yum/__init__.py:1126
+#: ../yum/__init__.py:1229
#, python-format
msgid "Existing lock %s: another copy is running as pid %s."
msgstr "Bloqueig existent %s: una altra còpia s'està executant amb pid %s."
-#: ../yum/__init__.py:1196
+#: ../yum/__init__.py:1306
msgid "Package does not match intended download"
msgstr "El paquet no coincideix amb la descàrrega intentada"
-#: ../yum/__init__.py:1211
+#: ../yum/__init__.py:1321
msgid "Could not perform checksum"
msgstr "No s'ha pogut realitzar la suma de verificació"
-#: ../yum/__init__.py:1214
+#: ../yum/__init__.py:1324
msgid "Package does not match checksum"
msgstr "No coincideix la suma de verificació del paquet"
-#: ../yum/__init__.py:1257
+#: ../yum/__init__.py:1366
#, python-format
msgid "package fails checksum but caching is enabled for %s"
-msgstr "la suma de verificació del paquet falla però l'ús de memòria cau està habilitat per a %s"
+msgstr ""
+"la suma de verificació del paquet falla però l'ús de memòria cau està "
+"habilitat per a %s"
-#: ../yum/__init__.py:1260
-#: ../yum/__init__.py:1289
+#: ../yum/__init__.py:1369 ../yum/__init__.py:1398
#, python-format
msgid "using local copy of %s"
msgstr "s'està utilitzant la còpia local de %s"
-#: ../yum/__init__.py:1301
+#: ../yum/__init__.py:1410
#, python-format
msgid ""
"Insufficient space in download directory %s\n"
@@ -1840,441 +1921,462 @@ msgstr ""
" * lliure %s\n"
" * necessari %s"
-#: ../yum/__init__.py:1348
+#: ../yum/__init__.py:1459
msgid "Header is not complete."
msgstr "La capçalera no està completa."
-#: ../yum/__init__.py:1385
+#: ../yum/__init__.py:1496
#, python-format
-msgid "Header not in local cache and caching-only mode enabled. Cannot download %s"
-msgstr "La capçalera no es troba en la memòria cau local i està habilitat el mode de només memòria cau. No es pot descarregar %s"
+msgid ""
+"Header not in local cache and caching-only mode enabled. Cannot download %s"
+msgstr ""
+"La capçalera no es troba en la memòria cau local i està habilitat el mode de "
+"només memòria cau. No es pot baixar %s"
-#: ../yum/__init__.py:1440
+#: ../yum/__init__.py:1551
#, python-format
msgid "Public key for %s is not installed"
msgstr "La clau pública per a %s no està instal·lada"
-#: ../yum/__init__.py:1444
+#: ../yum/__init__.py:1555
#, python-format
msgid "Problem opening package %s"
msgstr "Hi ha hagut un problema obrint el paquet %s"
-#: ../yum/__init__.py:1452
+#: ../yum/__init__.py:1563
#, python-format
msgid "Public key for %s is not trusted"
msgstr "La clau pública per a %s no és de confiança"
-#: ../yum/__init__.py:1456
+#: ../yum/__init__.py:1567
#, python-format
msgid "Package %s is not signed"
msgstr "El paquet %s no està signat"
-#: ../yum/__init__.py:1494
+#: ../yum/__init__.py:1605
#, python-format
msgid "Cannot remove %s"
-msgstr "No es pot esborrar %s"
+msgstr "No es pot suprimir %s"
-#: ../yum/__init__.py:1498
+#: ../yum/__init__.py:1609
#, python-format
msgid "%s removed"
-msgstr "S'ha esborrat %s"
+msgstr "S'ha suprimit %s"
-#: ../yum/__init__.py:1534
+#: ../yum/__init__.py:1645
#, python-format
msgid "Cannot remove %s file %s"
-msgstr "No es pot esborrar %s fitxer %s"
+msgstr "No es pot suprimir %s fitxer %s"
-#: ../yum/__init__.py:1538
+#: ../yum/__init__.py:1649
#, python-format
msgid "%s file %s removed"
-msgstr "%s fitxer %s esborrat"
+msgstr "%s fitxer %s suprimit"
-#: ../yum/__init__.py:1540
+#: ../yum/__init__.py:1651
#, python-format
msgid "%d %s files removed"
-msgstr "%d %s fitxers esborrats"
+msgstr "%d %s fitxers suprimits"
-#: ../yum/__init__.py:1609
+#: ../yum/__init__.py:1720
#, python-format
msgid "More than one identical match in sack for %s"
msgstr "Hi ha més d'una coincidència idèntica en el sac per a %s"
-#: ../yum/__init__.py:1615
+#: ../yum/__init__.py:1726
#, python-format
msgid "Nothing matches %s.%s %s:%s-%s from update"
msgstr "No hi ha coincidències %s.%s-%s:%s-%s de l'actualització"
-#: ../yum/__init__.py:1833
-msgid "searchPackages() will go away in a future version of Yum. Use searchGenerator() instead. \n"
-msgstr "searchPackages() desapareixerà en una futura versió de Yum. Useu searchGenerator(). \n"
+#: ../yum/__init__.py:1959
+msgid ""
+"searchPackages() will go away in a future version of "
+"Yum. Use searchGenerator() instead. \n"
+msgstr ""
+"searchPackages() desapareixerà en una futura versió de "
+"Yum. Useu searchGenerator(). \n"
-#: ../yum/__init__.py:1875
+#: ../yum/__init__.py:2001
#, python-format
msgid "Searching %d packages"
msgstr "S'estan buscant %d paquets"
-#: ../yum/__init__.py:1879
+#: ../yum/__init__.py:2005
#, python-format
msgid "searching package %s"
msgstr "s'està buscant el paquet %s"
-#: ../yum/__init__.py:1891
+#: ../yum/__init__.py:2017
msgid "searching in file entries"
msgstr "s'està buscant en les entrades de fitxers"
-#: ../yum/__init__.py:1898
+#: ../yum/__init__.py:2024
msgid "searching in provides entries"
msgstr "s'està buscant en les entrades proporcionades"
-#: ../yum/__init__.py:1931
+#: ../yum/__init__.py:2057
#, python-format
msgid "Provides-match: %s"
msgstr "Proporciona-coincideix: %s"
-#: ../yum/__init__.py:1980
+#: ../yum/__init__.py:2106
msgid "No group data available for configured repositories"
msgstr "No hi ha dades de grup disponibles en cap dels repositoris configurats"
-#: ../yum/__init__.py:2011
-#: ../yum/__init__.py:2030
-#: ../yum/__init__.py:2061
-#: ../yum/__init__.py:2067
-#: ../yum/__init__.py:2146
-#: ../yum/__init__.py:2150
-#: ../yum/__init__.py:2447
+#: ../yum/__init__.py:2137 ../yum/__init__.py:2156 ../yum/__init__.py:2187
+#: ../yum/__init__.py:2193 ../yum/__init__.py:2272 ../yum/__init__.py:2276
+#: ../yum/__init__.py:2586
#, python-format
msgid "No Group named %s exists"
msgstr "No existeix cap grup anomenat %s"
-#: ../yum/__init__.py:2042
-#: ../yum/__init__.py:2163
+#: ../yum/__init__.py:2168 ../yum/__init__.py:2289
#, python-format
msgid "package %s was not marked in group %s"
msgstr "el paquet %s no estava marcat en el grup %s"
-#: ../yum/__init__.py:2089
+#: ../yum/__init__.py:2215
#, python-format
msgid "Adding package %s from group %s"
msgstr "S'està afegint el paquet %s del grup %s"
-#: ../yum/__init__.py:2093
+#: ../yum/__init__.py:2219
#, python-format
msgid "No package named %s available to be installed"
msgstr "No hi ha cap paquet anomenat %s disponible per a ser instal·lat"
-#: ../yum/__init__.py:2190
+#: ../yum/__init__.py:2316
#, python-format
msgid "Package tuple %s could not be found in packagesack"
msgstr "No s'ha pogut trobar la tupla de paquets %s al sac de paquets"
-#: ../yum/__init__.py:2205
-msgid "getInstalledPackageObject() will go away, use self.rpmdb.searchPkgTuple().\n"
-msgstr "getInstalledPackageObject() desapareixarà, useu self.rpmdb.searchPkgTuple().\n"
+#: ../yum/__init__.py:2330
+msgid ""
+"getInstalledPackageObject() will go away, use self.rpmdb.searchPkgTuple().\n"
+msgstr ""
+"getInstalledPackageObject() desapareixarà, useu self.rpmdb.searchPkgTuple"
+"().\n"
-#: ../yum/__init__.py:2261
-#: ../yum/__init__.py:2305
+#: ../yum/__init__.py:2386 ../yum/__init__.py:2436
msgid "Invalid version flag"
msgstr "Marcador de versió invàlid"
-#: ../yum/__init__.py:2276
-#: ../yum/__init__.py:2280
+#: ../yum/__init__.py:2406 ../yum/__init__.py:2411
#, python-format
msgid "No Package found for %s"
msgstr "No s'ha trobat cap paquet per a %s"
-#: ../yum/__init__.py:2480
+#: ../yum/__init__.py:2627
msgid "Package Object was not a package object instance"
msgstr "L'objecte paquet no era una instància d'objecte paquet"
-#: ../yum/__init__.py:2484
+#: ../yum/__init__.py:2631
msgid "Nothing specified to install"
msgstr "No hi ha res especificat per a instal·lar"
-#: ../yum/__init__.py:2500
-#: ../yum/__init__.py:3127
+#: ../yum/__init__.py:2647 ../yum/__init__.py:3411
#, python-format
msgid "Checking for virtual provide or file-provide for %s"
-msgstr "S'està verificant si hi ha un proveïdor virtual o un fitxer proveïdor per a %s"
+msgstr ""
+"S'està verificant si hi ha un proveïdor virtual o un fitxer proveïdor per a %"
+"s"
-#: ../yum/__init__.py:2506
-#: ../yum/__init__.py:2783
-#: ../yum/__init__.py:2943
-#: ../yum/__init__.py:3133
+#: ../yum/__init__.py:2653 ../yum/__init__.py:2960 ../yum/__init__.py:3127
+#: ../yum/__init__.py:3417
#, python-format
msgid "No Match for argument: %s"
msgstr "No hi ha cap coincidència per a l'argument: %s"
-#: ../yum/__init__.py:2580
+#: ../yum/__init__.py:2729
#, python-format
msgid "Package %s installed and not available"
msgstr "El paquet %s es troba instal·lat però no és disponible"
-#: ../yum/__init__.py:2583
+#: ../yum/__init__.py:2732
msgid "No package(s) available to install"
msgstr "No hi ha cap paquet disponible per a instal·lar"
-#: ../yum/__init__.py:2595
+#: ../yum/__init__.py:2744
#, python-format
msgid "Package: %s - already in transaction set"
msgstr "El paquet: %s - ja està en la transacció"
-#: ../yum/__init__.py:2610
+#: ../yum/__init__.py:2770
+#, python-format
+msgid "Package %s is obsoleted by %s which is already installed"
+msgstr "El paquet %s és obsolet degut a %s, que ja està instal·lat"
+
+#: ../yum/__init__.py:2773
#, python-format
msgid "Package %s is obsoleted by %s, trying to install %s instead"
-msgstr "El paquet %s és obsolet degut a %s, es provarà d'instal·lar %s"
+msgstr "El paquet %s és obsolet degut a %s, es provarà d'instal·lar %s en el seu lloc"
-#: ../yum/__init__.py:2618
+#: ../yum/__init__.py:2781
#, python-format
msgid "Package %s already installed and latest version"
msgstr "El paquet %s ja es troba instal·lat i en l'última versió."
-#: ../yum/__init__.py:2632
+#: ../yum/__init__.py:2795
#, python-format
msgid "Package matching %s already installed. Checking for update."
-msgstr "El paquet coincident %s ja es troba instal·lat. S'està buscant una actualització."
+msgstr ""
+"El paquet coincident %s ja es troba instal·lat. S'està buscant una "
+"actualització."
#. update everything (the easy case)
-#: ../yum/__init__.py:2718
+#: ../yum/__init__.py:2889
msgid "Updating Everything"
msgstr "S'està actualitzant tot"
-#: ../yum/__init__.py:2736
-#: ../yum/__init__.py:2845
-#: ../yum/__init__.py:2866
-#: ../yum/__init__.py:2892
+#: ../yum/__init__.py:2910 ../yum/__init__.py:3025 ../yum/__init__.py:3054
+#: ../yum/__init__.py:3081
#, python-format
msgid "Not Updating Package that is already obsoleted: %s.%s %s:%s-%s"
msgstr "No s'actualitzarà el paquet obsolet: %s.%s %s:%s-%s"
-#: ../yum/__init__.py:2771
-#: ../yum/__init__.py:2940
+#: ../yum/__init__.py:2945 ../yum/__init__.py:3124
#, python-format
msgid "%s"
msgstr "%s"
-#: ../yum/__init__.py:2836
+#: ../yum/__init__.py:3016
#, python-format
msgid "Package is already obsoleted: %s.%s %s:%s-%s"
msgstr "El paquet és obsolet: %s.%s %s:%s-%s"
-#: ../yum/__init__.py:2869
-#: ../yum/__init__.py:2895
+#: ../yum/__init__.py:3049
+#, python-format
+msgid "Not Updating Package that is obsoleted: %s"
+msgstr "No s'actualitzarà el paquet obsolet: %s"
+
+#: ../yum/__init__.py:3058 ../yum/__init__.py:3085
#, python-format
msgid "Not Updating Package that is already updated: %s.%s %s:%s-%s"
msgstr "No s'actualitzarà el paquet actualitzat: %s.%s %s:%s-%s"
-#: ../yum/__init__.py:2956
+#: ../yum/__init__.py:3140
msgid "No package matched to remove"
-msgstr "No hi ha cap paquet coincident per a esborrar"
+msgstr "No hi ha cap paquet coincident per a suprimir"
-#: ../yum/__init__.py:2990
+#: ../yum/__init__.py:3173 ../yum/__init__.py:3277 ../yum/__init__.py:3366
#, python-format
msgid "Cannot open file: %s. Skipping."
msgstr "No es pot obrir el fitxer %s. S'ometrà."
-#: ../yum/__init__.py:2993
+#: ../yum/__init__.py:3176 ../yum/__init__.py:3280 ../yum/__init__.py:3369
#, python-format
msgid "Examining %s: %s"
msgstr "S'està examinant %s: %s"
-#: ../yum/__init__.py:3001
+#: ../yum/__init__.py:3184 ../yum/__init__.py:3283 ../yum/__init__.py:3372
#, python-format
msgid "Cannot add package %s to transaction. Not a compatible architecture: %s"
-msgstr "No s'ha pogut afegir el paquet %s a la transacció. No és una arquitectura compatible: %s"
+msgstr ""
+"No s'ha pogut afegir el paquet %s a la transacció. No és una arquitectura "
+"compatible: %s"
-#: ../yum/__init__.py:3009
+#: ../yum/__init__.py:3192
#, python-format
-msgid "Package %s not installed, cannot update it. Run yum install to install it instead."
-msgstr "El paquet %s no està instal·lat; no es pot actualitzar. Executeu «yum install» per a instal·lar-lo."
+msgid ""
+"Package %s not installed, cannot update it. Run yum install to install it "
+"instead."
+msgstr ""
+"El paquet %s no està instal·lat; no es pot actualitzar. Executeu «yum "
+"install» per a instal·lar-lo."
-#: ../yum/__init__.py:3044
+#: ../yum/__init__.py:3227 ../yum/__init__.py:3294 ../yum/__init__.py:3383
#, python-format
msgid "Excluding %s"
msgstr "S'està excloent %s"
-#: ../yum/__init__.py:3049
+#: ../yum/__init__.py:3232
#, python-format
msgid "Marking %s to be installed"
msgstr "S'està marcant %s per a ser instal·lat"
-#: ../yum/__init__.py:3055
+#: ../yum/__init__.py:3238
#, python-format
msgid "Marking %s as an update to %s"
msgstr "S'està marcant %s com a actualització de %s"
-#: ../yum/__init__.py:3062
+#: ../yum/__init__.py:3245
#, python-format
msgid "%s: does not update installed package."
msgstr "%s no actualitza el paquet instal·lat."
-#: ../yum/__init__.py:3077
+#: ../yum/__init__.py:3313
msgid "Problem in reinstall: no package matched to remove"
-msgstr "Hi ha un problema en reinstal·lar: no hi ha cap paquet marcat per a esborrar"
+msgstr ""
+"Hi ha un problema en reinstal·lar: no hi ha cap paquet marcat per a suprimir"
-#: ../yum/__init__.py:3089
-#: ../yum/__init__.py:3160
+#: ../yum/__init__.py:3326 ../yum/__init__.py:3444
#, python-format
msgid "Package %s is allowed multiple installs, skipping"
msgstr "El paquet %s permet múltiples instal·lacions, s'està ometent"
-#: ../yum/__init__.py:3098
-msgid "Problem in reinstall: no package matched to install"
-msgstr "Hi ha un problema en reinstal·lar: no hi ha cap paquet marcat per a instal·lar"
+#: ../yum/__init__.py:3347
+#, python-format
+msgid "Problem in reinstall: no package %s matched to install"
+msgstr ""
+"Hi ha un problema en reinstal·lar: no hi ha cap paquet %s marcat per a "
+"instal·lar"
-#: ../yum/__init__.py:3152
+#: ../yum/__init__.py:3436
msgid "No package(s) available to downgrade"
msgstr "No hi ha cap paquet disponible per a desactualitzar"
-#: ../yum/__init__.py:3183
+#: ../yum/__init__.py:3480
#, python-format
msgid "No Match for available package: %s"
msgstr "No hi ha cap paquet disponible que coincideixi: %s"
-#: ../yum/__init__.py:3189
+#: ../yum/__init__.py:3486
#, python-format
msgid "Only Upgrade available on package: %s"
msgstr "Només hi ha una actualització disponible per al paquet: %s"
-#: ../yum/__init__.py:3241
+#: ../yum/__init__.py:3545
#, python-format
msgid "Retrieving GPG key from %s"
msgstr "S'està recuperant la clau GPG des de %s"
-#: ../yum/__init__.py:3261
+#: ../yum/__init__.py:3565
msgid "GPG key retrieval failed: "
msgstr "La recuperació de la clau GPG ha fallat: "
-#: ../yum/__init__.py:3272
+#: ../yum/__init__.py:3576
#, python-format
msgid "GPG key parsing failed: key does not have value %s"
msgstr "L'ànalisi de la clau GPG ha fallat: la clau no té el valor %s"
-#: ../yum/__init__.py:3304
+#: ../yum/__init__.py:3608
#, python-format
msgid "GPG key at %s (0x%s) is already installed"
msgstr "La clau GPG de %s (0x%s) ja està instal·lada"
#. Try installing/updating GPG key
-#: ../yum/__init__.py:3309
-#: ../yum/__init__.py:3371
+#: ../yum/__init__.py:3613 ../yum/__init__.py:3675
#, python-format
msgid "Importing GPG key 0x%s \"%s\" from %s"
msgstr "S'està important la clau GPG 0x%s \"%s\" des de %s"
-#: ../yum/__init__.py:3326
+#: ../yum/__init__.py:3630
msgid "Not installing key"
msgstr "No s'està instal·lant la clau"
-#: ../yum/__init__.py:3332
+#: ../yum/__init__.py:3636
#, python-format
msgid "Key import failed (code %d)"
msgstr "La importació de la clau ha fallat (codi %d)"
-#: ../yum/__init__.py:3333
-#: ../yum/__init__.py:3392
+#: ../yum/__init__.py:3637 ../yum/__init__.py:3696
msgid "Key imported successfully"
msgstr "La clau s'ha importat amb èxit"
-#: ../yum/__init__.py:3338
-#: ../yum/__init__.py:3397
+#: ../yum/__init__.py:3642 ../yum/__init__.py:3701
#, python-format
msgid ""
-"The GPG keys listed for the \"%s\" repository are already installed but they are not correct for this package.\n"
+"The GPG keys listed for the \"%s\" repository are already installed but they "
+"are not correct for this package.\n"
"Check that the correct key URLs are configured for this repository."
msgstr ""
-"Les claus GPG llistades per al repositori \"%s\" ja estan instal·lades però no són correctes per a aquest paquet.\n"
-"Comproveu que les URL de claus correctes estan configurades per a aquest repositori."
+"Les claus GPG llistades per al repositori \"%s\" ja estan instal·lades però "
+"no són correctes per a aquest paquet.\n"
+"Comproveu que les URL de claus correctes estan configurades per a aquest "
+"repositori."
-#: ../yum/__init__.py:3347
+#: ../yum/__init__.py:3651
msgid "Import of key(s) didn't help, wrong key(s)?"
msgstr "La importació de claus no ha ajudat, eren claus incorrectes?"
-#: ../yum/__init__.py:3366
+#: ../yum/__init__.py:3670
#, python-format
msgid "GPG key at %s (0x%s) is already imported"
msgstr "La clau GPG a %s (0x%s) ja ha estat importada"
-#: ../yum/__init__.py:3386
+#: ../yum/__init__.py:3690
#, python-format
msgid "Not installing key for repo %s"
msgstr "No s'està instal·lant la clau per al repositori %s"
-#: ../yum/__init__.py:3391
+#: ../yum/__init__.py:3695
msgid "Key import failed"
msgstr "Ha fallat la importació de la clau"
-#: ../yum/__init__.py:3482
+#: ../yum/__init__.py:3816
msgid "Unable to find a suitable mirror."
msgstr "No s'ha pogut trobar un servidor rèplica vàlid."
-#: ../yum/__init__.py:3484
+#: ../yum/__init__.py:3818
msgid "Errors were encountered while downloading packages."
-msgstr "S'han trobat errors descarregant paquets."
+msgstr "S'han trobat errors baixant paquets."
-#: ../yum/__init__.py:3525
+#: ../yum/__init__.py:3868
#, python-format
msgid "Please report this error at %s"
msgstr "Siusplau, informeu d'aquest error al %s"
-#: ../yum/__init__.py:3549
+#: ../yum/__init__.py:3892
msgid "Test Transaction Errors: "
msgstr "Errors en la transacció de prova: "
#. Mostly copied from YumOutput._outKeyValFill()
-#: ../yum/plugins.py:204
+#: ../yum/plugins.py:202
msgid "Loaded plugins: "
msgstr "Connectors carregats: "
-#: ../yum/plugins.py:218
-#: ../yum/plugins.py:224
+#: ../yum/plugins.py:216 ../yum/plugins.py:222
#, python-format
msgid "No plugin match for: %s"
msgstr "No hi ha cap connector que coincideixi amb: %s"
-#: ../yum/plugins.py:254
+#: ../yum/plugins.py:252
#, python-format
msgid "Not loading \"%s\" plugin, as it is disabled"
msgstr "No s'està carregant el connector \"%s\", ja que està deshabilitat"
#. Give full backtrace:
-#: ../yum/plugins.py:266
+#: ../yum/plugins.py:264
#, python-format
msgid "Plugin \"%s\" can't be imported"
msgstr "No s'ha pogut importar el connector \"%s\""
-#: ../yum/plugins.py:273
+#: ../yum/plugins.py:271
#, python-format
msgid "Plugin \"%s\" doesn't specify required API version"
msgstr "El connector \"%s\" no especifica la versió de l'API requerida."
-#: ../yum/plugins.py:278
+#: ../yum/plugins.py:276
#, python-format
msgid "Plugin \"%s\" requires API %s. Supported API is %s."
msgstr "El connector \"%s\" requereix l'API %s. L'API disponible és %s"
-#: ../yum/plugins.py:311
+#: ../yum/plugins.py:309
#, python-format
msgid "Loading \"%s\" plugin"
msgstr "S'està carregant el connector \"%s\""
-#: ../yum/plugins.py:318
+#: ../yum/plugins.py:316
#, python-format
-msgid "Two or more plugins with the name \"%s\" exist in the plugin search path"
-msgstr "Existeixen dos o més connectors amb el mateix nom \"%s\" en el camí de cerca de connectors"
+msgid ""
+"Two or more plugins with the name \"%s\" exist in the plugin search path"
+msgstr ""
+"Existeixen dos o més connectors amb el mateix nom \"%s\" en el camí de cerca "
+"de connectors"
-#: ../yum/plugins.py:338
+#: ../yum/plugins.py:336
#, python-format
msgid "Configuration file %s not found"
msgstr "No s'ha trobat el fitxer de configuració %s"
#. for
#. Configuration files for the plugin not found
-#: ../yum/plugins.py:341
+#: ../yum/plugins.py:339
#, python-format
msgid "Unable to find configuration file for plugin %s"
msgstr "No s'ha pogut trobar un fitxer de configuració per al connector %s"
-#: ../yum/plugins.py:495
+#: ../yum/plugins.py:497
msgid "registration of commands not supported"
msgstr "l'enregistrament d'ordres no està suportat"
@@ -2282,44 +2384,87 @@ msgstr "l'enregistrament d'ordres no està suportat"
msgid "Repackaging"
msgstr "Reempaquetant"
-#: ../rpmUtils/oldUtils.py:31
+#: ../rpmUtils/oldUtils.py:33
#, python-format
msgid "Header cannot be opened or does not match %s, %s."
msgstr "La capçalera no es pot obrir o no coincideix amb %s, %s"
-#: ../rpmUtils/oldUtils.py:51
+#: ../rpmUtils/oldUtils.py:53
#, python-format
msgid "RPM %s fails md5 check"
msgstr "Falla la comprobació md5 per al RPM %s"
-#: ../rpmUtils/oldUtils.py:149
+#: ../rpmUtils/oldUtils.py:151
msgid "Could not open RPM database for reading. Perhaps it is already in use?"
-msgstr "No s'ha pogut obrir la base de dades RPM per a llegir-la. Potser ja està en ús?"
+msgstr ""
+"No s'ha pogut obrir la base de dades RPM per a llegir-la. Potser ja està en "
+"ús?"
-#: ../rpmUtils/oldUtils.py:181
+#: ../rpmUtils/oldUtils.py:183
msgid "Got an empty Header, something has gone wrong"
msgstr "S'ha obtingut una capçalera buida, alguna cosa ha anat malament"
-#: ../rpmUtils/oldUtils.py:251
-#: ../rpmUtils/oldUtils.py:258
-#: ../rpmUtils/oldUtils.py:261
-#: ../rpmUtils/oldUtils.py:264
+#: ../rpmUtils/oldUtils.py:253 ../rpmUtils/oldUtils.py:260
+#: ../rpmUtils/oldUtils.py:263 ../rpmUtils/oldUtils.py:266
#, python-format
msgid "Damaged Header %s"
msgstr "Capçalera malmesa %s"
-#: ../rpmUtils/oldUtils.py:279
+#: ../rpmUtils/oldUtils.py:281
#, python-format
msgid "Error opening rpm %s - error %s"
-msgstr "S'ha produïut un error en obrir rpm %s - error %s"
+msgstr "S'ha produït un error en obrir l'rpm %s - error %s"
+
+#~ msgid "Matching packages for package list to user args"
+#~ msgstr ""
+#~ "S'està comparant els paquets per a la llista de paquets amb els arguments "
+#~ "de l'usuari"
+
+#~ msgid ""
+#~ "\n"
+#~ "Transaction Summary\n"
+#~ "%s\n"
+#~ "Install %5.5s Package(s) \n"
+#~ "Update %5.5s Package(s) \n"
+#~ "Remove %5.5s Package(s) \n"
+#~ msgstr ""
+#~ "\n"
+#~ "Resum de transaccions\n"
+#~ "%s\n"
+#~ "Instal·la %5.5s paquets \n"
+#~ "Actualitza %5.5s paquets \n"
+#~ "Esborra %5.5s paquets \n"
+
+#~ msgid "excluding for cost: %s from %s"
+#~ msgstr "s'està excloent per cost: %s de %s"
+
+#~ msgid "Excluding Packages in global exclude list"
+#~ msgstr "S'estan excloent paquets en la llista global d'exclusió"
+
+#~ msgid "Excluding Packages from %s"
+#~ msgstr "S'estan excloent paquets de %s"
+
+#~ msgid "Reducing %s to included packages only"
+#~ msgstr "S'està reduint %s únicament a paquets inclosos."
+
+#~ msgid "Keeping included package %s"
+#~ msgstr "S'està mantenint el paquet inclòs %s"
+
+#~ msgid "Removing unmatched package %s"
+#~ msgstr "S'està esborrant el paquet sense coincidències %s"
+
+#~ msgid "Finished"
+#~ msgstr "Finalitzat"
#~ msgid "Entering rpm code"
#~ msgstr "S'està entrant en codi rpm"
+
#~ msgid "Leaving rpm code"
#~ msgstr "Deixant codi rpm"
+
#~ msgid "Parsing package install arguments"
#~ msgstr "S'estan analitzant els arguments del paquet a instal·lar"
+
#~ msgid "Invalid versioned dependency string, try quoting it."
#~ msgstr ""
#~ "La cadena de versió de dependència és invàlida, proveu-ho entre cometes."
-
diff --git a/rpmUtils/arch.py b/rpmUtils/arch.py
index d22782b..edfc707 100644
--- a/rpmUtils/arch.py
+++ b/rpmUtils/arch.py
@@ -255,6 +255,7 @@ def getCanonPPCArch(arch):
def getCanonSPARCArch(arch):
# Deal with sun4v, sun4u, sun4m cases
+ SPARCtype = None
f = open("/proc/cpuinfo", "r")
lines = f.readlines()
f.close()
@@ -262,6 +263,9 @@ def getCanonSPARCArch(arch):
if line.startswith("type"):
SPARCtype = line.split(':')[1]
break
+ if SPARCtype is None:
+ return arch
+
if SPARCtype.find("sun4v") != -1:
if arch.startswith("sparc64"):
return "sparc64v"
diff --git a/rpmUtils/updates.py b/rpmUtils/updates.py
index f2d43f8..3264956 100644
--- a/rpmUtils/updates.py
+++ b/rpmUtils/updates.py
@@ -24,7 +24,7 @@ class Updates:
"""
This class computes and keeps track of updates and obsoletes.
initialize, add installed packages, add available packages (both as
- unique lists of name, epoch, ver, rel, arch tuples), add an optional dict
+ unique lists of name, arch, ver, rel, epoch tuples), add an optional dict
of obsoleting packages with obsoletes and what they obsolete ie::
foo, i386, 0, 1.1, 1: bar >= 1.1.
"""
diff --git a/test/skipbroken-tests.py b/test/skipbroken-tests.py
index db71a21..f8896f1 100644
--- a/test/skipbroken-tests.py
+++ b/test/skipbroken-tests.py
@@ -582,6 +582,24 @@ class SkipBrokenTests(DepsolveTests):
self.assertEquals('empty', *self.resolveCode(skip=True))
self.assertResult([c1,d1,r1,r2,r3,r4])
+ def testDualPackageUpdate(self):
+ '''
+ RHBZ #522112
+ two version of the same package installed on the system
+ and update will update both, but if it fail some dep only
+ One of the updated packages will be removed from the
+ transaction.
+ '''
+ i1 = self.instPackage('xorg-x11-server-Xorg','1.6.99.900')
+ i2 = self.instPackage('xorg-x11-server-Xorg','1.6.3')
+ u1 = self.repoPackage('xorg-x11-server-Xorg', '1.6.99.901')
+ u1.addRequires("notfound")
+ self.tsInfo.addUpdate(u1, oldpo=i1)
+ self.tsInfo.addUpdate(u1, oldpo=i2)
+ self.assertEquals('empty', *self.resolveCode(skip=True))
+ self.assertResult([i1,i2])
+
+
def resolveCode(self,skip = False):
solver = YumBase()
diff --git a/utils.py b/utils.py
index 5456c68..945aa65 100644
--- a/utils.py
+++ b/utils.py
@@ -15,14 +15,29 @@
import sys
import time
+import exceptions
import yum
from cli import *
+from yum import Errors
from yum import _
+from yum import logginglevels
from optparse import OptionGroup
import yum.plugins as plugins
+
+def suppress_keyboard_interrupt_message():
+ old_excepthook = sys.excepthook
+
+ def new_hook(type, value, traceback):
+ if type != exceptions.KeyboardInterrupt:
+ old_excepthook(type, value, traceback)
+ else:
+ pass
+
+ sys.excepthook = new_hook
+
class YumUtilBase(YumBaseCli):
def __init__(self,name,ver,usage):
YumBaseCli.__init__(self)
@@ -32,7 +47,7 @@ class YumUtilBase(YumBaseCli):
self._utilVer = ver
self._option_group = OptionGroup(self._parser, "%s options" % self._utilName,"")
self._parser.add_option_group(self._option_group)
-
+ suppress_keyboard_interrupt_message()
def getOptionParser(self):
return self._parser
@@ -46,7 +61,7 @@ class YumUtilBase(YumBaseCli):
while True:
try:
self.doLock()
- except yum.Errors.LockError, e:
+ except Errors.LockError, e:
if "%s" %(e.msg,) != lockerr:
lockerr = "%s" %(e.msg,)
self.logger.critical(lockerr)
@@ -83,7 +98,7 @@ class YumUtilBase(YumBaseCli):
pc.enabled_plugins = self._parser._splitArg(opts.enableplugins)
self.conf
- except yum.Errors.ConfigError, e:
+ except Errors.ConfigError, e:
self.logger.critical(_('Config Error: %s'), e)
sys.exit(1)
except ValueError, e:
@@ -108,10 +123,63 @@ class YumUtilBase(YumBaseCli):
self._getRpmDB()
self._getRepos(doSetup = True)
self._getSacks()
- except yum.Errors.YumBaseError, msg:
+ except Errors.YumBaseError, msg:
self.logger.critical(str(msg))
sys.exit(1)
-
+
+ def doUtilTransaction(self):
+ def exUserCancel():
+ self.logger.critical(_('\n\nExiting on user cancel'))
+ if unlock(): return 200
+ return 1
+
+ def exIOError(e):
+ if e.errno == 32:
+ self.logger.critical(_('\n\nExiting on Broken Pipe'))
+ else:
+ self.logger.critical(_('\n\n%s') % str(e))
+ if unlock(): return 200
+ return 1
+
+ def exPluginExit(e):
+ '''Called when a plugin raises PluginYumExit.
+
+ Log the plugin's exit message if one was supplied.
+ ''' # ' xemacs hack
+ exitmsg = str(e)
+ if exitmsg:
+ self.logger.warn('\n\n%s', exitmsg)
+ if unlock(): return 200
+ return 1
+
+ def exFatal(e):
+ self.logger.critical('\n\n%s', to_unicode(e.value))
+ if unlock(): return 200
+ return 1
+
+ def unlock():
+ try:
+ self.closeRpmDB()
+ self.doUnlock()
+ except Errors.LockError, e:
+ return 200
+ return 0
+
+ try:
+ return_code = self.doTransaction()
+ except plugins.PluginYumExit, e:
+ return exPluginExit(e)
+ except Errors.YumBaseError, e:
+ return exFatal(e)
+ except KeyboardInterrupt:
+ return exUserCancel()
+ except IOError, e:
+ return exIOError(e)
+
+ self.verbose_logger.log(logginglevels.INFO_2, _('Complete!'))
+ if unlock(): return 200
+ return return_code
+
def main():
name = 'testutil'
ver = '0.1'
diff --git a/yum/Errors.py b/yum/Errors.py
index 6f0ffe4..3a5aca9 100644
--- a/yum/Errors.py
+++ b/yum/Errors.py
@@ -101,6 +101,9 @@ class RepoMDError(YumBaseError):
class PackageSackError(YumBaseError):
pass
+class RpmDBError(YumBaseError):
+ pass
+
class CompsException(YumBaseError):
pass
diff --git a/yum/__init__.py b/yum/__init__.py
index 8211c70..c1e2c3b 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -57,6 +57,7 @@ import plugins
import logginglevels
import yumRepo
import callbacks
+import yum.history
import warnings
warnings.simplefilter("ignore", Errors.YumFutureDeprecationWarning)
@@ -137,6 +138,7 @@ class YumBase(depsolve.Depsolve):
self._rpmdb = None
self._up = None
self._comps = None
+ self._history = None
self._pkgSack = None
self._lockfile = None
self.skipped_packages = [] # packages skip by the skip-broken code
@@ -153,6 +155,7 @@ class YumBase(depsolve.Depsolve):
self.arch = ArchStorage()
self.preconf = _YumPreBaseConf()
+ self.run_with_package_names = set()
def __del__(self):
self.close()
@@ -272,6 +275,10 @@ class YumBase(depsolve.Depsolve):
# worthless. So we delete it, and thus. it'll raise AttributeError
del self.preconf
+ # Packages used to run yum...
+ for pkgname in self.conf.history_record_packages:
+ self.run_with_package_names.add(pkgname)
+
# run the postconfig plugin hook
self.plugins.run('postconfig')
self.yumvar = self.conf.yumvar
@@ -694,6 +701,13 @@ class YumBase(depsolve.Depsolve):
self._comps.compile(self.rpmdb.simplePkgList())
self.verbose_logger.debug('group time: %0.3f' % (time.time() - group_st))
return self._comps
+
+ def _getHistory(self):
+ """auto create the history object that to acess/append the transaction
+ history information. """
+ if self._history is None:
+ self._history = yum.history.YumHistory(root=self.conf.installroot)
+ return self._history
# properties so they auto-create themselves with defaults
repos = property(fget=lambda self: self._getRepos(),
@@ -718,6 +732,9 @@ class YumBase(depsolve.Depsolve):
comps = property(fget=lambda self: self._getGroups(),
fset=lambda self, value: self._setGroups(value),
fdel=lambda self: setattr(self, "_comps", None))
+ history = property(fget=lambda self: self._getHistory(),
+ fset=lambda self, value: setattr(self, "_history",value),
+ fdel=lambda self: setattr(self, "_history", None))
def doSackFilelistPopulate(self):
@@ -879,6 +896,7 @@ class YumBase(depsolve.Depsolve):
self.verbose_logger.debug('SKIPBROKEN: sanity check the current transaction' )
self.tsInfo.resetResolved(hard=True)
self._checkMissingObsoleted() # This is totally insane, but needed :(
+ self._checkUpdatedLeftovers() # Cleanup updated leftovers
rescode, restring = self.resolveDeps()
if rescode != 1:
self.verbose_logger.debug(_("Skip-broken took %i rounds "), count)
@@ -901,7 +919,7 @@ class YumBase(depsolve.Depsolve):
then the TS_OBSOLETED can get removed from the transaction
so we must make sure that they, exist and else create them
"""
- for txmbr in self.tsInfo:
+ for txmbr in self.tsInfo.getMembersWithState(None, [TS_OBSOLETING,TS_OBSOLETED]):
for pkg in txmbr.obsoletes:
if not self.tsInfo.exists(pkg.pkgtup):
obs = self.tsInfo.addObsoleted(pkg,txmbr.po)
@@ -914,6 +932,21 @@ class YumBase(depsolve.Depsolve):
self.verbose_logger.debug('SKIPBROKEN: Remove extra obsoleted %s (%s)' % (txmbr.po,pkg) )
self.tsInfo.remove(txmbr.po.pkgtup)
+ def _checkUpdatedLeftovers(self):
+ """
+ If multiple packages is updated the same package
+ and this package get removed because of an dep issue
+ then make sure that all the TS_UPDATED get removed.
+ """
+ for txmbr in self.tsInfo.getMembersWithState(None, [TS_UPDATED]):
+ for pkg in txmbr.updated_by:
+ # check if the updating txmbr is in the transaction
+ # else remove the updated txmbr
+ # it clean out some really wierd cases with dupes installed on the system
+ if not self.tsInfo.exists(pkg.pkgtup):
+ self.verbose_logger.debug('SKIPBROKEN: Remove extra updated %s (%s)' % (txmbr.po,pkg) )
+ self.tsInfo.remove(txmbr.po.pkgtup)
+
def _getPackagesToRemoveAllArch(self,po):
''' get all compatible arch packages in pkgSack'''
pkgs = []
@@ -1013,6 +1046,18 @@ class YumBase(depsolve.Depsolve):
self.plugins.run('pretrans')
+ using_pkgs_pats = list(self.run_with_package_names)
+ using_pkgs = self.rpmdb.returnPackages(patterns=using_pkgs_pats)
+ rpmdbv = self.rpmdb.simpleVersion(main_only=True)[0]
+ lastdbv = self.history.last()
+ if lastdbv is not None:
+ lastdbv = lastdbv.end_rpmdbversion
+ if lastdbv is not None and rpmdbv != lastdbv:
+ errstring = _('Warning: RPMDB has been altered since the last yum transaction.')
+ self.logger.warning(errstring)
+ if self.conf.history_record:
+ self.history.beg(rpmdbv, using_pkgs, list(self.tsInfo))
+
errors = self.ts.run(cb.callback, '')
# ts.run() exit codes are, hmm, "creative": None means all ok, empty
# list means some errors happened in the transaction and non-empty
@@ -1028,6 +1073,8 @@ class YumBase(depsolve.Depsolve):
self.verbose_logger.debug(errstring)
resultobject.return_code = 1
else:
+ if self.conf.history_record:
+ self.history.end(rpmdbv, 2, errors=errors)
raise Errors.YumBaseError, errors
if not self.conf.keepcache:
@@ -1044,10 +1091,10 @@ class YumBase(depsolve.Depsolve):
self.rpmdb.dropCachedData() # drop out the rpm cache so we don't step on bad hdr indexes
self.plugins.run('posttrans')
# sync up what just happened versus what is in the rpmdb
- self.verifyTransaction()
+ self.verifyTransaction(resultobject)
return resultobject
- def verifyTransaction(self):
+ def verifyTransaction(self, resultobject=None):
"""checks that the transaction did what we expected it to do. Also
propagates our external yumdb info"""
@@ -1071,7 +1118,7 @@ class YumBase(depsolve.Depsolve):
self.logger.critical(_('%s was supposed to be installed' \
' but is not!' % txmbr.po))
continue
- po = self.rpmdb.searchPkgTuple(txmbr.pkgtup)[0]
+ po = self.getInstalledPackageObject(txmbr.pkgtup)
rpo = txmbr.po
po.yumdb_info.from_repo = rpo.repoid
po.yumdb_info.reason = txmbr.reason
@@ -1115,6 +1162,11 @@ class YumBase(depsolve.Depsolve):
else:
self.verbose_logger.log(logginglevels.DEBUG_2, 'What is this? %s' % txmbr.po)
+ if self.conf.history_record:
+ ret = -1
+ if resultobject is not None:
+ ret = resultobject.return_code
+ self.history.end(self.rpmdb.simpleVersion(main_only=True)[0], ret)
self.rpmdb.dropCachedData()
def costExcludePackages(self):
@@ -1259,7 +1311,10 @@ class YumBase(depsolve.Depsolve):
os.makedirs(lockdir, mode=0755)
fd = os.open(filename, os.O_EXCL|os.O_CREAT|os.O_WRONLY, mode)
except OSError, msg:
- if not msg.errno == errno.EEXIST: raise msg
+ if not msg.errno == errno.EEXIST:
+ # Whoa. What the heck happened?
+ errmsg = _('Could not create lock at %s: %s ') % (filename, str(msg))
+ raise Errors.LockError(msg.errno, errmsg, contents)
return 0
else:
os.write(fd, contents)
@@ -1783,7 +1838,7 @@ class YumBase(depsolve.Depsolve):
for (pkgtup, instTup) in self.up.getObsoletesTuples():
(n,a,e,v,r) = pkgtup
pkgs = self.pkgSack.searchNevra(name=n, arch=a, ver=v, rel=r, epoch=e)
- instpo = self.rpmdb.searchPkgTuple(instTup)[0] # the first one
+ instpo = self.getInstalledPackageObject(instTup)
for po in pkgs:
obsoletes.append(po)
obsoletesTuples.append((po, instpo))
@@ -2326,11 +2381,16 @@ class YumBase(depsolve.Depsolve):
return result
def getInstalledPackageObject(self, pkgtup):
- """returns a YumInstallPackage object for the pkgtup specified"""
- warnings.warn(_('getInstalledPackageObject() will go away, use self.rpmdb.searchPkgTuple().\n'),
- Errors.YumFutureDeprecationWarning, stacklevel=2)
-
- po = self.rpmdb.searchPkgTuple(pkgtup)[0] # take the first one
+ """ Returns a YumInstallPackage object for the pkgtup specified, or
+ raises an exception. You should use this instead of
+ searchPkgTuple() if you are assuming there is a value. """
+
+ pkgs = self.rpmdb.searchPkgTuple(pkgtup)
+ if len(pkgs) == 0:
+ raise Errors.RpmDBError, _('Package tuple %s could not be found in rpmdb') % str(pkgtup)
+
+ # Dito. FIXME from getPackageObject() for len() > 1 ... :)
+ po = pkgs[0] # take the first one
return po
def gpgKeyCheck(self):
@@ -2594,7 +2654,7 @@ class YumBase(depsolve.Depsolve):
if not isinstance(po, YumLocalPackage):
for (obstup, inst_tup) in self.up.getObsoletersTuples(name=po.name):
if po.pkgtup == obstup:
- installed_pkg = self.rpmdb.searchPkgTuple(inst_tup)[0]
+ installed_pkg = self.getInstalledPackageObject(inst_tup)
yield installed_pkg
else:
for (obs_n, obs_f, (obs_e, obs_v, obs_r)) in po.obsoletes:
@@ -2898,7 +2958,7 @@ class YumBase(depsolve.Depsolve):
topkg = self._test_loop(obsoleting_pkg, self._pkg2obspkg)
if topkg is not None:
obsoleting_pkg = topkg
- installed_pkg = self.rpmdb.searchPkgTuple(installed)[0]
+ installed_pkg = self.getInstalledPackageObject(installed)
txmbr = self.tsInfo.addObsoleting(obsoleting_pkg, installed_pkg)
self.tsInfo.addObsoleted(installed_pkg, obsoleting_pkg)
if requiringPo:
@@ -3059,7 +3119,7 @@ class YumBase(depsolve.Depsolve):
updated)
else:
- updated_pkg = self.rpmdb.searchPkgTuple(updated)[0]
+ updated_pkg = self.getInstalledPackageObject(updated)
txmbr = self.tsInfo.addUpdate(available_pkg, updated_pkg)
if requiringPo:
txmbr.setAsDep(requiringPo)
@@ -3426,6 +3486,7 @@ class YumBase(depsolve.Depsolve):
if not apkgs:
# Do we still want to return errors here?
# We don't in the cases below, so I didn't here...
+ pkgs = []
if 'pattern' in kwargs:
pkgs = self.rpmdb.returnPackages(patterns=[kwargs['pattern']],
ignore_case=False)
@@ -3534,6 +3595,84 @@ class YumBase(depsolve.Depsolve):
return returndict
+ def history_redo(self, transaction):
+ """ Given a valid historical transaction object, try and repeat
+ that transaction. """
+ # NOTE: This is somewhat basic atm. ... see comment in undo.
+ old_conf_obs = self.conf.obsoletes
+ self.conf.obsoletes = False
+ done = False
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Reinstall':
+ if self.reinstall(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Downgrade':
+ try:
+ if self.downgrade(pkgtup=pkg.pkgtup):
+ done = True
+ except yum.Errors.DowngradeError:
+ self.logger.critical(_('Failed to downgrade: %s'), pkg)
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Update':
+ if self.update(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state in ('Install', 'True-Install', 'Obsoleting'):
+ if self.install(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Erase':
+ if self.remove(pkgtup=pkg.pkgtup):
+ done = True
+ self.conf.obsoletes = old_conf_obs
+ return done
+
+ def history_undo(self, transaction):
+ """ Given a valid historical transaction object, try and undo
+ that transaction. """
+ # NOTE: This is somewhat basic atm. ... for instance we don't check
+ # that we are going from the old new version. However it's still
+ # better than the RHN rollback code, and people pay for that :).
+ # We turn obsoletes off because we want the specific versions of stuff
+ # from history ... even if they've been obsoleted since then.
+ old_conf_obs = self.conf.obsoletes
+ self.conf.obsoletes = False
+ done = False
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Reinstall':
+ if self.reinstall(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Updated':
+ try:
+ if self.downgrade(pkgtup=pkg.pkgtup):
+ done = True
+ except yum.Errors.DowngradeError:
+ self.logger.critical(_('Failed to downgrade: %s'), pkg)
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Downgraded':
+ if self.update(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Obsoleting':
+ if self.remove(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state in ('Install', 'True-Install'):
+ if self.remove(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Obsoleted':
+ if self.install(pkgtup=pkg.pkgtup):
+ done = True
+ for pkg in transaction.trans_data:
+ if pkg.state == 'Erase':
+ if self.install(pkgtup=pkg.pkgtup):
+ done = True
+ self.conf.obsoletes = old_conf_obs
+ return done
+
def _retrievePublicKey(self, keyurl, repo=None):
"""
Retrieve a key file
diff --git a/yum/config.py b/yum/config.py
index 2f057c3..0d7bc38 100644
--- a/yum/config.py
+++ b/yum/config.py
@@ -703,6 +703,8 @@ class YumConf(StartupConf):
sslclientcert = Option()
sslclientkey = Option()
+ history_record = BoolOption(True)
+ history_record_packages = ListOption(['yum', 'rpm', 'yum-metadata-parser'])
_reposlist = []
@@ -893,7 +895,13 @@ def _getsysver(installroot, distroverpkg):
idx = ts.dbMatch('provides', distroverpkg)
except TypeError, e:
# This is code for "cannot open rpmdb"
- raise Errors.YumBaseError("Error: " + e.message)
+ # this is for pep 352 compliance on python 2.6 and above :(
+ if sys.hexversion < 0x02050000:
+ if hasattr(e,'message'):
+ raise Errors.YumBaseError("Error: " + str(e.message))
+ else:
+ raise Errors.YumBaseError("Error: " + str(e))
+ raise Errors.YumBaseError("Error: " + str(e))
# we're going to take the first one - if there is more than one of these
# then the user needs a beating
if idx.count() == 0:
diff --git a/yum/depsolve.py b/yum/depsolve.py
index d6b1b02..467f657 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -1083,7 +1083,16 @@ class Depsolve(object):
# could play a part ... this probably needs a better fix.
newest = sorted(rpmdbpkgs)[-1]
if newest.verLT(pkg):
- ipkgresults[pkg] = 0
+ # give pkgs which are updates just a SLIGHT edge
+ # we should also make sure that any pkg
+ # we are giving an edge to is not obsoleted by
+ # something else in the transaction. :(
+ # there are many ways I hate this - this is but one
+ ipkgresults[pkg] = 5
+ else:
+ # just b/c they're not installed pkgs doesn't mean they should
+ # be ignored entirely. Just not preferred
+ ipkgresults[pkg] = 0
# This is probably only for "renames". What happens is that pkgA-1 gets
# obsoleted by pkgB but pkgB requires pkgA-2, now _if_ the pkgA txmbr
diff --git a/yum/history.py b/yum/history.py
new file mode 100644
index 0000000..9741d36
--- /dev/null
+++ b/yum/history.py
@@ -0,0 +1,622 @@
+#!/usr/bin/python -t
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2009 Red Hat
+#
+# James Antill <james@fedoraproject.org>
+
+import time
+import os, os.path
+import glob
+from weakref import proxy as weakref
+
+from sqlutils import sqlite, executeSQL
+import yum.misc
+import yum.constants
+from yum.constants import *
+from yum.packages import YumInstalledPackage, YumAvailablePackage, PackageObject
+
+_history_dir = '/var/lib/yum/history'
+
+_stcode2sttxt = {TS_UPDATE : 'Update',
+ TS_UPDATED : 'Updated',
+ TS_ERASE: 'Erase',
+ TS_INSTALL: 'Install',
+ TS_TRUEINSTALL : 'True-Install',
+ TS_OBSOLETED: 'Obsoleted',
+ TS_OBSOLETING: 'Obsoleting'}
+
+_sttxt2stcode = {'Update' : TS_UPDATE,
+ 'Updated' : TS_UPDATED,
+ 'Erase' : TS_ERASE,
+ 'Install' : TS_INSTALL,
+ 'True-Install' : TS_TRUEINSTALL,
+ 'Reinstall' : TS_INSTALL, # Broken
+ 'Downgrade' : TS_INSTALL, # Broken
+ 'Downgraded' : TS_INSTALL, # Broken
+ 'Obsoleted' : TS_OBSOLETED,
+ 'Obsoleting' : TS_OBSOLETING}
+
+# ---- horrible Copy and paste from sqlitesack ----
+def _sql_esc(pattern):
+ """ Apply SQLite escaping, if needed. Returns pattern and esc. """
+ esc = ''
+ if "_" in pattern or "%" in pattern:
+ esc = ' ESCAPE "!"'
+ pattern = pattern.replace("!", "!!")
+ pattern = pattern.replace("%", "!%")
+ pattern = pattern.replace("_", "!_")
+ return (pattern, esc)
+
+def _sql_esc_glob(patterns):
+ """ Converts patterns to SQL LIKE format, if required (or gives up if
+ not possible). """
+ ret = []
+ for pattern in patterns:
+ if '[' in pattern: # LIKE only has % and _, so [abc] can't be done.
+ return [] # So Load everything
+
+ # Convert to SQL LIKE format
+ (pattern, esc) = _sql_esc(pattern)
+ pattern = pattern.replace("*", "%")
+ pattern = pattern.replace("?", "_")
+ ret.append((pattern, esc))
+ return ret
+
+def _setupHistorySearchSQL(patterns=None, ignore_case=False):
+ """Setup need_full and patterns for _yieldSQLDataList, also see if
+ we can get away with just using searchNames(). """
+
+ if patterns is None:
+ patterns = []
+
+ fields = ['name', 'sql_nameArch', 'sql_nameVerRelArch',
+ 'sql_nameVer', 'sql_nameVerRel',
+ 'sql_envra', 'sql_nevra']
+ need_full = False
+ for pat in patterns:
+ if yum.misc.re_full_search_needed(pat):
+ need_full = True
+ break
+
+ pat_max = PATTERNS_MAX
+ if not need_full:
+ fields = ['name']
+ pat_max = PATTERNS_INDEXED_MAX
+ if len(patterns) > pat_max:
+ patterns = []
+ if ignore_case:
+ patterns = _sql_esc_glob(patterns)
+ else:
+ tmp = []
+ need_glob = False
+ for pat in patterns:
+ if misc.re_glob(pat):
+ tmp.append((pat, 'glob'))
+ need_glob = True
+ else:
+ tmp.append((pat, '='))
+ if not need_full and not need_glob and patterns:
+ return (need_full, patterns, fields, True)
+ patterns = tmp
+ return (need_full, patterns, fields, False)
+# ---- horrible Copy and paste from sqlitesack ----
+
+class YumHistoryPackage(PackageObject):
+
+ def __init__(self, name, arch, epoch, version, release, checksum):
+ self.name = name
+ self.version = version
+ self.release = release
+ self.epoch = epoch
+ self.arch = arch
+ self.pkgtup = (self.name, self.arch,
+ self.epoch, self.version, self.release)
+ if checksum is None:
+ self._checksums = [] # (type, checksum, id(0,1)
+ else:
+ chk = checksum.split(':')
+ self._checksums = [(chk[0], chk[1], 0)] # (type, checksum, id(0,1))
+
+class YumHistoryTransaction:
+ """ Holder for a history transaction. """
+
+ def __init__(self, history, row):
+ self._history = weakref(history)
+
+ self.tid = row[0]
+ self.beg_timestamp = row[1]
+ self.beg_rpmdbversion = row[2]
+ self.end_timestamp = row[3]
+ self.end_rpmdbversion = row[4]
+ self.loginuid = row[5]
+ self.return_code = row[6]
+
+ self._loaded_TW = None
+ self._loaded_TD = None
+
+ self.altered_lt_rpmdb = None
+ self.altered_gt_rpmdb = None
+
+ def __cmp__(self, other):
+ if other is None:
+ return 1
+ ret = cmp(self.beg_timestamp, other.beg_timestamp)
+ if ret: return -ret
+ ret = cmp(self.end_timestamp, other.end_timestamp)
+ if ret: return ret
+ ret = cmp(self.tid, other.tid)
+ return -ret
+
+ def _getTransWith(self):
+ if self._loaded_TW is None:
+ self._loaded_TW = sorted(self._history._old_with_pkgs(self.tid))
+ return self._loaded_TW
+ def _getTransData(self):
+ if self._loaded_TD is None:
+ self._loaded_TD = sorted(self._history._old_data_pkgs(self.tid))
+ return self._loaded_TD
+
+ trans_with = property(fget=lambda self: self._getTransWith())
+ trans_data = property(fget=lambda self: self._getTransData())
+
+class YumHistory:
+ """ API for accessing the history sqlite data. """
+
+ def __init__(self, root='/', db_path=_history_dir):
+ self._conn = None
+
+ self.conf = yum.misc.GenericHolder()
+ self.conf.db_path = os.path.normpath(root + '/' + db_path)
+ self.conf.writable = False
+
+ if not os.path.exists(self.conf.db_path):
+ try:
+ os.makedirs(self.conf.db_path)
+ except (IOError, OSError), e:
+ # some sort of useful thing here? A warning?
+ return
+ self.conf.writable = True
+ else:
+ if os.access(self.conf.db_path, os.W_OK):
+ self.conf.writable = True
+
+ DBs = glob.glob('%s/history-*-*-*.sqlite' % self.conf.db_path)
+ self._db_file = None
+ for d in reversed(sorted(DBs)):
+ fname = os.path.basename(d)
+ fname = fname[len("history-"):-len(".sqlite")]
+ pieces = fname.split('-', 4)
+ if len(pieces) != 3:
+ continue
+ try:
+ map(int, pieces)
+ except ValueError:
+ continue
+
+ self._db_file = d
+ break
+
+ if self._db_file is None:
+ self._create_db_file()
+
+ def _get_cursor(self):
+ if self._conn is None:
+ self._conn = sqlite.connect(self._db_file)
+ return self._conn.cursor()
+ def _commit(self):
+ return self._conn.commit()
+
+ def _pkgtup2pid(self, pkgtup, checksum=None):
+ cur = self._get_cursor()
+ executeSQL(cur, """SELECT pkgtupid, checksum FROM pkgtups
+ WHERE name=? AND arch=? AND
+ epoch=? AND version=? AND release=?""", pkgtup)
+ for sql_pkgtupid, sql_checksum in cur:
+ if checksum is None and sql_checksum is None:
+ return sql_pkgtupid
+ if checksum is None:
+ continue
+ if sql_checksum is None:
+ continue
+ if checksum == sql_checksum:
+ return sql_pkgtupid
+
+ if checksum is not None:
+ (n,a,e,v,r) = pkgtup
+ res = executeSQL(cur,
+ """INSERT INTO pkgtups
+ (name, arch, epoch, version, release, checksum)
+ VALUES (?, ?, ?, ?, ?, ?)""", (n,a,e,v,r,
+ checksum))
+ else:
+ res = executeSQL(cur,
+ """INSERT INTO pkgtups
+ (name, arch, epoch, version, release)
+ VALUES (?, ?, ?, ?, ?)""", pkgtup)
+ return cur.lastrowid
+ def _apkg2pid(self, po):
+ csum = po.returnIdSum()
+ if csum is not None:
+ csum = "%s:%s" % (str(csum[0]), str(csum[1]))
+ return self._pkgtup2pid(po.pkgtup, csum)
+ def _ipkg2pid(self, po):
+ csum = None
+ yumdb = po.yumdb_info
+ if 'checksum_type' in yumdb and 'checksum_type' in yumdb:
+ csum = "%s:%s" % (yumdb.checksum_type, yumdb.checksum_data)
+ return self._pkgtup2pid(po.pkgtup, csum)
+ def pkg2pid(self, po):
+ if isinstance(po, YumInstalledPackage):
+ return self._ipkg2pid(po)
+ if isinstance(po, YumAvailablePackage):
+ return self._apkg2pid(po)
+ return self._pkgtup2pid(po.pkgtup, None)
+
+ @staticmethod
+ def txmbr2state(txmbr):
+ state = None
+ if txmbr.output_state in (TS_INSTALL, TS_TRUEINSTALL):
+ if hasattr(txmbr, 'reinstall'):
+ state = 'Reinstall'
+ elif txmbr.downgrades:
+ state = 'Downgrade'
+ if txmbr.output_state == TS_ERASE:
+ if txmbr.downgraded_by:
+ state = 'Downgraded'
+ if state is None:
+ state = _stcode2sttxt[txmbr.output_state]
+ return state
+
+ def trans_with_pid(self, pid):
+ cur = self._get_cursor()
+ res = executeSQL(cur,
+ """INSERT INTO trans_with_pkgs
+ (tid, pkgtupid)
+ VALUES (?, ?)""", (self._tid, pid))
+ return cur.lastrowid
+
+ def trans_data_pid_beg(self, pid, state):
+ if not hasattr(self, '_tid'):
+ return # Not configured to run
+ cur = self._get_cursor()
+ res = executeSQL(cur,
+ """INSERT INTO trans_data_pkgs
+ (tid, pkgtupid, state)
+ VALUES (?, ?, ?)""", (self._tid, pid, state))
+ return cur.lastrowid
+ def trans_data_pid_end(self, pid, state):
+ if not hasattr(self, '_tid'):
+ return # Not configured to run
+
+ cur = self._get_cursor()
+ res = executeSQL(cur,
+ """UPDATE trans_data_pkgs SET done = ?
+ WHERE tid = ? AND pkgtupid = ? AND state = ?
+ """, ('TRUE', self._tid, pid, state))
+ self._commit()
+ return cur.lastrowid
+
+ def beg(self, rpmdb_version, using_pkgs, txmbrs):
+ cur = self._get_cursor()
+ res = executeSQL(cur,
+ """INSERT INTO trans_beg
+ (timestamp, rpmdb_version, loginuid)
+ VALUES (?, ?, ?)""", (int(time.time()),
+ str(rpmdb_version),
+ yum.misc.getloginuid()))
+ self._tid = cur.lastrowid
+
+ for pkg in using_pkgs:
+ pid = self._ipkg2pid(pkg)
+ self.trans_with_pid(pid)
+
+ for txmbr in txmbrs:
+ pid = self.pkg2pid(txmbr.po)
+ state = self.txmbr2state(txmbr)
+ self.trans_data_pid_beg(pid, state)
+
+ self._commit()
+
+ def _log_errors(self, errors):
+ cur = self._get_cursor()
+ for error in errors:
+ executeSQL(cur,
+ """INSERT INTO trans_error
+ (tid, msg) VALUES (?, ?)""", (self._tid, error))
+ self._commit()
+
+ def log_scriptlet_output(self, data, msg):
+ """ Note that data can be either a real pkg. ... or not. """
+ if msg is None or not hasattr(self, '_tid'):
+ return # Not configured to run
+
+ cur = self._get_cursor()
+ for error in msg.split('\n'):
+ executeSQL(cur,
+ """INSERT INTO trans_script_stdout
+ (tid, line) VALUES (?, ?)""", (self._tid, error))
+ self._commit()
+
+ def end(self, rpmdb_version, return_code, errors=None):
+ assert return_code or not errors
+ cur = self._get_cursor()
+ res = executeSQL(cur,
+ """INSERT INTO trans_end
+ (tid, timestamp, rpmdb_version, return_code)
+ VALUES (?, ?, ?, ?)""", (self._tid,int(time.time()),
+ str(rpmdb_version),
+ return_code))
+ self._commit()
+ if not return_code:
+ # Simple hack, if the transaction finished. Note that this
+ # catches the erase cases (as we still don't get pkgtups for them),
+ # Eg. Updated elements.
+ executeSQL(cur,
+ """UPDATE trans_data_pkgs SET done = ?
+ WHERE tid = ?""", ('TRUE', self._tid,))
+ self._commit()
+ if errors is not None:
+ self._log_errors(errors)
+ del self._tid
+
+ def _old_with_pkgs(self, tid):
+ cur = self._get_cursor()
+ executeSQL(cur,
+ """SELECT name, arch, epoch, version, release, checksum
+ FROM trans_with_pkgs JOIN pkgtups USING(pkgtupid)
+ WHERE tid = ?
+ ORDER BY name ASC, epoch ASC""", (tid,))
+ ret = []
+ for row in cur:
+ obj = YumHistoryPackage(row[0],row[1],row[2],row[3],row[4], row[5])
+ ret.append(obj)
+ return ret
+ def _old_data_pkgs(self, tid):
+ cur = self._get_cursor()
+ executeSQL(cur,
+ """SELECT name, arch, epoch, version, release,
+ checksum, done, state
+ FROM trans_data_pkgs JOIN pkgtups USING(pkgtupid)
+ WHERE tid = ?
+ ORDER BY name ASC, epoch ASC, state DESC""", (tid,))
+ ret = []
+ for row in cur:
+ obj = YumHistoryPackage(row[0],row[1],row[2],row[3],row[4], row[5])
+ obj.done = row[6] == 'TRUE'
+ obj.state = row[7]
+ obj.state_installed = None
+ if _sttxt2stcode[obj.state] in TS_INSTALL_STATES:
+ obj.state_installed = True
+ if _sttxt2stcode[obj.state] in TS_REMOVE_STATES:
+ obj.state_installed = False
+ ret.append(obj)
+ return ret
+
+ def old(self, tids=[], limit=None, complete_transactions_only=False):
+ """ Return a list of the last transactions, note that this includes
+ partial transactions (ones without an end transaction). """
+ cur = self._get_cursor()
+ sql = """SELECT tid,
+ trans_beg.timestamp AS beg_ts,
+ trans_beg.rpmdb_version AS beg_rv,
+ trans_end.timestamp AS end_ts,
+ trans_end.rpmdb_version AS end_rv,
+ loginuid, return_code
+ FROM trans_beg JOIN trans_end USING(tid)"""
+ # NOTE: sqlite doesn't do OUTER JOINs ... *sigh*. So we have to do it
+ # ourself.
+ if not complete_transactions_only:
+ sql = """SELECT tid,
+ trans_beg.timestamp AS beg_ts,
+ trans_beg.rpmdb_version AS beg_rv,
+ NULL, NULL,
+ loginuid, NULL
+ FROM trans_beg"""
+ params = None
+ if tids and len(tids) <= yum.constants.PATTERNS_INDEXED_MAX:
+ params = tids = list(set(tids))
+ sql += " WHERE tid IN (%s)" % ", ".join(['?'] * len(tids))
+ sql += " ORDER BY beg_ts DESC, tid ASC"
+ if limit is not None:
+ sql += " LIMIT " + str(limit)
+ executeSQL(cur, sql, params)
+ ret = []
+ tid2obj = {}
+ for row in cur:
+ if tids and len(tids) > yum.constants.PATTERNS_INDEXED_MAX:
+ if row[0] not in tids:
+ continue
+ obj = YumHistoryTransaction(self, row)
+ tid2obj[row[0]] = obj
+ ret.append(obj)
+
+ sql = """SELECT tid,
+ trans_end.timestamp AS end_ts,
+ trans_end.rpmdb_version AS end_rv,
+ return_code
+ FROM trans_end"""
+ params = tid2obj.keys()
+ if len(params) > yum.constants.PATTERNS_INDEXED_MAX:
+ executeSQL(cur, sql)
+ else:
+ sql += " WHERE tid IN (%s)" % ", ".join(['?'] * len(params))
+ executeSQL(cur, sql, params)
+ for row in cur:
+ if row[0] not in tid2obj:
+ continue
+ tid2obj[row[0]].end_timestamp = row[1]
+ tid2obj[row[0]].end_rpmdbversion = row[2]
+ tid2obj[row[0]].return_code = row[3]
+
+ # Go through backwards, and see if the rpmdb versions match
+ las = None
+ for obj in reversed(ret):
+ cur_rv = obj.beg_rpmdbversion
+ las_rv = None
+ if las is not None:
+ las_rv = las.end_rpmdbversion
+ if las_rv is None or cur_rv is None or (las.tid + 1) != obj.tid:
+ pass
+ elif las_rv != cur_rv:
+ obj.altered_lt_rpmdb = True
+ las.altered_gt_rpmdb = True
+ else:
+ obj.altered_lt_rpmdb = False
+ las.altered_gt_rpmdb = False
+ las = obj
+
+ return ret
+
+ def last(self):
+ """ This is the last full transaction. So any imcomplete transactions
+ do not count. """
+ cur = self._get_cursor()
+ sql = """SELECT tid,
+ trans_beg.timestamp AS beg_ts,
+ trans_beg.rpmdb_version AS beg_rv,
+ trans_end.timestamp AS end_ts,
+ trans_end.rpmdb_version AS end_rv,
+ loginuid, return_code
+ FROM trans_beg JOIN trans_end USING(tid)
+ ORDER BY beg_ts DESC, tid ASC
+ LIMIT 1"""
+ executeSQL(cur, sql)
+ for row in cur:
+ return YumHistoryTransaction(self, row)
+ return None
+
+ def _yieldSQLDataList(self, patterns, fields, ignore_case):
+ """Yields all the package data for the given params. """
+
+ cur = self._get_cursor()
+ qsql = _FULL_PARSE_QUERY_BEG
+
+ pat_sqls = []
+ pat_data = []
+ for (pattern, rest) in patterns:
+ for field in fields:
+ if ignore_case:
+ pat_sqls.append("%s LIKE ?%s" % (field, rest))
+ else:
+ pat_sqls.append("%s %s ?" % (field, rest))
+ pat_data.append(pattern)
+ assert pat_sqls
+
+ qsql += " OR ".join(pat_sqls)
+ executeSQL(cur, qsql, pat_data)
+ for x in cur:
+ yield x
+
+ def search(self, patterns, ignore_case=True):
+ """ Search for history transactions which contain specified
+ packages al. la. "yum list". Returns transaction ids. """
+ # Search packages ... kind of sucks that it's search not list, pkglist?
+
+ data = _setupHistorySearchSQL(patterns, ignore_case)
+ (need_full, patterns, fields, names) = data
+
+ ret = []
+ pkgtupids = set()
+ for row in self._yieldSQLDataList(patterns, fields, ignore_case):
+ pkgtupids.add(row[0])
+
+ cur = self._get_cursor()
+ sql = """SELECT tid FROM trans_data_pkgs WHERE pkgtupid IN """
+ sql += "(%s)" % ",".join(['?'] * len(pkgtupids))
+ params = list(pkgtupids)
+ tids = set()
+ if len(params) > yum.constants.PATTERNS_INDEXED_MAX:
+ executeSQL(cur, """SELECT tid FROM trans_data_pkgs""")
+ for row in cur:
+ if row[0] in params:
+ tids.add(row[0])
+ return tids
+ if not params:
+ return tids
+ executeSQL(cur, sql, params)
+ for row in cur:
+ tids.add(row[0])
+ return tids
+
+ def _create_db_file(self):
+ """ Create a new history DB file, populating tables etc. """
+
+ _db_file = '%s/%s-%s.%s' % (self.conf.db_path,
+ 'history',
+ time.strftime('%Y-%m-%d'),
+ 'sqlite')
+ if self._db_file == _db_file:
+ os.rename(_db_file, _db_file + '.old')
+ self._db_file = _db_file
+
+ cur = self._get_cursor()
+ ops = ['''\
+ CREATE TABLE trans_beg (
+ tid INTEGER PRIMARY KEY,
+ timestamp INTEGER NOT NULL, rpmdb_version TEXT NOT NULL,
+ loginuid INTEGER);
+''', '''\
+ CREATE TABLE trans_end (
+ tid INTEGER PRIMARY KEY REFERENCES trans_beg,
+ timestamp INTEGER NOT NULL, rpmdb_version TEXT NOT NULL,
+ return_code INTEGER NOT NULL);
+''', '''\
+\
+ CREATE TABLE trans_with_pkgs (
+ tid INTEGER NOT NULL REFERENCES trans_beg,
+ pkgtupid INTEGER NOT NULL REFERENCES pkgtups);
+''', '''\
+\
+ CREATE TABLE trans_error (
+ mid INTEGER PRIMARY KEY,
+ tid INTEGER NOT NULL REFERENCES trans_beg,
+ msg TEXT NOT NULL);
+''', '''\
+ CREATE TABLE trans_script_stdout (
+ lid INTEGER PRIMARY KEY,
+ tid INTEGER NOT NULL REFERENCES trans_beg,
+ line TEXT NOT NULL);
+''', '''\
+\
+ CREATE TABLE trans_data_pkgs (
+ tid INTEGER NOT NULL REFERENCES trans_beg,
+ pkgtupid INTEGER NOT NULL REFERENCES pkgtups,
+ done BOOL NOT NULL DEFAULT FALSE, state TEXT NOT NULL);
+''', '''\
+\
+ CREATE TABLE pkgtups (
+ pkgtupid INTEGER PRIMARY KEY, name TEXT NOT NULL, arch TEXT NOT NULL,
+ epoch TEXT NOT NULL, version TEXT NOT NULL, release TEXT NOT NULL,
+ checksum TEXT);
+''', '''\
+ CREATE INDEX i_pkgtup_naevr ON pkgtups (name, arch, epoch, version, release);
+''']
+ for op in ops:
+ cur.execute(op)
+ self._commit()
+
+# Pasted from sqlitesack
+_FULL_PARSE_QUERY_BEG = """
+SELECT pkgtupid,name,epoch,version,release,arch,
+ name || "." || arch AS sql_nameArch,
+ name || "-" || version || "-" || release || "." || arch AS sql_nameVerRelArch,
+ name || "-" || version AS sql_nameVer,
+ name || "-" || version || "-" || release AS sql_nameVerRel,
+ epoch || ":" || name || "-" || version || "-" || release || "." || arch AS sql_envra,
+ name || "-" || epoch || ":" || version || "-" || release || "." || arch AS sql_nevra
+ FROM pkgtups
+ WHERE
+"""
diff --git a/yum/misc.py b/yum/misc.py
index a8f7954..a092b65 100644
--- a/yum/misc.py
+++ b/yum/misc.py
@@ -797,6 +797,21 @@ def unlink_f(filename):
if e.errno != errno.ENOENT:
raise
+def getloginuid():
+ """ Get the audit-uid/login-uid, if available. None is returned if there
+ was a problem. Note that no caching is done here. """
+ # We might normally call audit.audit_getloginuid(), except that requires
+ # importing all of the audit module. And it doesn't work anyway: BZ 518721
+ try:
+ fo = open("/proc/self/loginuid")
+ except IOError:
+ return None
+ data = fo.read()
+ try:
+ return int(data)
+ except ValueError:
+ return None
+
# ---------- i18n ----------
import locale
import sys
diff --git a/yum/packageSack.py b/yum/packageSack.py
index 3716410..cc26d03 100644
--- a/yum/packageSack.py
+++ b/yum/packageSack.py
@@ -35,6 +35,8 @@ class PackageSackVersion:
def __eq__(self, other):
if other is None: return False
+ if type(other) in (type(''), type(u'')):
+ return str(self) == other
if self._num != other._num: return False
if self._chksum.digest() != other._chksum.digest(): return False
return True
diff --git a/yum/plugins.py b/yum/plugins.py
index 27b1aa5..02f0d57 100644
--- a/yum/plugins.py
+++ b/yum/plugins.py
@@ -457,6 +457,10 @@ class PluginConduit:
'''
return config.getOption(self._conf, section, opt, config.BoolOption(default))
+ def registerPackageName(self, name):
+ self._base.run_with_package_names.add(name)
+
+
class ConfigPluginConduit(PluginConduit):
def registerOpt(self, name, valuetype, where, default):
diff --git a/yum/rpmsack.py b/yum/rpmsack.py
index fbeb9b3..8368d52 100644
--- a/yum/rpmsack.py
+++ b/yum/rpmsack.py
@@ -339,7 +339,7 @@ class RPMDBPackageSack(PackageSackBase):
pkgobjlist = pkgobjlist[0] + pkgobjlist[1]
return pkgobjlist
- def simpleVersion(self):
+ def simpleVersion(self, main_only=False):
""" Return a simple version for all installed packages. """
main = PackageSackVersion()
irepos = {}
@@ -350,6 +350,9 @@ class RPMDBPackageSack(PackageSackBase):
csum = (ydbi.checksum_type, ydbi.checksum_data)
main.update(pkg, csum)
+ if main_only:
+ continue
+
repoid = 'installed'
rev = None
if 'from_repo' in pkg.yumdb_info:
diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index 77b06a2..b1b896f 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -230,6 +230,11 @@ class RPMTransaction:
except IOError:
pass
+ def _scriptout(self, data):
+ msgs = self._scriptOutput()
+ self.display.scriptout(data, msgs)
+ self.base.history.log_scriptlet_output(data, msgs)
+
def __del__(self):
self._shutdownOutputLogging()
@@ -339,7 +344,7 @@ class RPMTransaction:
# we hand back the right path to those 'outside' of the chroot() calls
# but we're using the right path inside.
if self.base.conf.installroot != '/':
- tsfn = tsfn.replace(self.base.conf.installroot,'')
+ tsfn = tsfn.replace(os.path.normpath(self.base.conf.installroot),'')
try:
if not os.path.exists(os.path.dirname(tsfn)):
os.makedirs(os.path.dirname(tsfn)) # make the dir,
@@ -439,10 +444,14 @@ class RPMTransaction:
txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
for txmbr in txmbrs:
self.display.filelog(txmbr.po, txmbr.output_state)
- self.display.scriptout(txmbr.po, self._scriptOutput())
+ self._scriptout(txmbr.po)
+ # NOTE: We only do this for install, not erase atm.
+ # because we don't get pkgtup data for erase (this
+ # includes "Updated" pkgs).
+ pid = self.base.history.pkg2pid(txmbr.po)
+ state = self.base.history.txmbr2state(txmbr)
+ self.base.history.trans_data_pid_end(pid, state)
self.ts_done(txmbr.po, txmbr.output_state)
-
-
def _instProgress(self, bytes, total, h):
if h is not None:
@@ -477,7 +486,7 @@ class RPMTransaction:
self.display.event(h, action, 100, 100, self.complete_actions,
self.total_actions)
- self.display.scriptout(h, self._scriptOutput())
+ self._scriptout(h)
if self.test: return # and we're done
self.ts_done(h, action)
diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py
index b6c14c5..3dd93a5 100644
--- a/yum/sqlitesack.py
+++ b/yum/sqlitesack.py
@@ -929,15 +929,19 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack):
if file_glob:
name_re = re.compile(fnmatch.translate(name))
def filelist_globber(sql_dirname, sql_filenames):
+ # Note: Can't return bool, because sqlite doesn't like it in
+ # weird ways. Test:
+ # install '*bin/autoheader'
+ # provides /lib/security/pam_loginuid.so
files = sql_filenames.split('/')
if not file_glob:
- return filename in files
+ return int(filename in files)
fns = map(lambda f: '%s/%s' % (sql_dirname, f), files)
for match in fns:
if name_re.match(match):
- return True
- return False
+ return 1
+ return 0
cache.create_function("filelist_globber", 2, filelist_globber)
# for all the ones where filenames is multiple files,
diff --git a/yum/sqlutils.py b/yum/sqlutils.py
index fda380e..3a93146 100644
--- a/yum/sqlutils.py
+++ b/yum/sqlutils.py
@@ -121,6 +121,11 @@ def QmarkToPyformat(query, params):
if token.endswith("?"):
output.append(token[:-1] + "%%(param%d)s" % count)
count+=1
+ elif token.endswith("?,") or token.endswith("?)"):
+ ntoken = token[:-2] + "%%(param%d)s" % count
+ ntoken += token[-1]
+ output.append(ntoken)
+ count+=1
else:
output.append(token)
diff --git a/yum/transactioninfo.py b/yum/transactioninfo.py
index be772e5..bd7bf80 100644
--- a/yum/transactioninfo.py
+++ b/yum/transactioninfo.py
@@ -271,6 +271,7 @@ class TransactionData:
elif txmbr.output_state in (TS_INSTALL, TS_TRUEINSTALL):
if include_reinstall and self.rpmdb.contains(po=txmbr.po):
+ txmbr.reinstall = True
self.reinstalled.append(txmbr)
continue
@@ -319,6 +320,8 @@ class TransactionData:
self.depremoved.sort()
self.instgroups.sort()
self.removedgroups.sort()
+ self.reinstalled.sort()
+ self.downgraded.sort()
self.failed.sort()
diff --git a/yum/yumRepo.py b/yum/yumRepo.py
index fac218a..367a68e 100644
--- a/yum/yumRepo.py
+++ b/yum/yumRepo.py
@@ -1034,6 +1034,8 @@ class YumRepository(Repository, config.RepoConf):
old_local = local + '.old.tmp' # locked, so this is ok
shutil.copy2(local, old_local)
xml = self._parseRepoXML(old_local, True)
+ if xml is None:
+ return None
self._oldRepoMDData = {'old_repo_XML' : xml, 'local' : local,
'old_local' : old_local, 'new_MD_files' : []}
return xml
diff --git a/yumcommands.py b/yumcommands.py
index bd73d0c..f6c4e19 100644
--- a/yumcommands.py
+++ b/yumcommands.py
@@ -778,13 +778,17 @@ class RepoListCommand(YumCommand):
arg = 'enabled'
extcmds = map(lambda x: x.lower(), extcmds)
- # Setup so len(repo.sack) is correct
- base.repos.populateSack()
+ verbose = base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3)
+ try:
+ # Setup so len(repo.sack) is correct
+ base.repos.populateSack()
+ except yum.Errors.RepoError:
+ if verbose:
+ raise
repos = base.repos.repos.values()
repos.sort()
enabled_repos = base.repos.listEnabled()
- verbose = base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3)
if arg == 'all':
ehibeg = base.term.FG_COLOR['green'] + base.term.MODE['bold']
dhibeg = base.term.FG_COLOR['red']
@@ -1061,7 +1065,7 @@ class DowngradeCommand(YumCommand):
def needTs(self, base, basecmd, extcmds):
return False
-
+
class VersionCommand(YumCommand):
def getNames(self):
@@ -1097,11 +1101,19 @@ class VersionCommand(YumCommand):
cols = []
if vcmd in ('installed', 'all'):
try:
- data = base.rpmdb.simpleVersion()
+ main_only = True
+ if base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3):
+ main_only = False
+ data = base.rpmdb.simpleVersion(main_only)
+ lastdbv = base.history.last()
+ if lastdbv is not None:
+ lastdbv = lastdbv.end_rpmdbversion
+ if lastdbv is not None and data[0] != lastdbv:
+ errstring = _('Warning: RPMDB has been altered since the last yum transaction.')
+ base.logger.warning(errstring)
cols.append(("%s %s/%s" % (_("Installed:"), rel, ba),
str(data[0])))
- if base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3):
- _append_repos(cols, data[1])
+ _append_repos(cols, data[1])
except yum.Errors.YumBaseError, e:
return 1, [str(e)]
if vcmd in ('available', 'all'):
@@ -1126,10 +1138,83 @@ class VersionCommand(YumCommand):
for line in cols:
print base.fmtColumns(zip(line, columns))
- return 0, []
+ return 0, ['version']
def needTs(self, base, basecmd, extcmds):
vcmd = 'installed'
if extcmds:
vcmd = extcmds[0]
return vcmd in ('available', 'all')
+
+
+class HistoryCommand(YumCommand):
+ def getNames(self):
+ return ['history']
+
+ def getUsage(self):
+ return "[info|list|summary|redo|undo|new]"
+
+ def getSummary(self):
+ return _("Display, or use, the transaction history")
+
+ def _hcmd_redo(self, base, extcmds):
+ old = base._history_get_transaction(extcmds)
+ if old is None:
+ return 1, ['Failed history redo']
+ tm = time.ctime(old.beg_timestamp)
+ print "Repeating transaction %u, from %s" % (old.tid, tm)
+ base.historyInfoCmdPkgsAltered(old)
+ if base.history_redo(old):
+ return 2, ["Repeating transaction %u" % (old.tid,)]
+
+ def _hcmd_undo(self, base, extcmds):
+ old = base._history_get_transaction(extcmds)
+ if old is None:
+ return 1, ['Failed history undo']
+ tm = time.ctime(old.beg_timestamp)
+ print "Undoing transaction %u, from %s" % (old.tid, tm)
+ base.historyInfoCmdPkgsAltered(old)
+ if base.history_undo(old):
+ return 2, ["Undoing transaction %u" % (old.tid,)]
+
+ def _hcmd_new(self, base, extcmds):
+ base.history._create_db_file()
+
+ def doCheck(self, base, basecmd, extcmds):
+ cmds = ('list', 'info', 'summary', 'repeat', 'redo', 'undo', 'new')
+ if extcmds and extcmds[0] not in cmds:
+ base.logger.critical(_('Invalid history sub-command, use: %s.'),
+ ", ".join(cmds))
+ raise cli.CliError
+ if extcmds and extcmds[0] in ('repeat', 'redo', 'undo', 'new'):
+ checkRootUID(base)
+ checkGPGKey(base)
+
+ def doCommand(self, base, basecmd, extcmds):
+ vcmd = 'list'
+ if extcmds:
+ vcmd = extcmds[0]
+
+ if False: pass
+ elif vcmd == 'list':
+ ret = base.historyListCmd(extcmds)
+ elif vcmd == 'info':
+ ret = base.historyInfoCmd(extcmds)
+ elif vcmd == 'summary':
+ ret = base.historySummaryCmd(extcmds)
+ elif vcmd == 'undo':
+ ret = self._hcmd_undo(base, extcmds)
+ elif vcmd in ('redo', 'repeat'):
+ ret = self._hcmd_redo(base, extcmds)
+ elif vcmd == 'new':
+ ret = self._hcmd_new(base, extcmds)
+
+ if ret is None:
+ return 0, ['history %s' % (vcmd,)]
+ return ret
+
+ def needTs(self, base, basecmd, extcmds):
+ vcmd = 'list'
+ if extcmds:
+ vcmd = extcmds[0]
+ return vcmd in ('repeat', 'redo', 'undo')
diff --git a/yummain.py b/yummain.py
index 964975b..b2a09cc 100755
--- a/yummain.py
+++ b/yummain.py
@@ -31,7 +31,7 @@ from yum import _
from yum.i18n import to_unicode
import yum.misc
import cli
-
+from utils import suppress_keyboard_interrupt_message
def main(args):
"""This does all the real work"""
@@ -307,12 +307,18 @@ def user_main(args, exit_code=False):
errcode = cprof(main, args)
if os.environ['YUM_PROF'] == 'hotshot':
errcode = hotshot(main, args)
+ if 'YUM_PDB' in os.environ:
+ import pdb
+ pdb.run(main(args))
+
if errcode is None:
errcode = main(args)
if exit_code:
sys.exit(errcode)
return errcode
+suppress_keyboard_interrupt_message()
+
if __name__ == "__main__":
try:
user_main(sys.argv[1:], exit_code=True)