diff --git a/cli.py b/cli.py
index 640f190..2267b86 100644
--- a/cli.py
+++ b/cli.py
@@ -45,6 +45,11 @@ import yumcommands
from yum.i18n import to_unicode, to_utf8
+# This is for yum-utils/yumdownloader in RHEL-5, where it isn't importing this
+# directly but did do "from cli import *", and we did have this in 3.2.22. I
+# just _love_ how python re-exports these by default.
+from yum.packages import parsePackages
+
def sigquit(signum, frame):
""" SIGQUIT handler for the yum cli. """
print >> sys.stderr, "Quit signal sent - exiting immediately"
@@ -73,6 +78,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
self.logger = logging.getLogger("yum.cli")
self.verbose_logger = logging.getLogger("yum.verbose.cli")
self.yum_cli_commands = {}
+ self.use_txmbr_in_callback = True
self.registerCommand(yumcommands.InstallCommand())
self.registerCommand(yumcommands.UpdateCommand())
self.registerCommand(yumcommands.InfoCommand())
@@ -504,30 +510,35 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
if self.gpgsigcheck(downloadpkgs) != 0:
return 1
- if self.conf.rpm_check_debug:
- rcd_st = time.time()
- self.verbose_logger.log(yum.logginglevels.INFO_2,
- _('Running rpm_check_debug'))
- msgs = self._run_rpm_check_debug()
- if msgs:
- rpmlib_only = True
- for msg in msgs:
- if msg.startswith('rpmlib('):
- continue
- rpmlib_only = False
- if rpmlib_only:
- print _("ERROR You need to update rpm to handle:")
- else:
- print _('ERROR with rpm_check_debug vs depsolve:')
+ self.initActionTs()
+ # save our dsCallback out
+ dscb = self.dsCallback
+ self.dsCallback = None # dumb, dumb dumb dumb!
+ self.populateTs(keepold=0) # sigh
- for msg in msgs:
- print to_utf8(msg)
+ rcd_st = time.time()
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Running Transaction Check'))
+ msgs = self._run_rpm_check()
+ if msgs:
+ rpmlib_only = True
+ for msg in msgs:
+ if msg.startswith('rpmlib('):
+ continue
+ rpmlib_only = False
+ if rpmlib_only:
+ print _("ERROR You need to update rpm to handle:")
+ else:
+ print _('ERROR with transaction check vs depsolve:')
- if rpmlib_only:
- return 1, [_('RPM needs to be updated')]
- return 1, [_('Please report this error in %s') % self.conf.bugtracker_url]
+ for msg in msgs:
+ print to_utf8(msg)
- self.verbose_logger.debug('rpm_check_debug time: %0.3f' % (time.time() - rcd_st))
+ if rpmlib_only:
+ return 1, [_('RPM needs to be updated')]
+ return 1, [_('Please report this error in %s') % self.conf.bugtracker_url]
+
+ self.verbose_logger.debug('Transaction Check time: %0.3f' % (time.time() - rcd_st))
tt_st = time.time()
self.verbose_logger.log(yum.logginglevels.INFO_2,
@@ -535,14 +546,10 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
if not self.conf.diskspacecheck:
self.tsInfo.probFilterFlags.append(rpm.RPMPROB_FILTER_DISKSPACE)
+ self.ts.order() # order the transaction
+ self.ts.clean() # release memory not needed beyond this point
testcb = RPMTransaction(self, test=True)
-
- self.initActionTs()
- # save our dsCallback out
- dscb = self.dsCallback
- self.dsCallback = None # dumb, dumb dumb dumb!
- self.populateTs(keepold=0) # sigh
tserrors = self.ts.test(testcb)
del testcb
@@ -555,7 +562,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
self.errorSummary(errstring)
self.verbose_logger.log(yum.logginglevels.INFO_2,
_('Transaction Test Succeeded'))
- del self.ts
self.verbose_logger.debug('Transaction Test time: %0.3f' % (time.time() - tt_st))
@@ -563,10 +569,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
signal.signal(signal.SIGQUIT, signal.SIG_DFL)
ts_st = time.time()
- self.initActionTs() # make a new, blank ts to populate
- self.populateTs(keepold=0) # populate the ts
- self.ts.check() #required for ordering
- self.ts.order() # order
# put back our depcheck callback
self.dsCallback = dscb
@@ -629,7 +631,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
", ".join(matches))
self.verbose_logger.log(yum.logginglevels.INFO_2, to_unicode(msg))
- def _checkMaybeYouMeant(self, arg, always_output=True):
+ def _checkMaybeYouMeant(self, arg, always_output=True, rpmdb_only=False):
""" If the update/remove argument doesn't match with case, or due
to not being installed, tell the user. """
# always_output is a wart due to update/remove not producing the
@@ -638,7 +640,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
# skip it.
if not arg or arg[0] == '@':
return
- matches = self.doPackageLists(patterns=[arg], ignore_case=False)
+
+ pkgnarrow='all'
+ if rpmdb_only:
+ pkgnarrow='installed'
+
+ matches = self.doPackageLists(pkgnarrow=pkgnarrow, patterns=[arg], ignore_case=False)
if (matches.installed or (not matches.available and
self.returnInstalledPackagesByDep(arg))):
return # Found a match so ignore
@@ -651,7 +658,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return
# No package name, so do the maybeYouMeant thing here too
- matches = self.doPackageLists(patterns=[arg], ignore_case=True)
+ matches = self.doPackageLists(pkgnarrow=pkgnarrow, patterns=[arg], ignore_case=True)
if not matches.installed and matches.available:
self.verbose_logger.log(yum.logginglevels.INFO_2,
_('Package(s) %s%s%s available, but not installed.'),
@@ -822,7 +829,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
for arg in userlist:
rms = self.remove(pattern=arg)
if not rms:
- self._checkMaybeYouMeant(arg, always_output=False)
+ self._checkMaybeYouMeant(arg, always_output=False, rpmdb_only=True)
all_rms.extend(rms)
if all_rms:
@@ -1063,13 +1070,16 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
os.path.exists(arg))):
thispkg = yum.packages.YumUrlPackage(self, self.ts, arg)
pkgs.append(thispkg)
+ elif self.conf.showdupesfromrepos:
+ pkgs.extend(self.pkgSack.returnPackages(patterns=[arg]))
else:
- ematch, match, unmatch = self.pkgSack.matchPackageNames([arg])
- for po in ematch + match:
- pkgs.append(po)
+ try:
+ pkgs.extend(self.pkgSack.returnNewestByName(patterns=[arg]))
+ except yum.Errors.PackageSackError:
+ pass
- results = self.findDeps(pkgs)
- self.depListOutput(results)
+ results = self.findDeps(pkgs)
+ self.depListOutput(results)
return 0, []
diff --git a/docs/yum.8 b/docs/yum.8
index 52f6b53..360a976 100644
--- a/docs/yum.8
+++ b/docs/yum.8
@@ -73,7 +73,7 @@ gnome\-packagekit application\&.
.br
.I \fR * version [ all | installed | available | group-* | nogroups* | grouplist | groupinfo ]
.br
-.I \fR * history [info|list|summary|redo|undo|new|addon-info]
+.I \fR * history [info|list|packages-list|summary|redo|undo|new|addon-info]
.br
.I \fR * check
.br
@@ -253,7 +253,10 @@ on groups, files, provides, filelists and rpm files just like the "install" comm
.IP
.IP "\fBdeplist\fP"
Produces a list of all dependencies and what packages provide those
-dependencies for the given packages.
+dependencies for the given packages. As of 3.2.30 it now just shows the latest
+version of each package that matches (this can be changed by
+using --showduplicates) and it only shows the newest providers (which can be
+changed by using --verbose).
.IP
.IP "\fBrepolist\fP"
Produces a list of configured repositories. The default is to list all
@@ -316,8 +319,12 @@ The undo/redo commands take either a transaction id or the keyword last and
an offset from the last transaction (Eg. if you've done 250 transactions,
"last" refers to transaction 250, and "last-4" refers to transaction 246).
+The addon-info command takes a transaction ID, and the packages-list command
+takes a package (with wildcards).
+
In "history list" output the Altered column also gives some extra information
-if there was something not good with the transaction.
+if there was something not good with the transaction (this is also shown at the
+end of the package column in the packages-list command).
.I \fB>\fR - The rpmdb was changed, outside yum, after the transaction.
.br
@@ -402,7 +409,11 @@ Doesn't limit packages to their latest versions in the info, list and search
commands (will also affect plugins which use the doPackageLists() API).
.IP "\fB\-\-installroot=root\fP"
Specifies an alternative installroot, relative to which all packages will be
-installed.
+installed. Think of this like doing "chroot <root> yum" except using
+\-\-installroot allows yum to work before the chroot is created.
+Note: You may also want to use the option \-\-releasever=/ when creating the
+installroot as otherwise the $releasever value is taken from the rpmdb within
+the installroot (and thus. will be empty, before creation).
.br
Configuration Option: \fBinstallroot\fP
.IP "\fB\-\-enablerepo=repoidglob\fP"
@@ -458,9 +469,11 @@ Configuration Option: \fBskip_broken\fP
.br
.IP "\fB\-\-releasever=version\fP"
Pretend the current release version is the given string. This is very useful
-when combined with \-\-installroot. Note that with the default upstream cachedir,
-of /var/cache/yum, using this option will corrupt your cache (and you can use
-$releasever in your cachedir configuration to stop this).
+when combined with \-\-installroot. You can also use \-\-releasever=/ to take
+the releasever information from outside the installroot.
+Note that with the default upstream cachedir, of /var/cache/yum, using this
+option will corrupt your cache (and you can use $releasever in your cachedir
+configuration to stop this).
.PP
.IP "\fB\-t, \-\-tolerant\fP"
This option currently does nothing.
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
index e1c3480..a535b79 100644
--- a/docs/yum.conf.5
+++ b/docs/yum.conf.5
@@ -474,6 +474,8 @@ bugtrackers.
\fBcolor \fR
Display colorized output automatically, depending on the output terminal,
always (using ANSI codes) or never.
+Default is `auto'.
+Possible values are: auto, never, always.
Command-line option: \fB\-\-color\fP
.IP
diff --git a/etc/yum.bash b/etc/yum.bash
index f4be628..1ccb83d 100644
--- a/etc/yum.bash
+++ b/etc/yum.bash
@@ -176,9 +176,13 @@ _yum()
{
COMPREPLY=()
local yum=$1
- local cur
- type _get_cword &>/dev/null && cur=`_get_cword` || cur=$2
- local prev=$3
+ local cur prev
+ local -a words
+ if type _get_comp_words_by_ref &>/dev/null ; then
+ _get_comp_words_by_ref cur prev words
+ else
+ cur=$2 prev=$3 words=("${COMP_WORDS[@]}")
+ fi
# Commands offered as completions
local cmds=( check check-update clean deplist distro-sync downgrade
groupinfo groupinstall grouplist groupremove help history info install
@@ -186,12 +190,12 @@ _yum()
shell update upgrade version )
local i c cmd subcmd
- for (( i=1; i < ${#COMP_WORDS[@]}-1; i++ )) ; do
- [[ -n $cmd ]] && subcmd=${COMP_WORDS[i]} && break
+ for (( i=1; i < ${#words[@]}-1; i++ )) ; do
+ [[ -n $cmd ]] && subcmd=${words[i]} && break
# Recognize additional commands and aliases
for c in ${cmds[@]} check-rpmdb distribution-synchronization erase \
groupupdate grouperase localinstall localupdate whatprovides ; do
- [[ ${COMP_WORDS[i]} == $c ]] && cmd=$c && break
+ [[ ${words[i]} == $c ]] && cmd=$c && break
done
done
@@ -251,7 +255,7 @@ _yum()
COMPREPLY=( $( compgen -W 'info list summary undo redo
new addon-info package-list' -- "$cur" ) )
;;
- undo|redo|addon|addon-info)
+ undo|redo|repeat|addon|addon-info)
COMPREPLY=( $( compgen -W "last $( $yum -d 0 -C history \
2>/dev/null | \
sed -ne 's/^[[:space:]]*\([0-9]\{1,\}\).*/\1/p' )" \
diff --git a/output.py b/output.py
index b1d92e5..85b21f8 100755
--- a/output.py
+++ b/output.py
@@ -809,20 +809,26 @@ class YumOutput:
def depListOutput(self, results):
"""take a list of findDeps results and 'pretty print' the output"""
- for pkg in results:
+ verb = self.verbose_logger.isEnabledFor(logginglevels.DEBUG_3)
+ for pkg in sorted(results):
print _("package: %s") % pkg.compactPrint()
if len(results[pkg]) == 0:
print _(" No dependencies for this package")
continue
- for req in results[pkg]:
+ for req in sorted(results[pkg]):
reqlist = results[pkg][req]
print _(" dependency: %s") % prco_tuple_to_string(req)
if not reqlist:
print _(" Unsatisfied dependency")
continue
- for po in reqlist:
+ seen = {}
+ for po in reversed(sorted(reqlist)):
+ key = (po.name, po.arch)
+ if not verb and key in seen:
+ continue
+ seen[key] = po
print " provider: %s" % po.compactPrint()
def format_number(self, number, SI=0, space=' '):
@@ -1619,6 +1625,18 @@ to exit.
self._historyInfoCmd(mobj)
+ def _hpkg2from_repo(self, hpkg):
+ """ Given a pkg, find the ipkg.ui_from_repo ... if none, then
+ get an apkg. ... and put a ? in there. """
+ ipkgs = self.rpmdb.searchPkgTuple(hpkg.pkgtup)
+ if not ipkgs:
+ apkgs = self.pkgSack.searchPkgTuple(hpkg.pkgtup)
+ if not apkgs:
+ return '?'
+ return '@?' + str(apkgs[0].repoid)
+
+ return ipkgs[0].ui_from_repo
+
def _historyInfoCmd(self, old, pats=[]):
name = self._pwd_ui_username(old.loginuid)
@@ -1631,7 +1649,8 @@ to exit.
_pkg_states_available.values())])[-1]
_pkg_states_installed['maxlen'] = maxlen
_pkg_states_available['maxlen'] = maxlen
- def _simple_pkg(pkg, prefix_len, was_installed=False, highlight=False):
+ def _simple_pkg(pkg, prefix_len, was_installed=False, highlight=False,
+ pkg_max_len=0):
prefix = " " * prefix_len
if was_installed:
_pkg_states = _pkg_states_installed
@@ -1655,7 +1674,9 @@ to exit.
else:
(hibeg, hiend) = self._highlight('normal')
state = utf8_width_fill(state, _pkg_states['maxlen'])
- print "%s%s%s%s %s" % (prefix, hibeg, state, hiend, hpkg)
+ print "%s%s%s%s %-*s %s" % (prefix, hibeg, state, hiend,
+ pkg_max_len, hpkg,
+ self._hpkg2from_repo(hpkg))
if type(old.tid) == type([]):
print _("Transaction ID :"), "%u..%u" % (old.tid[0], old.tid[-1])
@@ -1726,30 +1747,37 @@ to exit.
addon_info = self.history.return_addon_data(old.tid)
# for the ones we create by default - don't display them as there
- default_addons = set(['config-main', 'config-repos'])
+ default_addons = set(['config-main', 'config-repos', 'saved_tx'])
non_default = set(addon_info).difference(default_addons)
if len(non_default) > 0:
print _("Additional non-default information stored: %d"
% len(non_default))
- print _("Transaction performed with:")
+ if old.trans_with:
+ # This is _possible_, but not common
+ print _("Transaction performed with:")
+ pkg_max_len = max((len(str(hpkg)) for hpkg in old.trans_with))
for hpkg in old.trans_with:
- _simple_pkg(hpkg, 4, was_installed=True)
+ _simple_pkg(hpkg, 4, was_installed=True, pkg_max_len=pkg_max_len)
print _("Packages Altered:")
self.historyInfoCmdPkgsAltered(old, pats)
if old.trans_skip:
print _("Packages Skipped:")
+ pkg_max_len = max((len(str(hpkg)) for hpkg in old.trans_skip))
for hpkg in old.trans_skip:
- _simple_pkg(hpkg, 4)
+ _simple_pkg(hpkg, 4, pkg_max_len=pkg_max_len)
if old.rpmdb_problems:
print _("Rpmdb Problems:")
for prob in old.rpmdb_problems:
key = "%s%s: " % (" " * 4, prob.problem)
print self.fmtKeyValFill(key, prob.text)
+ if prob.packages:
+ pkg_max_len = max((len(str(hpkg)) for hpkg in prob.packages))
for hpkg in prob.packages:
- _simple_pkg(hpkg, 8, was_installed=True, highlight=hpkg.main)
+ _simple_pkg(hpkg, 8, was_installed=True, highlight=hpkg.main,
+ pkg_max_len=pkg_max_len)
if old.output:
print _("Scriptlet output:")
@@ -1783,10 +1811,13 @@ to exit.
# version in the transaction and now.
all_uistates = self._history_state2uistate
maxlen = 0
+ pkg_max_len = 0
for hpkg in old.trans_data:
uistate = all_uistates.get(hpkg.state, hpkg.state)
if maxlen < len(uistate):
maxlen = len(uistate)
+ if pkg_max_len < len(str(hpkg)):
+ pkg_max_len = len(str(hpkg))
for hpkg in old.trans_data:
prefix = " " * 4
@@ -1813,18 +1844,18 @@ to exit.
hpkg.state == 'Update'):
ln = len(hpkg.name) + 1
cn = (" " * ln) + cn[ln:]
- print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn)
elif (last is not None and
last.state == 'Downgrade' and last.name == hpkg.name and
hpkg.state == 'Downgraded'):
ln = len(hpkg.name) + 1
cn = (" " * ln) + cn[ln:]
- print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn)
else:
last = None
if hpkg.state in ('Updated', 'Downgrade'):
last = hpkg
- print "%s%s%s%s %s" % (prefix, hibeg, uistate, hiend, cn)
+ print "%s%s%s%s %-*s %s" % (prefix, hibeg, uistate, hiend,
+ pkg_max_len, cn,
+ self._hpkg2from_repo(hpkg))
def historySummaryCmd(self, extcmds):
tids, printall = self._history_list_transactions(extcmds)
@@ -1936,6 +1967,9 @@ to exit.
of a package(s) instead of via. transactions. """
tids = self.history.search(extcmds)
limit = None
+ if extcmds and not tids:
+ self.logger.critical(_('Bad transaction IDs, or package(s), given'))
+ return 1, ['Failed history packages-list']
if not tids:
limit = 20
diff --git a/rpmUtils/transaction.py b/rpmUtils/transaction.py
index e8f4459..121ad5b 100644
--- a/rpmUtils/transaction.py
+++ b/rpmUtils/transaction.py
@@ -22,18 +22,13 @@ ts = None
class TransactionWrapper:
def __init__(self, root='/'):
self.ts = rpm.TransactionSet(root)
- self._methods = ['dbMatch',
- 'check',
+ self._methods = ['check',
'order',
'addErase',
'addInstall',
'run',
- 'IDTXload',
- 'IDTXglob',
- 'rollback',
'pgpImportPubkey',
'pgpPrtPkts',
- 'Debug',
'problems',
'setFlags',
'setVSFlags',
@@ -54,6 +49,17 @@ class TransactionWrapper:
self.ts = None
self.open = False
+ def dbMatch(self, *args, **kwds):
+ if 'patterns' in kwds:
+ patterns = kwds.pop('patterns')
+ else:
+ patterns = []
+
+ mi = self.ts.dbMatch(*args, **kwds)
+ for (tag, tp, pat) in patterns:
+ mi.pattern(tag, tp, pat)
+ return mi
+
def __getattr__(self, attr):
if attr in self._methods:
return self.getMethod(attr)
@@ -91,6 +97,9 @@ class TransactionWrapper:
def isTsFlagSet(self, flag):
val = self.getTsFlags()
return bool(flag & val)
+
+ def setScriptFd(self, fd):
+ self.ts.scriptFd = fd.fileno()
# def addProblemFilter(self, filt):
# curfilter = self.ts.setProbFilter(0)
@@ -100,12 +109,14 @@ class TransactionWrapper:
"""tests the ts we've setup, takes a callback function and a conf dict
for flags and what not"""
+ origflags = self.getTsFlags()
self.addTsFlag(rpm.RPMTRANS_FLAG_TEST)
# FIXME GARBAGE - remove once this is reimplemented elsehwere
# KEEPING FOR API COMPLIANCE ONLY
if conf.get('diskspacecheck') == 0:
self.ts.setProbFilter(rpm.RPMPROB_FILTER_DISKSPACE)
tserrors = self.ts.run(cb.callback, '')
+ self.ts.setFlags(origflags)
reserrors = []
if tserrors:
diff --git a/test/skipbroken-tests.py b/test/skipbroken-tests.py
index 4e6b2c8..36a4a6d 100644
--- a/test/skipbroken-tests.py
+++ b/test/skipbroken-tests.py
@@ -1,8 +1,11 @@
import unittest
import logging
import sys
+import re
from testbase import *
+REGEX_PKG = re.compile(r"(\d*):?(.*)-(.*)-(.*)\.(.*)$")
+
class SkipBrokenTests(DepsolveTests):
''' Test cases to test skip-broken'''
@@ -20,6 +23,36 @@ class SkipBrokenTests(DepsolveTests):
po = FakePackage(name, version, release, epoch, arch, repo=self.repo)
self.rpmdb.addPackage(po)
return po
+
+ def _pkgstr_to_nevra(self, pkg_str):
+ '''
+ Get a nevra from from a epoch:name-version-release.arch string
+ @param pkg_str: package string
+ '''
+ res = REGEX_PKG.search(pkg_str)
+ if res:
+ (e,n,v,r,a) = res.groups()
+ if e == "":
+ e = "0"
+ return (n,e,v,r,a)
+ else:
+ raise AttributeError("Illegal package string : %s" % pkg_str)
+
+ def repoString(self, pkg_str):
+ '''
+ Add an available package from a epoch:name-version-release.arch string
+ '''
+ (n,e,v,r,a) = self._pkgstr_to_nevra(pkg_str)
+ return self.repoPackage(n,v,r,e,a)
+
+
+ def instString(self, pkg_str):
+ '''
+ Add an installed package from a epoch:name-version-release.arch string
+ '''
+ (n,e,v,r,a) = self._pkgstr_to_nevra(pkg_str)
+ return self.instPackage(n,v,r,e,a)
+
def testMissingReqNoSkip(self):
''' install fails, because of missing req.
@@ -669,8 +702,37 @@ class SkipBrokenTests(DepsolveTests):
self.tsInfo.addUpdate(u7, oldpo=i7)
self.assertEquals('ok', *self.resolveCode(skip=True))
# uncomment this line and the test will fail and you can see the output
- self.assertResult([i1])
+ # self.assertResult([i1])
+ def test_conflict_looping(self):
+ '''
+ Skip-broken is looping
+ https://bugzilla.redhat.com/show_bug.cgi?id=681806
+ '''
+ members = [] # the result after the transaction
+ # Installed package conflicts with u1
+ i0 = self.instString('kde-l10n-4.6.0-3.fc15.1.noarch')
+ i0.addConflicts('kdepim', 'GT', ('6', '4.5.9', '0'))
+ members.append(i0)
+ i1 = self.instString('6:kdepim-4.5.94.1-1.fc14.x86_64')
+ u1 = self.repoString('7:kdepim-4.4.10-1.fc15.x86_64')
+ self.tsInfo.addUpdate(u1, oldpo=i1)
+ # u1 should be removed, because of the conflict
+ members.append(i1)
+ i2 = self.instString('6:kdepim-libs-4.5.94.1-1.fc14.x86_64')
+ u2 = self.repoString('7:kdepim-libs-4.4.10-1.fc15.x86_64')
+ self.tsInfo.addUpdate(u2, oldpo=i2)
+ members.append(u2)
+ i3 = self.instString('kdepim-runtime-libs-4.5.94.1-2.fc14.x86_64')
+ u3 = self.repoString('1:kdepim-runtime-libs-4.4.10-2.fc15.x86_64')
+ self.tsInfo.addUpdate(u3, oldpo=i3)
+ members.append(u3)
+ i4 = self.instString('kdepim-runtime-4.5.94.1-2.fc14.x86_64')
+ u4 = self.repoString('1:kdepim-runtime-4.4.10-2.fc15.x86_64')
+ self.tsInfo.addUpdate(u4, oldpo=i4)
+ members.append(u4)
+ self.assertEquals('ok', *self.resolveCode(skip=True))
+ self.assertResult(members)
def resolveCode(self,skip = False):
diff --git a/yum.spec b/yum.spec
index a1fbc72..65a2397 100644
--- a/yum.spec
+++ b/yum.spec
@@ -194,8 +194,8 @@ exit 0
%defattr(-,root,root)
%doc COPYING
%{_sysconfdir}/cron.daily/0yum.cron
-%{_sysconfdir}/yum/yum-daily.yum
-%{_sysconfdir}/yum/yum-weekly.yum
+%config(noreplace) %{_sysconfdir}/yum/yum-daily.yum
+%config(noreplace) %{_sysconfdir}/yum/yum-weekly.yum
%{_sysconfdir}/rc.d/init.d/yum-cron
%config(noreplace) %{_sysconfdir}/sysconfig/yum-cron
diff --git a/yum/__init__.py b/yum/__init__.py
index f6e8a6b..36fc203 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -349,7 +349,10 @@ class YumBase(depsolve.Depsolve):
# who are we:
self.conf.uid = os.geteuid()
-
+ # repos are ver/arch specific so add $basearch/$releasever
+ self.conf._repos_persistdir = os.path.normpath('%s/repos/%s/%s/'
+ % (self.conf.persistdir, self.yumvar.get('basearch', '$basearch'),
+ self.yumvar.get('releasever', '$releasever')))
self.doFileLogSetup(self.conf.uid, self.conf.logfile)
self.verbose_logger.debug('Config time: %0.3f' % (time.time() - conf_st))
self.plugins.run('init')
@@ -418,10 +421,7 @@ class YumBase(depsolve.Depsolve):
else:
thisrepo.repo_config_age = repo_age
thisrepo.repofile = repofn
- # repos are ver/arch specific so add $basearch/$releasever
- self.conf._repos_persistdir = os.path.normpath('%s/repos/%s/%s/'
- % (self.conf.persistdir, self.yumvar.get('basearch', '$basearch'),
- self.yumvar.get('releasever', '$releasever')))
+
thisrepo.base_persistdir = self.conf._repos_persistdir
@@ -574,6 +574,11 @@ class YumBase(depsolve.Depsolve):
self.getReposFromConfig()
+ # For rhnplugin, and in theory other stuff, calling
+ # .getReposFromConfig() recurses back into this function but only once.
+ # This means that we have two points on the stack leaving the above call
+ # but only one of them can do the repos setup. BZ 678043.
+ if hasattr(self, 'prerepoconf'):
# Recursion
prerepoconf = self.prerepoconf
del self.prerepoconf
@@ -1024,6 +1029,11 @@ class YumBase(depsolve.Depsolve):
for txmbr in txmbrs:
if kern_pkgtup is not None and txmbr.pkgtup == kern_pkgtup:
pass
+ elif kern_pkgtup is not None and txmbr.name == kern_pkgtup[0]:
+ # We don't care if they've explicitly set protected on the
+ # kernel package. Because we don't allow you to uninstall the
+ # running one so it has _special_ semantics anyway.
+ continue
elif txmbr.name not in protected:
continue
if txmbr.name not in bad_togo:
@@ -1435,12 +1445,17 @@ class YumBase(depsolve.Depsolve):
# will be we store what we thought, not what happened (so it'll be an
# invalid cache).
self.rpmdb.transactionResultVersion(frpmdbv)
-
# transaction has started - all bets are off on our saved ts file
- try:
- os.unlink(self._ts_save_file)
- except (IOError, OSError), e:
- pass
+ if self._ts_save_file is not None:
+ # write the saved transaction data to the addon location in history
+ # so we can pull it back later if we need to
+ savetx_msg = open(self._ts_save_file, 'r').read()
+ self.history.write_addon_data('saved_tx', savetx_msg)
+
+ try:
+ os.unlink(self._ts_save_file)
+ except (IOError, OSError), e:
+ pass
self._ts_save_file = None
errors = self.ts.run(cb.callback, '')
@@ -1485,7 +1500,12 @@ class YumBase(depsolve.Depsolve):
# drop out the rpm cache so we don't step on bad hdr indexes
- self.rpmdb.dropCachedDataPostTransaction(list(self.tsInfo))
+ if (self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST) or
+ resultobject.return_code):
+ self.rpmdb.dropCachedData()
+ else:
+ self.rpmdb.dropCachedDataPostTransaction(list(self.tsInfo))
+
self.plugins.run('posttrans')
# sync up what just happened versus what is in the rpmdb
if not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST):
@@ -1674,8 +1694,11 @@ class YumBase(depsolve.Depsolve):
def doLock(self, lockfile = YUM_PID_FILE):
"""perform the yum locking, raise yum-based exceptions, not OSErrors"""
- # if we're not root then lock the cache
if self.conf.uid != 0:
+ # If we are a user, assume we are using the root cache ... so don't
+ # bother locking.
+ if self.conf.cache:
+ return
root = self.conf.cachedir
# Don't want <cachedir>/var/run/yum.pid ... just: <cachedir>/yum.pid
lockfile = os.path.basename(lockfile)
@@ -1690,7 +1713,7 @@ class YumBase(depsolve.Depsolve):
fd = open(lockfile, 'r')
except (IOError, OSError), e:
msg = _("Could not open lock %s: %s") % (lockfile, e)
- raise Errors.LockError(1, msg)
+ raise Errors.LockError(errno.EPERM, msg)
try: oldpid = int(fd.readline())
except ValueError:
@@ -1707,7 +1730,7 @@ class YumBase(depsolve.Depsolve):
else:
# Whoa. What the heck happened?
msg = _('Unable to check if PID %s is active') % oldpid
- raise Errors.LockError(1, msg, oldpid)
+ raise Errors.LockError(errno.EPERM, msg, oldpid)
else:
# Another copy seems to be running.
msg = _('Existing lock %s: another copy is running as pid %s.') % (lockfile, oldpid)
@@ -1752,7 +1775,7 @@ class YumBase(depsolve.Depsolve):
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)
+ raise Errors.LockError(msg.errno, errmsg, int(contents))
return 0
else:
os.write(fd, contents)
@@ -3417,7 +3440,6 @@ class YumBase(depsolve.Depsolve):
pkgs = po.obsoletedBy(pkgs, limit=1)
if pkgs:
already_obs = pkgs[0]
- continue
if already_obs:
self.verbose_logger.warning(_('Package %s is obsoleted by %s which is already installed'),
@@ -3934,11 +3956,17 @@ class YumBase(depsolve.Depsolve):
if (po.arch != installed_pkg.arch and
(isMultiLibArch(po.arch) or
isMultiLibArch(installed_pkg.arch))):
- installpkgs.append(po)
+ if updateonly:
+ self.logger.warning(_('Package %s.%s not installed, cannot update it. Run yum install to install it instead.'), po.name, po.arch)
+ else:
+ installpkgs.append(po)
else:
donothingpkgs.append(po)
elif self.allowedMultipleInstalls(po):
- installpkgs.append(po)
+ if updateonly:
+ self.logger.warning(_('Package %s.%s not installed, cannot update it. Run yum install to install it instead.'), po.name, po.arch)
+ else:
+ installpkgs.append(po)
else:
donothingpkgs.append(po)
@@ -4462,17 +4490,20 @@ class YumBase(depsolve.Depsolve):
be imported using askcb.
@param po: Package object to retrieve the key of.
- @param askcb: Callback function to use for asking for verification.
+ @param askcb: Callback function to use for asking for permission to
+ import a key. This is verification, but also "choice".
Takes arguments of the po, the userid for the key, and
the keyid.
- @param fullaskcb: Callback function to use for asking for verification
- of a key. Differs from askcb in that it gets passed
- a dictionary so that we can expand the values passed.
+ @param fullaskcb: Callback function to use for asking for permission to
+ import a key. This is verification, but also "choice".
+ Differs from askcb in that it gets passed a
+ dictionary so that we can expand the values passed.
"""
repo = self.repos.getRepo(po.repoid)
keyurls = repo.gpgkey
key_installed = False
+ user_cb_fail = False
for keyurl in keyurls:
keys = self._retrievePublicKey(keyurl, repo)
@@ -4509,7 +4540,8 @@ class YumBase(depsolve.Depsolve):
rc = askcb(po, info['userid'], info['hexkeyid'])
if not rc:
- raise Errors.YumBaseError, _("Not installing key")
+ user_cb_fail = True
+ continue
# Import the key
ts = self.rpmdb.readOnlyTS()
@@ -4520,6 +4552,9 @@ class YumBase(depsolve.Depsolve):
self.logger.info(_('Key imported successfully'))
key_installed = True
+ if not key_installed and user_cb_fail:
+ raise Errors.YumBaseError, _("Didn't install any keys")
+
if not key_installed:
raise Errors.YumBaseError, \
_('The GPG keys listed for the "%s" repository are ' \
@@ -4543,11 +4578,13 @@ class YumBase(depsolve.Depsolve):
@param destdir: destination of the gpg pub ring
@param keyurl_list: list of urls for gpg keys
@param is_cakey: bool - are we pulling in a ca key or not
- @param callback: Callback function to use for asking for verification
- of a key. Takes a dictionary of key info.
+ @param callback: Callback function to use for asking for permission to
+ import a key. This is verification, but also "choice".
+ Takes a dictionary of key info.
"""
key_installed = False
+ user_cb_fail = False
for keyurl in keyurl_list:
keys = self._retrievePublicKey(keyurl, repo, getSig=not is_cakey)
for info in keys:
@@ -4557,16 +4594,25 @@ class YumBase(depsolve.Depsolve):
keyurl, info['hexkeyid']))
key_installed = True
continue
-
# Try installing/updating GPG key
if is_cakey:
+ # know where the 'imported_cakeys' file is
+ ikf = repo.base_persistdir + '/imported_cakeys'
keytype = 'CA'
+ cakeys = []
+ try:
+ cakeys_d = open(ikf, 'r').read()
+ cakeys = cakeys_d.split('\n')
+ except (IOError, OSError):
+ pass
+ if str(info['hexkeyid']) in cakeys:
+ key_installed = True
else:
keytype = 'GPG'
-
- if repo.gpgcakey and info['has_sig'] and info['valid_sig']:
- key_installed = True
- else:
+ if repo.gpgcakey and info['has_sig'] and info['valid_sig']:
+ key_installed = True
+
+ if not key_installed:
self._getKeyImportMessage(info, keyurl, keytype)
rc = False
if self.conf.assumeyes:
@@ -4579,7 +4625,8 @@ class YumBase(depsolve.Depsolve):
if not rc:
- raise Errors.YumBaseError, _("Not installing key for repo %s") % repo
+ user_cb_fail = True
+ continue
# Import the key
result = misc.import_key_to_pubring(info['raw_key'], info['hexkeyid'], gpgdir=destdir)
@@ -4587,6 +4634,20 @@ class YumBase(depsolve.Depsolve):
raise Errors.YumBaseError, _('Key import failed')
self.logger.info(_('Key imported successfully'))
key_installed = True
+ # write out the key id to imported_cakeys in the repos basedir
+ if is_cakey and key_installed:
+ if info['hexkeyid'] not in cakeys:
+ ikfo = open(ikf, 'a')
+ try:
+ ikfo.write(info['hexkeyid']+'\n')
+ ikfo.flush()
+ ikfo.close()
+ except (IOError, OSError):
+ # maybe a warning - but in general this is not-critical, just annoying to the user
+ pass
+
+ if not key_installed and user_cb_fail:
+ raise Errors.YumBaseError, _("Didn't install any keys for repo %s") % repo
if not key_installed:
raise Errors.YumBaseError, \
@@ -4775,26 +4836,31 @@ class YumBase(depsolve.Depsolve):
def _doTestTransaction(self,callback,display=None):
''' Do the RPM test transaction '''
+ self.initActionTs()
+ # save our dsCallback out
+ dscb = self.dsCallback
+ self.dsCallback = None # dumb, dumb dumb dumb!
+ self.populateTs( keepold=0 ) # sigh
+
# This can be overloaded by a subclass.
- if self.conf.rpm_check_debug:
- self.verbose_logger.log(logginglevels.INFO_2,
- _('Running rpm_check_debug'))
- msgs = self._run_rpm_check_debug()
- if msgs:
- rpmlib_only = True
- for msg in msgs:
- if msg.startswith('rpmlib('):
- continue
- rpmlib_only = False
- if rpmlib_only:
- retmsgs = [_("ERROR You need to update rpm to handle:")]
- retmsgs.extend(msgs)
- raise Errors.YumRPMCheckError, retmsgs
- retmsgs = [_('ERROR with rpm_check_debug vs depsolve:')]
- retmsgs.extend(msgs)
- retmsgs.append(_('Please report this error at %s')
- % self.conf.bugtracker_url)
- raise Errors.YumRPMCheckError,retmsgs
+ self.verbose_logger.log(logginglevels.INFO_2,
+ _('Running Transaction Check'))
+ msgs = self._run_rpm_check()
+ if msgs:
+ rpmlib_only = True
+ for msg in msgs:
+ if msg.startswith('rpmlib('):
+ continue
+ rpmlib_only = False
+ if rpmlib_only:
+ retmsgs = [_("ERROR You need to update rpm to handle:")]
+ retmsgs.extend(msgs)
+ raise Errors.YumRPMCheckError, retmsgs
+ retmsgs = [_('ERROR with transaction check vs depsolve:')]
+ retmsgs.extend(msgs)
+ retmsgs.append(_('Please report this error at %s')
+ % self.conf.bugtracker_url)
+ raise Errors.YumRPMCheckError,retmsgs
tsConf = {}
for feature in ['diskspacecheck']: # more to come, I'm sure
@@ -4804,14 +4870,7 @@ class YumBase(depsolve.Depsolve):
# overwrite the default display class
if display:
testcb.display = display
- # clean out the ts b/c we have to give it new paths to the rpms
- del self.ts
- self.initActionTs()
- # save our dsCallback out
- dscb = self.dsCallback
- self.dsCallback = None # dumb, dumb dumb dumb!
- self.populateTs( keepold=0 ) # sigh
tserrors = self.ts.test( testcb, conf=tsConf )
del testcb
@@ -4839,12 +4898,8 @@ class YumBase(depsolve.Depsolve):
cb.display = display
self.runTransaction( cb=cb )
- def _run_rpm_check_debug(self):
+ def _run_rpm_check(self):
results = []
- # save our dsCallback out
- dscb = self.dsCallback
- self.dsCallback = None # dumb, dumb dumb dumb!
- self.populateTs(test=1)
self.ts.check()
for prob in self.ts.problems():
# Newer rpm (4.8.0+) has problem objects, older have just strings.
@@ -4852,7 +4907,6 @@ class YumBase(depsolve.Depsolve):
# now just be compatible.
results.append(to_str(prob))
- self.dsCallback = dscb
return results
def add_enable_repo(self, repoid, baseurls=[], mirrorlist=None, **kwargs):
diff --git a/yum/config.py b/yum/config.py
index 97e5e3d..8c966f8 100644
--- a/yum/config.py
+++ b/yum/config.py
@@ -691,6 +691,7 @@ class YumConf(StartupConf):
metadata_expire = SecondsOption(60 * 60 * 6) # Time in seconds (6h).
# Time in seconds (1 day). NOTE: This isn't used when using metalinks
mirrorlist_expire = SecondsOption(60 * 60 * 24)
+ # XXX rpm_check_debug is unused, left around for API compatibility for now
rpm_check_debug = BoolOption(True)
disable_excludes = ListOption()
skip_broken = BoolOption(False)
@@ -1050,10 +1051,24 @@ def writeRawRepoFile(repo,only=None):
# Updated the ConfigParser with the changed values
cfgOptions = repo.cfg.options(repo.id)
for name,value in repo.iteritems():
+ if value is None: # Proxy
+ continue
+
+ if only is not None and name not in only:
+ continue
+
option = repo.optionobj(name)
- if option.default != value or name in cfgOptions :
- if only == None or name in only:
- ini[section_id][name] = option.tostring(value)
+ ovalue = option.tostring(value)
+ # If the value is the same, but just interpreted ... when we don't want
+ # to keep the interpreted values.
+ if (name in ini[section_id] and
+ ovalue == varReplace(ini[section_id][name], yumvar)):
+ ovalue = ini[section_id][name]
+
+ if name not in cfgOptions and option.default == value:
+ continue
+
+ ini[section_id][name] = ovalue
fp =file(repo.repofile,"w")
fp.write(str(ini))
fp.close()
diff --git a/yum/depsolve.py b/yum/depsolve.py
index de2849a..388811d 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -69,6 +69,8 @@ class Depsolve(object):
self._ts = None
self._tsInfo = None
self.dsCallback = None
+ # Callback-style switch, default to legacy (hdr, file) mode
+ self.use_txmbr_in_callback = False
self.logger = logging.getLogger("yum.Depsolve")
self.verbose_logger = logging.getLogger("yum.verbose.Depsolve")
@@ -220,8 +222,13 @@ class Depsolve(object):
txmbr.ts_state = 'i'
txmbr.output_state = TS_INSTALL
+ # New-style callback with just txmbr instead of full headers?
+ if self.use_txmbr_in_callback:
+ cbkey = txmbr
+ else:
+ cbkey = (hdr, rpmfile)
- self.ts.addInstall(hdr, (hdr, rpmfile), txmbr.ts_state)
+ self.ts.addInstall(hdr, cbkey, txmbr.ts_state)
self.verbose_logger.log(logginglevels.DEBUG_1,
_('Adding Package %s in mode %s'), txmbr.po, txmbr.ts_state)
if self.dsCallback:
@@ -673,11 +680,12 @@ class Depsolve(object):
if len(self.tsInfo) != length and txmbrs:
return CheckDeps, errormsgs
- msg = '%s conflicts with %s' % (name, conflicting_po.name)
+ msg = '%s conflicts with %s' % (name, str(conflicting_po))
errormsgs.append(msg)
self.verbose_logger.log(logginglevels.DEBUG_1, msg)
CheckDeps = False
- self.po_with_problems.add((po,None,errormsgs[-1]))
+ # report the conflicting po, so skip-broken can remove it
+ self.po_with_problems.add((po,conflicting_po,errormsgs[-1]))
return CheckDeps, errormsgs
def _undoDepInstalls(self):
@@ -799,9 +807,9 @@ class Depsolve(object):
continue
done.add((po, err))
self.verbose_logger.log(logginglevels.DEBUG_4,
- _("%s from %s has depsolving problems") % (po, po.repoid))
+ "SKIPBROKEN: %s from %s has depsolving problems" % (po, po.repoid))
err = err.replace('\n', '\n --> ')
- self.verbose_logger.log(logginglevels.DEBUG_4," --> %s" % err)
+ self.verbose_logger.log(logginglevels.DEBUG_4,"SKIPBROKEN: --> %s" % err)
return (1, errors)
if not len(self.tsInfo):
diff --git a/yum/misc.py b/yum/misc.py
index 15e571f..8e81c34 100644
--- a/yum/misc.py
+++ b/yum/misc.py
@@ -252,6 +252,9 @@ class Checksums:
def __len__(self):
return self._len
+ # Note that len(x) is assert limited to INT_MAX, which is 2GB on i686.
+ length = property(fget=lambda self: self._len)
+
def update(self, data):
self._len += len(data)
for sumalgo in self._sumalgos:
@@ -323,7 +326,7 @@ def checksum(sumtype, file, CHUNK=2**16, datasize=None):
data = Checksums([sumtype])
while data.read(fo, CHUNK):
- if datasize is not None and len(data) > datasize:
+ if datasize is not None and data.length > datasize:
break
if type(file) is types.StringType:
@@ -332,7 +335,7 @@ def checksum(sumtype, file, CHUNK=2**16, datasize=None):
# This screws up the length, but that shouldn't matter. We only care
# if this checksum == what we expect.
- if datasize is not None and datasize != len(data):
+ if datasize is not None and datasize != data.length:
return '!%u!%s' % (datasize, data.hexdigest(sumtype))
return data.hexdigest(sumtype)
diff --git a/yum/packages.py b/yum/packages.py
index 6f61fea..db3e973 100644
--- a/yum/packages.py
+++ b/yum/packages.py
@@ -1069,6 +1069,9 @@ class YumAvailablePackage(PackageObject, RpmBase):
if self.sourcerpm:
msg += """ <rpm:sourcerpm>%s</rpm:sourcerpm>\n""" % misc.to_xml(self.sourcerpm)
+ else: # b/c yum 2.4.3 and OLD y-m-p willgfreak out if it is not there.
+ msg += """ <rpm:sourcerpm/>\n"""
+
msg +=""" <rpm:header-range start="%s" end="%s"/>""" % (self.hdrstart,
self.hdrend)
msg += self._dump_pco('provides')
@@ -1243,18 +1246,32 @@ class YumHeaderPackage(YumAvailablePackage):
self.ver = self.version
self.rel = self.release
self.pkgtup = (self.name, self.arch, self.epoch, self.version, self.release)
- # Summaries "can be" empty, which rpm return [], see BZ 473239, *sigh*
- self.summary = self.hdr['summary'] or ''
- self.summary = misc.share_data(self.summary.replace('\n', ''))
- self.description = self.hdr['description'] or ''
- self.description = misc.share_data(self.description)
+ self._loaded_summary = None
+ self._loaded_description = None
self.pkgid = self.hdr[rpm.RPMTAG_SHA1HEADER]
if not self.pkgid:
self.pkgid = "%s.%s" %(self.hdr['name'], self.hdr['buildtime'])
self.packagesize = self.hdr['size']
self.__mode_cache = {}
self.__prcoPopulated = False
-
+
+ def _loadSummary(self):
+ # Summaries "can be" empty, which rpm return [], see BZ 473239, *sigh*
+ if self._loaded_summary is None:
+ summary = self._get_hdr()['summary'] or ''
+ summary = misc.share_data(summary.replace('\n', ''))
+ self._loaded_summary = summary
+ return self._loaded_summary
+ summary = property(lambda x: x._loadSummary())
+
+ def _loadDescription(self):
+ if self._loaded_description is None:
+ description = self._get_hdr()['description'] or ''
+ description = misc.share_data(description)
+ self._loaded_description = description
+ return self._loaded_description
+ description = property(lambda x: x._loadDescription())
+
def __str__(self):
if self.epoch == '0':
val = '%s-%s-%s.%s' % (self.name, self.version, self.release,
@@ -1828,7 +1845,6 @@ class YumInstalledPackage(YumHeaderPackage):
my_mode = my_st.st_mode
if 'ghost' in ftypes: # This is what rpm does, although it
my_mode &= 0777 # doesn't usually get here.
- mode &= 0777
if check_perms and pf.verify_mode and my_mode != pf.mode:
prob = _PkgVerifyProb('mode', 'mode does not match', ftypes)
prob.database_value = pf.mode
diff --git a/yum/parser.py b/yum/parser.py
index e46d611..fccf528 100644
--- a/yum/parser.py
+++ b/yum/parser.py
@@ -144,6 +144,11 @@ class ConfigPreProcessor:
# the current file returned EOF, pop it off the stack.
self._popfile()
+ # if the section is prefixed by a space then it is breaks iniparser/configparser
+ # so fix it
+ broken_sec_match = re.match(r'\s+\[(?P<section>.*)\]', line)
+ if broken_sec_match:
+ line = line.lstrip()
# at this point we have a line from the topmost file on the stack
# or EOF if the stack is empty
if self._vars:
diff --git a/yum/rpmsack.py b/yum/rpmsack.py
index 0982a7c..e93df20 100644
--- a/yum/rpmsack.py
+++ b/yum/rpmsack.py
@@ -42,11 +42,6 @@ class RPMInstalledPackage(YumInstalledPackage):
def __init__(self, rpmhdr, index, rpmdb):
self._has_hdr = True
YumInstalledPackage.__init__(self, rpmhdr, yumdb=rpmdb.yumdb)
- # NOTE: We keep summary/description/url because it doesn't add much
- # and "yum search" uses them all.
- self.url = rpmhdr['url']
- # Also keep sourcerpm for pirut/etc.
- self.sourcerpm = rpmhdr['sourcerpm']
self.idx = index
self.rpmdb = rpmdb
@@ -67,13 +62,19 @@ class RPMInstalledPackage(YumInstalledPackage):
raise Errors.PackageSackError, 'Rpmdb changed underneath us'
def __getattr__(self, varname):
- self.hdr = val = self._get_hdr()
- self._has_hdr = True
- # If these existed, then we wouldn't get here ... and nothing in the DB
- # starts and ends with __'s. So these are missing.
- if varname.startswith('__') and varname.endswith('__'):
+ # If these existed, then we wouldn't get here...
+ # Prevent access of __foo__, _cached_foo etc from loading the header
+ if varname.startswith('_'):
raise AttributeError, "%s has no attribute %s" % (self, varname)
-
+
+ if varname != 'hdr': # Don't cache the hdr, unless explicitly requested
+ # Note that we don't even cache the .blah value, but looking up the
+ # header is _really_ fast so it's not obvious any of it is worth it.
+ # This is different to prco etc. data, which is loaded separately.
+ val = self._get_hdr()
+ else:
+ self.hdr = val = self._get_hdr()
+ self._has_hdr = True
if varname != 'hdr': # This is unusual, for anything that happens
val = val[varname] # a lot we should preload at __init__.
# Also note that pkg.no_value raises KeyError.
@@ -234,7 +235,7 @@ class RPMDBPackageSack(PackageSackBase):
self._simple_pkgtup_list = csumpkgtups.keys()
if not self._simple_pkgtup_list:
- for (hdr, mi) in self._all_packages():
+ for (hdr, mi) in self._get_packages():
self._simple_pkgtup_list.append(self._hdr2pkgTuple(hdr))
return self._simple_pkgtup_list
@@ -378,54 +379,36 @@ class RPMDBPackageSack(PackageSackBase):
pass
def searchAll(self, name, query_type='like'):
- ts = self.readOnlyTS()
result = {}
# check provides
tag = self.DEP_TABLE['provides'][0]
- mi = ts.dbMatch()
- mi.pattern(tag, rpm.RPMMIRE_GLOB, name)
- for hdr in mi:
- if hdr['name'] == 'gpg-pubkey':
- continue
- pkg = self._makePackageObject(hdr, mi.instance())
+ mi = self._get_packages(patterns=[(tag, rpm.RPMMIRE_GLOB, name)])
+ for hdr, idx in mi:
+ pkg = self._makePackageObject(hdr, idx)
result.setdefault(pkg.pkgid, pkg)
- del mi
fileresults = self.searchFiles(name)
for pkg in fileresults:
result.setdefault(pkg.pkgid, pkg)
- if self.auto_close:
- self.ts.close()
-
return result.values()
def searchFiles(self, name):
"""search the filelists in the rpms for anything matching name"""
- ts = self.readOnlyTS()
result = {}
name = os.path.normpath(name)
- mi = ts.dbMatch('basenames', name)
# Note that globs can't be done. As of 4.8.1:
# mi.pattern('basenames', rpm.RPMMIRE_GLOB, name)
# ...produces no results.
- for hdr in mi:
- if hdr['name'] == 'gpg-pubkey':
- continue
- pkg = self._makePackageObject(hdr, mi.instance())
+ for hdr, idx in self._get_packages('basenames', name):
+ pkg = self._makePackageObject(hdr, idx)
result.setdefault(pkg.pkgid, pkg)
- del mi
-
- result = result.values()
-
- if self.auto_close:
- self.ts.close()
- return result
+ return result.values()
def searchPrco(self, name, prcotype):
@@ -438,21 +421,15 @@ class RPMDBPackageSack(PackageSackBase):
if misc.re_glob(n):
glob = True
- ts = self.readOnlyTS()
result = {}
tag = self.DEP_TABLE[prcotype][0]
- mi = ts.dbMatch(tag, misc.to_utf8(n))
- for hdr in mi:
- if hdr['name'] == 'gpg-pubkey':
- continue
- po = self._makePackageObject(hdr, mi.instance())
+ for hdr, idx in self._get_packages(tag, misc.to_utf8(n)):
+ po = self._makePackageObject(hdr, idx)
if not glob:
if po.checkPrco(prcotype, (n, f, (e,v,r))):
result[po.pkgid] = po
else:
result[po.pkgid] = po
- del mi
-
# If it's not a provides or filename, we are done
if prcotype == 'provides' and name[0] == '/':
@@ -463,9 +440,6 @@ class RPMDBPackageSack(PackageSackBase):
result = result.values()
self._cache[prcotype][name] = result
- if self.auto_close:
- self.ts.close()
-
return result
def searchProvides(self, name):
@@ -607,7 +581,7 @@ class RPMDBPackageSack(PackageSackBase):
if not self._completely_loaded:
rpats = self._compile_patterns(patterns, ignore_case)
- for hdr, idx in self._all_packages():
+ for hdr, idx in self._get_packages():
if self._match_repattern(rpats, hdr, ignore_case):
self._makePackageObject(hdr, idx)
self._completely_loaded = patterns is None
@@ -636,18 +610,13 @@ class RPMDBPackageSack(PackageSackBase):
if self._cached_conflicts_data is None:
result = {}
- ts = self.readOnlyTS()
- mi = ts.dbMatch('conflictname')
-
- for hdr in mi:
- if hdr['name'] == 'gpg-pubkey': # Just in case...
- continue
+ for hdr, idx in self._get_packages('conflictname'):
if not hdr[rpm.RPMTAG_CONFLICTNAME]:
# Pre. rpm-4.9.x the above dbMatch() does nothing.
continue
- po = self._makePackageObject(hdr, mi.instance())
+ po = self._makePackageObject(hdr, idx)
result[po.pkgid] = po
if po._has_hdr:
continue # Unlikely, but, meh...
@@ -659,9 +628,6 @@ class RPMDBPackageSack(PackageSackBase):
del po.hdr
self._cached_conflicts_data = result.values()
- if self.auto_close:
- self.ts.close()
-
return self._cached_conflicts_data
def _write_conflicts_new(self, pkgs, rpmdbv):
@@ -1168,7 +1134,7 @@ class RPMDBPackageSack(PackageSackBase):
if not lowered:
searchstrings = map(lambda x: x.lower(), searchstrings)
ret = []
- for hdr, idx in self._all_packages():
+ for hdr, idx in self._get_packages():
n = self._find_search_fields(fields, searchstrings, hdr)
if n > 0:
ret.append((self._makePackageObject(hdr, idx), n))
@@ -1190,41 +1156,20 @@ class RPMDBPackageSack(PackageSackBase):
return [ self._makePackageObject(h, mi) for (h, mi) in ts.returnLeafNodes(headers=True) ]
# Helper functions
- def _all_packages(self):
- '''Generator that yield (header, index) for all packages
+ def _get_packages(self, *args, **kwds):
+ '''dbMatch() wrapper generator that yields (header, index) for matches
'''
ts = self.readOnlyTS()
- mi = ts.dbMatch()
- for hdr in mi:
- if hdr['name'] != 'gpg-pubkey':
- yield (hdr, mi.instance())
+ mi = ts.dbMatch(*args, **kwds)
+ for h in mi:
+ if h['name'] != 'gpg-pubkey':
+ yield (h, mi.instance())
del mi
- if self.auto_close:
- self.ts.close()
- def _header_from_index(self, idx):
- """returns a package header having been given an index"""
- warnings.warn('_header_from_index() will go away in a future version of Yum.\n',
- Errors.YumFutureDeprecationWarning, stacklevel=2)
-
- ts = self.readOnlyTS()
- try:
- mi = ts.dbMatch(0, idx)
- except (TypeError, StopIteration), e:
- #FIXME: raise some kind of error here
- print 'No index matching %s found in rpmdb, this is bad' % idx
- yield None # it should REALLY not be returning none - this needs to be right
- else:
- hdr = mi.next()
- yield hdr
- del hdr
-
- del mi
if self.auto_close:
self.ts.close()
-
def _search(self, name=None, epoch=None, ver=None, rel=None, arch=None):
'''List of matching packages, to zero or more of NEVRA.'''
if name is not None and name in self._pkgname_fails:
@@ -1254,18 +1199,16 @@ class RPMDBPackageSack(PackageSackBase):
ts = self.readOnlyTS()
if name is not None:
- mi = ts.dbMatch('name', name)
+ mi = self._get_packages('name', name)
elif arch is not None:
- mi = ts.dbMatch('arch', arch)
+ mi = self._get_packages('arch', arch)
else:
- mi = ts.dbMatch()
+ mi = self._get_packages()
self._completely_loaded = True
done = False
- for hdr in mi:
- if hdr['name'] == 'gpg-pubkey':
- continue
- po = self._makePackageObject(hdr, mi.instance())
+ for hdr, idx in mi:
+ po = self._makePackageObject(hdr, idx)
# We create POs out of all matching names, even if we don't return
# them.
self._pkgnames_loaded.add(po.name)
@@ -1277,9 +1220,6 @@ class RPMDBPackageSack(PackageSackBase):
else:
ret.append(po)
- if self.auto_close:
- self.ts.close()
-
if not done and name is not None:
self._pkgname_fails.add(name)
@@ -1323,7 +1263,7 @@ class RPMDBPackageSack(PackageSackBase):
def getHdrList(self):
warnings.warn('getHdrList() will go away in a future version of Yum.\n',
DeprecationWarning, stacklevel=2)
- return [ hdr for hdr, idx in self._all_packages() ]
+ return [ hdr for hdr, idx in self._get_packages() ]
def getNameArchPkgList(self):
warnings.warn('getNameArchPkgList() will go away in a future version of Yum.\n',
diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index 0340153..08bf99d 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -25,6 +25,7 @@ import types
import sys
from yum.constants import *
from yum import _
+from yum.transactioninfo import TransactionMember
import misc
import tempfile
@@ -174,11 +175,11 @@ class RPMTransaction:
self.base = base # base yum object b/c we need so much
self.test = test # are we a test?
self.trans_running = False
- self.filehandles = {}
+ self.fd = None
self.total_actions = 0
self.total_installed = 0
self.complete_actions = 0
- self.installed_pkg_names = []
+ self.installed_pkg_names = set()
self.total_removed = 0
self.logger = logging.getLogger('yum.filelogging.RPMInstallCallback')
self.filelog = False
@@ -209,8 +210,7 @@ class RPMTransaction:
io_r = tempfile.NamedTemporaryFile()
self._readpipe = io_r
self._writepipe = open(io_r.name, 'w+b')
- # This is dark magic, it really needs to be "base.ts.ts".
- self.base.ts.ts.scriptFd = self._writepipe.fileno()
+ self.base.ts.setScriptFd(self._writepipe)
rpmverbosity = {'critical' : 'crit',
'emergency' : 'emerg',
'error' : 'err',
@@ -255,12 +255,23 @@ class RPMTransaction:
return (hdr['name'], hdr['arch'], epoch, hdr['version'], hdr['release'])
- def _makeHandle(self, hdr):
- handle = '%s:%s.%s-%s-%s' % (hdr['epoch'], hdr['name'], hdr['version'],
- hdr['release'], hdr['arch'])
+ # Find out txmbr based on the callback key. On erasures we dont know
+ # the exact txmbr but we always have a name, so return (name, txmbr)
+ # tuples so callers have less twists to deal with.
+ def _getTxmbr(self, cbkey):
+ if isinstance(cbkey, TransactionMember):
+ return (cbkey.name, cbkey)
+ elif isinstance(cbkey, tuple):
+ pkgtup = self._dopkgtup(cbkey[0])
+ txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
+ # if this is not one, somebody screwed up
+ assert len(txmbrs) == 1
+ return (txmbrs[0].name, txmbrs[0])
+ elif isinstance(cbkey, basestring):
+ return (cbkey, None)
+ else:
+ return (None, None)
- return handle
-
def ts_done(self, package, action):
"""writes out the portions of the transaction which have completed"""
@@ -409,11 +420,10 @@ class RPMTransaction:
def _transStart(self, bytes, total, h):
- if bytes == 6:
- self.total_actions = total
- if self.test: return
- self.trans_running = True
- self.ts_all() # write out what transaction will do
+ self.total_actions = total
+ if self.test: return
+ self.trans_running = True
+ self.ts_all() # write out what transaction will do
def _transProgress(self, bytes, total, h):
pass
@@ -423,62 +433,52 @@ class RPMTransaction:
def _instOpenFile(self, bytes, total, h):
self.lastmsg = None
- hdr = None
- if h is not None:
- hdr, rpmloc = h[0], h[1]
- handle = self._makeHandle(hdr)
+ name, txmbr = self._getTxmbr(h)
+ if txmbr is not None:
+ rpmloc = txmbr.po.localPkg()
try:
- fd = os.open(rpmloc, os.O_RDONLY)
- except OSError, e:
+ self.fd = file(rpmloc)
+ except IOError, e:
self.display.errorlog("Error: Cannot open file %s: %s" % (rpmloc, e))
else:
- self.filehandles[handle]=fd
if self.trans_running:
self.total_installed += 1
self.complete_actions += 1
- self.installed_pkg_names.append(hdr['name'])
- return fd
+ self.installed_pkg_names.add(name)
+ return self.fd.fileno()
else:
self.display.errorlog("Error: No Header to INST_OPEN_FILE")
def _instCloseFile(self, bytes, total, h):
- hdr = None
- if h is not None:
- hdr, rpmloc = h[0], h[1]
- handle = self._makeHandle(hdr)
- os.close(self.filehandles[handle])
- fd = 0
+ name, txmbr = self._getTxmbr(h)
+ if txmbr is not None:
+ self.fd.close()
+ self.fd = None
if self.test: return
if self.trans_running:
- pkgtup = self._dopkgtup(hdr)
- txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
- for txmbr in txmbrs:
- self.display.filelog(txmbr.po, txmbr.output_state)
- 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)
+ self.display.filelog(txmbr.po, txmbr.output_state)
+ 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:
- # If h is a string, we're repackaging.
+ name, txmbr = self._getTxmbr(h)
+ if name is not None:
+ # If we only have a name, we're repackaging.
# Why the RPMCALLBACK_REPACKAGE_PROGRESS flag isn't set, I have no idea
- if type(h) == type(""):
- self.display.event(h, 'repackaging', bytes, total,
+ if txmbr is None:
+ self.display.event(name, 'repackaging', bytes, total,
self.complete_actions, self.total_actions)
-
else:
- hdr, rpmloc = h[0], h[1]
- pkgtup = self._dopkgtup(hdr)
- txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
- for txmbr in txmbrs:
- action = txmbr.output_state
- self.display.event(txmbr.po, action, bytes, total,
- self.complete_actions, self.total_actions)
+ action = txmbr.output_state
+ self.display.event(txmbr.po, action, bytes, total,
+ self.complete_actions, self.total_actions)
+
def _unInstStart(self, bytes, total, h):
pass
@@ -486,20 +486,21 @@ class RPMTransaction:
pass
def _unInstStop(self, bytes, total, h):
+ name, txmbr = self._getTxmbr(h)
self.total_removed += 1
self.complete_actions += 1
- if h not in self.installed_pkg_names:
- self.display.filelog(h, TS_ERASE)
+ if name not in self.installed_pkg_names:
+ self.display.filelog(name, TS_ERASE)
action = TS_ERASE
else:
action = TS_UPDATED
- self.display.event(h, action, 100, 100, self.complete_actions,
+ self.display.event(name, action, 100, 100, self.complete_actions,
self.total_actions)
- self._scriptout(h)
+ self._scriptout(name)
if self.test: return # and we're done
- self.ts_done(h, action)
+ self.ts_done(name, action)
def _rePackageStart(self, bytes, total, h):
@@ -512,20 +513,16 @@ class RPMTransaction:
pass
def _cpioError(self, bytes, total, h):
- hdr, rpmloc = h[0], h[1]
- pkgtup = self._dopkgtup(hdr)
- txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
- for txmbr in txmbrs:
+ name, txmbr = self._getTxmbr(h)
+ if txmbr is not None:
msg = "Error in cpio payload of rpm package %s" % txmbr.po
txmbr.output_state = TS_FAILED
self.display.errorlog(msg)
# FIXME - what else should we do here? raise a failure and abort?
def _unpackError(self, bytes, total, h):
- hdr, rpmloc = h[0], h[1]
- pkgtup = self._dopkgtup(hdr)
- txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
- for txmbr in txmbrs:
+ name, txmbr = self._getTxmbr(h)
+ if txmbr is not None:
txmbr.output_state = TS_FAILED
msg = "Error unpacking rpm package %s" % txmbr.po
self.display.errorlog(msg)
@@ -533,35 +530,24 @@ class RPMTransaction:
# right behavior should be
def _scriptError(self, bytes, total, h):
- if not isinstance(h, types.TupleType):
- # fun with install/erase transactions, see rhbz#484729
- h = (h, None)
- hdr, rpmloc = h[0], h[1]
- remove_hdr = False # if we're in a clean up/remove then hdr will not be an rpm.hdr
- if not isinstance(hdr, rpm.hdr):
- txmbrs = [hdr]
- remove_hdr = True
+ # "bytes" carries the failed scriptlet tag,
+ # "total" carries fatal/non-fatal status
+ scriptlet_name = rpm.tagnames.get(bytes, "<unknown>")
+
+ name, txmbr = self._getTxmbr(h)
+ if txmbr is None:
+ package_name = name
else:
- pkgtup = self._dopkgtup(hdr)
- txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
+ package_name = txmbr.po
- for pkg in txmbrs:
- # "bytes" carries the failed scriptlet tag,
- # "total" carries fatal/non-fatal status
- scriptlet_name = rpm.tagnames.get(bytes, "<unknown>")
- if remove_hdr:
- package_name = pkg
- else:
- package_name = pkg.po
-
- if total:
- msg = ("Error in %s scriptlet in rpm package %s" %
- (scriptlet_name, package_name))
- if not remove_hdr:
- pkg.output_state = TS_FAILED
- else:
- msg = ("Non-fatal %s scriptlet failure in rpm package %s" %
- (scriptlet_name, package_name))
- self.display.errorlog(msg)
- # FIXME - what else should we do here? raise a failure and abort?
+ if total:
+ msg = ("Error in %s scriptlet in rpm package %s" %
+ (scriptlet_name, package_name))
+ if txmbr is not None:
+ txmbr.output_state = TS_FAILED
+ else:
+ msg = ("Non-fatal %s scriptlet failure in rpm package %s" %
+ (scriptlet_name, package_name))
+ self.display.errorlog(msg)
+ # FIXME - what else should we do here? raise a failure and abort?
diff --git a/yum/update_md.py b/yum/update_md.py
index 83e56c6..39fa72e 100644
--- a/yum/update_md.py
+++ b/yum/update_md.py
@@ -32,6 +32,15 @@ import Errors
import rpmUtils.miscutils
+
+def safe_iterparse(filename):
+ """ Works like iterparse, but hides XML errors (prints a warning). """
+ try:
+ for event, elem in iterparse(filename):
+ yield event, elem
+ except SyntaxError: # Bad XML
+ print >> sys.stderr, "File is not valid XML:", filename
+
class UpdateNoticeException(Exception):
""" An exception thrown for bad UpdateNotice data. """
pass
@@ -445,7 +454,7 @@ class UpdateMetadata(object):
else: # obj is a file object
infile = obj
- for event, elem in iterparse(infile):
+ for event, elem in safe_iterparse(infile):
if elem.tag == 'update':
try:
un = UpdateNotice(elem)
diff --git a/yumcommands.py b/yumcommands.py
index ecce347..41f0092 100644
--- a/yumcommands.py
+++ b/yumcommands.py
@@ -46,7 +46,7 @@ def checkRootUID(base):
def checkGPGKey(base):
if not base.gpgKeyCheck():
for repo in base.repos.listEnabled():
- if (repo.gpgcheck or repo.repo_gpgcheck) and repo.gpgkey == '':
+ if (repo.gpgcheck or repo.repo_gpgcheck) and not repo.gpgkey:
msg = _("""
You have enabled checking of packages via GPG keys. This is a good thing.
However, you do not have any GPG public keys installed. You need to download
@@ -283,7 +283,7 @@ class InfoCommand(YumCommand):
return ['info']
def getUsage(self):
- return "[PACKAGE|all|installed|updates|extras|obsoletes|recent]"
+ return "[PACKAGE|all|available|installed|updates|extras|obsoletes|recent]"
def getSummary(self):
return _("Display details about a package or group of packages")
@@ -626,13 +626,14 @@ class CheckUpdateCommand(YumCommand):
checkEnabledRepo(base)
def doCommand(self, base, basecmd, extcmds):
+ obscmds = ['obsoletes'] + extcmds
base.extcmds.insert(0, 'updates')
result = 0
try:
ypl = base.returnPkgLists(extcmds)
if (base.conf.obsoletes or
base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3)):
- typl = base.returnPkgLists(['obsoletes'])
+ typl = base.returnPkgLists(obscmds)
ypl.obsoletes = typl.obsoletes
ypl.obsoletesTuples = typl.obsoletesTuples
@@ -972,6 +973,12 @@ class RepoListCommand(YumCommand):
elif repo.mirrorlist:
out += [base.fmtKeyValFill(_("Repo-mirrors : "),
repo.mirrorlist)]
+ if enabled and repo.urls:
+ url = repo.urls[0]
+ if len(repo.urls) > 1:
+ url += ' (%d more)' % (len(repo.urls) - 1)
+ out += [base.fmtKeyValFill(_("Repo-baseurl : "),
+ url)]
if not os.path.exists(repo.metadata_cookie):
last = _("Unknown")
diff --git a/yummain.py b/yummain.py
index c64b140..d0b8251 100755
--- a/yummain.py
+++ b/yummain.py
@@ -23,6 +23,7 @@ import os.path
import sys
import logging
import time
+import errno
from yum import Errors
from yum import plugins
@@ -75,6 +76,15 @@ def main(args):
return 200
return 0
+ def rpmdb_warn_checks():
+ try:
+ probs = base._rpmdb_warn_checks(out=verbose_logger.info, warn=False)
+ except YumBaseError, e:
+ # This is mainly for PackageSackError from rpmdb.
+ verbose_logger.info(_(" Yum checks failed: %s"), exception2msg(e))
+ probs = []
+ if not probs:
+ verbose_logger.info(_(" You could try running: rpm -Va --nofiles --nodigest"))
logger = logging.getLogger("yum.main")
verbose_logger = logging.getLogger("yum.verbose.main")
@@ -99,12 +109,16 @@ def main(args):
if exception2msg(e) != lockerr:
lockerr = exception2msg(e)
logger.critical(lockerr)
- if not base.conf.exit_on_lock:
+ if (e.errno not in (errno.EPERM, errno.EACCES) and
+ not base.conf.exit_on_lock):
logger.critical(_("Another app is currently holding the yum lock; waiting for it to exit..."))
tm = 0.1
if show_lock_owner(e.pid, logger):
tm = 2
time.sleep(tm)
+ elif e.errno in (errno.EPERM, errno.EACCES):
+ logger.critical(_("Can't create lock file; exiting"))
+ return 1
else:
logger.critical(_("Another app is currently holding the yum lock; exiting as configured by exit_on_lock"))
return 1
@@ -177,8 +191,7 @@ def main(args):
logger.critical(prefix, msg.replace('\n', '\n' + prefix2nd))
if not base.conf.skip_broken:
verbose_logger.info(_(" You could try using --skip-broken to work around the problem"))
- if not base._rpmdb_warn_checks(out=verbose_logger.info, warn=False):
- verbose_logger.info(_(" You could try running: rpm -Va --nofiles --nodigest"))
+ rpmdb_warn_checks()
if unlock(): return 200
return 1
elif result == 2:
@@ -205,13 +218,12 @@ def main(args):
except IOError, e:
return exIOError(e)
- # rpm_check_debug failed.
+ # rpm ts.check() failed.
if type(return_code) == type((0,)) and len(return_code) == 2:
(result, resultmsgs) = return_code
for msg in resultmsgs:
logger.critical("%s", msg)
- if not base._rpmdb_warn_checks(out=verbose_logger.info, warn=False):
- verbose_logger.info(_(" You could try running: rpm -Va --nofiles --nodigest"))
+ rpmdb_warn_checks()
return_code = result
if base._ts_save_file:
verbose_logger.info(_("Your transaction was saved, rerun it with: yum load-transaction %s") % base._ts_save_file)