[yum: 1/2] update to latest HEAD Fix syncing of yum DB data in history. Add upgrade_requirements_on_install con
James Antill
james at fedoraproject.org
Fri Aug 19 20:47:34 UTC 2011
commit b8b2a22656dc997f013dfd9c59bacf30ba162592
Author: James Antill <james at and.org>
Date: Fri Aug 5 13:39:22 2011 -0400
update to latest HEAD
Fix syncing of yum DB data in history.
Add upgrade_requirements_on_install config. option.
Don't look for releasever if it's set directly (anaconda).
Expose ip_resolve urlgrabber option.
yum-HEAD.patch | 3007 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
yum.spec | 17 +-
2 files changed, 2846 insertions(+), 178 deletions(-)
---
diff --git a/yum-HEAD.patch b/yum-HEAD.patch
index 74ff6ed..588bb37 100644
--- a/yum-HEAD.patch
+++ b/yum-HEAD.patch
@@ -60,7 +60,7 @@ index 2f6154e..2e5a052 100644
diff --git a/cli.py b/cli.py
old mode 100644
new mode 100755
-index 6056d38..43c0e1d
+index 6056d38..3a68616
--- a/cli.py
+++ b/cli.py
@@ -25,7 +25,7 @@ import sys
@@ -72,6 +72,15 @@ index 6056d38..43c0e1d
import rpm
from weakref import proxy as weakref
+@@ -43,7 +43,7 @@ from yum.rpmtrans import RPMTransaction
+ import signal
+ import yumcommands
+
+-from yum.i18n import to_unicode, to_utf8
++from yum.i18n import to_unicode, to_utf8, exception2msg
+
+ # 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
@@ -51,23 +51,24 @@ from yum.i18n import to_unicode, to_utf8
from yum.packages import parsePackages
@@ -132,8 +141,33 @@ index 6056d38..43c0e1d
if self._repos and thisrepo is None:
return self._repos
-@@ -183,10 +193,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -163,8 +173,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ mainopts = yum.misc.GenericHolder()
+ mainopts.items = []
+
++ bad_setopt_tm = []
++ bad_setopt_ne = []
++
+ for item in setopts:
+- k,v = item.split('=')
++ vals = item.split('=')
++ if len(vals) > 2:
++ bad_setopt_tm.append(item)
++ continue
++ if len(vals) < 2:
++ bad_setopt_ne.append(item)
++ continue
++ k,v = vals
+ period = k.find('.')
+ if period != -1:
+ repo = k[:period]
+@@ -180,13 +200,15 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ self.main_setopts = mainopts
+ self.repo_setopts = repoopts
+-
++
++ return bad_setopt_tm, bad_setopt_ne
def getOptionsConfig(self, args):
- """parses command line arguments, takes cli args:
@@ -148,7 +182,29 @@ index 6056d38..43c0e1d
self.optparser = YumOptionParser(base=self, usage=self._makeUsage())
# Parse only command line options that affect basic yum setup
-@@ -318,9 +329,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -199,7 +221,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ opts.verbose = False
+
+ # go through all the setopts and set the global ones
+- self._parseSetOpts(opts.setopts)
++ bad_setopt_tm, bad_setopt_ne = self._parseSetOpts(opts.setopts)
+
+ if self.main_setopts:
+ for opt in self.main_setopts.items:
+@@ -229,6 +251,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ pc.releasever = opts.releasever
+ self.conf
+
++ for item in bad_setopt_tm:
++ msg = "Setopt argument has multiple values: %s"
++ self.logger.warning(msg % item)
++ for item in bad_setopt_ne:
++ msg = "Setopt argument has no value: %s"
++ self.logger.warning(msg % item)
+ # now set all the non-first-start opts from main from our setopts
+ if self.main_setopts:
+ for opt in self.main_setopts.items:
+@@ -318,9 +346,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
time.sleep(sleeptime)
def parseCommands(self):
@@ -163,7 +219,7 @@ index 6056d38..43c0e1d
self.verbose_logger.debug('Yum Version: %s', yum.__version__)
self.verbose_logger.log(yum.logginglevels.DEBUG_4,
'COMMAND: %s', self.cmdstring)
-@@ -365,7 +378,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -365,7 +395,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
self.history.write_addon_data('shell-cmds', data)
def doShell(self):
@@ -176,7 +232,7 @@ index 6056d38..43c0e1d
yumshell = shell.YumShell(base=self)
-@@ -382,8 +399,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -382,8 +416,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return yumshell.result, yumshell.resultmsgs
def errorSummary(self, errstring):
@@ -191,7 +247,7 @@ index 6056d38..43c0e1d
summary = ''
# do disk space report first
p = re.compile('needs (\d+)MB on the (\S+) filesystem')
-@@ -408,16 +429,17 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -408,16 +446,17 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
def doCommands(self):
@@ -219,7 +275,13 @@ index 6056d38..43c0e1d
# at this point we know the args are valid - we don't know their meaning
# but we know we're not being sent garbage
-@@ -440,9 +462,13 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -435,14 +474,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ try:
+ self._getTs(needTsRemove)
+ except yum.Errors.YumBaseError, e:
+- return 1, [str(e)]
++ return 1, [exception2msg(e)]
+
return self.yum_cli_commands[self.basecmd].doCommand(self, self.basecmd, self.extcmds)
def doTransaction(self):
@@ -236,7 +298,7 @@ index 6056d38..43c0e1d
# just make sure there's not, well, nothing to do
if len(self.tsInfo) == 0:
self.verbose_logger.info(_('Trying to run the transaction but nothing to do. Exiting.'))
-@@ -453,7 +479,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -453,7 +496,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
lsts = self.listTransaction()
if self.verbose_logger.isEnabledFor(yum.logginglevels.INFO_1):
self.verbose_logger.log(yum.logginglevels.INFO_1, lsts)
@@ -245,7 +307,7 @@ index 6056d38..43c0e1d
# If we are in quiet, and assumeyes isn't on we want to output
# at least the transaction list anyway.
self.logger.warn(lsts)
-@@ -491,7 +517,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -491,7 +534,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
# confirm with user
if self._promptWanted():
@@ -254,7 +316,7 @@ index 6056d38..43c0e1d
self.verbose_logger.info(_('Exiting on user Command'))
return -1
-@@ -609,12 +635,14 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -609,12 +652,14 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return resultobject.return_code
def gpgsigcheck(self, pkgs):
@@ -274,7 +336,7 @@ index 6056d38..43c0e1d
for po in pkgs:
result, errmsg = self.sigCheckPkg(po)
-@@ -623,7 +651,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -623,7 +668,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
continue
elif result == 1:
@@ -284,9 +346,46 @@ index 6056d38..43c0e1d
raise yum.Errors.YumBaseError, \
_('Refusing to automatically import keys when running ' \
'unattended.\nUse "-y" to override.')
-@@ -692,11 +721,22 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -691,12 +737,59 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ ", ".join(matches))
self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
++ def _install_upgraded_requires(self, txmbrs):
++ """Go through the given txmbrs, and for any to be installed packages
++ look for their installed deps. and try to upgrade them, if the
++ configuration is set. Returning any new transaction members to be
++ isntalled.
++
++ :param txmbrs: a list of :class:`yum.transactioninfo.TransactionMember` objects
++ :return: a list of :class:`yum.transactioninfo.TransactionMember` objects
++ """
++
++ if not self.conf.upgrade_requirements_on_install:
++ return []
++
++ ret = []
++ done = set()
++ def _pkg2ups(pkg, reqpo=None):
++ if pkg.name in done:
++ return []
++ if reqpo is None:
++ reqpo = pkg
++
++ done.add(pkg.name)
++
++ uret = []
++ for req in pkg.requires:
++ for npkg in self.returnInstalledPackagesByDep(req):
++ uret += self.update(pattern=npkg.name, requiringPo=reqpo)
++ uret += _pkg2ups(npkg, reqpo=reqpo)
++ return uret
++
++ for txmbr in txmbrs:
++ print "JDBG:", txmbr
++ ret += _pkg2ups(txmbr.po)
++
++ return ret
++
def installPkgs(self, userlist):
- """Attempts to take the user specified list of packages/wildcards
- and install them, or if they are installed, update them to a newer
@@ -312,7 +411,30 @@ index 6056d38..43c0e1d
# get the list of available packages
# iterate over the user's list
# add packages to Transaction holding class if they match.
-@@ -732,9 +772,27 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -710,11 +803,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ for arg in userlist:
+ if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
+ os.path.exists(arg))):
+- self.localInstall(filelist=[arg])
++ txmbrs = self.installLocal(arg)
++ self._install_upgraded_requires(txmbrs)
+ continue # it was something on disk and it ended in rpm
+ # no matter what we don't go looking at repos
+ try:
+- self.install(pattern=arg)
++ txmbrs = self.install(pattern=arg)
+ except yum.Errors.InstallError:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('No package %s%s%s available.'),
+@@ -723,6 +817,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ self._maybeYouMeant(arg)
+ else:
+ done = True
++ self._install_upgraded_requires(txmbrs)
+ if len(self.tsInfo) > oldcount:
+ change = len(self.tsInfo) - oldcount
+ return 2, [P_('%d package to install', '%d packages to install', change) % change]
+@@ -732,9 +827,27 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, [_('Nothing to do')]
def updatePkgs(self, userlist, quiet=0, update_to=False):
@@ -343,7 +465,36 @@ index 6056d38..43c0e1d
# if there is no userlist, then do global update below
# this is probably 90% of the calls
# if there is a userlist then it's for updating pkgs, not obsoleting
-@@ -770,9 +828,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -745,20 +858,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+
+ else:
+ # go through the userlist - look for items that are local rpms. If we find them
+- # pass them off to localInstall() and then move on
++ # pass them off to installLocal() and then move on
+ localupdates = []
+ for item in userlist:
+ if (item.endswith('.rpm') and (yum.misc.re_remote_url(item) or
+ os.path.exists(item))):
+- localupdates.append(item)
+-
+- if len(localupdates) > 0:
+- self.localInstall(filelist=localupdates, updateonly=1)
+- for item in localupdates:
+- userlist.remove(item)
+-
+- for arg in userlist:
+- if not self.update(pattern=arg, update_to=update_to):
++ txmbrs = self.installLocal(item, updateonly=1)
++ self._install_upgraded_requires(txmbrs)
++ continue
++
++ txmbrs = self.update(pattern=item, update_to=update_to)
++ self._install_upgraded_requires(txmbrs)
++ if not txmbrs:
+ self._checkMaybeYouMeant(arg)
+
+ if len(self.tsInfo) > oldcount:
+@@ -770,9 +881,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
# Note that we aren't in __init__ yet for a couple of reasons, but we
# probably will get there for 3.2.28.
def distroSyncPkgs(self, userlist):
@@ -371,7 +522,7 @@ index 6056d38..43c0e1d
level = 'diff'
if userlist and userlist[0] in ('full', 'diff', 'different'):
-@@ -866,9 +939,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -866,9 +992,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, [_('No Packages marked for Distribution Synchronization')]
def erasePkgs(self, userlist):
@@ -394,7 +545,7 @@ index 6056d38..43c0e1d
oldcount = len(self.tsInfo)
all_rms = []
-@@ -884,9 +967,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -884,9 +1020,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, [_('No Packages marked for removal')]
def downgradePkgs(self, userlist):
@@ -418,7 +569,7 @@ index 6056d38..43c0e1d
oldcount = len(self.tsInfo)
-@@ -911,8 +1005,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -911,20 +1058,32 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, [_('Nothing to do')]
def reinstallPkgs(self, userlist):
@@ -440,7 +591,31 @@ index 6056d38..43c0e1d
oldcount = len(self.tsInfo)
-@@ -946,9 +1051,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ for arg in userlist:
+ if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
+ os.path.exists(arg))):
+- self.reinstallLocal(arg)
++ txmbrs = self.reinstallLocal(arg)
++ self._install_upgraded_requires(txmbrs)
+ continue # it was something on disk and it ended in rpm
+ # no matter what we don't go looking at repos
+
+ try:
+- self.reinstall(pattern=arg)
++ txmbrs = self.reinstall(pattern=arg)
+ except yum.Errors.ReinstallRemoveError:
+ self._checkMaybeYouMeant(arg, always_output=False)
+ except yum.Errors.ReinstallInstallError, e:
+@@ -940,15 +1099,27 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ except yum.Errors.ReinstallError, e:
+ assert False, "Shouldn't happen, but just in case"
+ self.verbose_logger.log(yum.logginglevels.INFO_2, e)
++ else:
++ self._install_upgraded_requires(txmbrs)
++
+ if len(self.tsInfo) > oldcount:
+ change = len(self.tsInfo) - oldcount
+ return 2, [P_('%d package to reinstall', '%d packages to reinstall', change) % change]
return 0, [_('Nothing to do')]
def localInstall(self, filelist, updateonly=0):
@@ -462,7 +637,7 @@ index 6056d38..43c0e1d
# read in each package into a YumLocalPackage Object
# append it to self.localPackages
# check if it can be installed or updated based on nevra versus rpmdb
-@@ -972,20 +1086,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -972,20 +1143,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, [_('Nothing to do')]
def returnPkgLists(self, extcmds, installed_available=False):
@@ -502,7 +677,7 @@ index 6056d38..43c0e1d
special = ['available', 'installed', 'all', 'extras', 'updates', 'recent',
'obsoletes']
-@@ -1017,8 +1136,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1017,8 +1193,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return ypl
def search(self, args):
@@ -530,7 +705,7 @@ index 6056d38..43c0e1d
# call the yum module search function with lists of tags to search
# and what to search for
-@@ -1108,9 +1244,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1108,9 +1301,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, matching
def deplist(self, args):
@@ -539,11 +714,11 @@ index 6056d38..43c0e1d
+ """Print out a formatted list of dependencies for a list of
+ packages. This is a cli wrapper method for
+ :class:`yum.YumBase.findDeps`.
-
++
+ :param args: a list of names or wildcards specifying packages
+ that should have their dependenices printed
+ :return: (exit_code, [ errors ])
-+
+
+ exit_code is::
+
+ 0 = we're done, exit
@@ -553,7 +728,7 @@ index 6056d38..43c0e1d
pkgs = []
for arg in args:
if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
-@@ -1131,10 +1278,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1131,10 +1335,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, []
def provides(self, args):
@@ -577,7 +752,7 @@ index 6056d38..43c0e1d
old_sdup = self.conf.showdupesfromrepos
# For output, as searchPackageProvides() is always in showdups mode
self.conf.showdupesfromrepos = True
-@@ -1163,8 +1319,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1163,8 +1376,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, []
def resolveDepCli(self, args):
@@ -599,7 +774,7 @@ index 6056d38..43c0e1d
for arg in args:
try:
pkg = self.returnPackageByDep(arg)
-@@ -1177,6 +1344,34 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1177,6 +1401,34 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, []
def cleanCli(self, userlist):
@@ -634,7 +809,7 @@ index 6056d38..43c0e1d
hdrcode = pkgcode = xmlcode = dbcode = expccode = 0
pkgresults = hdrresults = xmlresults = dbresults = expcresults = []
msg = self.fmtKeyValFill(_('Cleaning repos: '),
-@@ -1228,7 +1423,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1228,7 +1480,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return code, []
def returnGroupLists(self, userlist):
@@ -654,18 +829,18 @@ index 6056d38..43c0e1d
uservisible=1
if len(userlist) > 0:
-@@ -1283,7 +1490,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1283,7 +1547,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, [_('Done')]
def returnGroupSummary(self, userlist):
+ """Print a summary of the groups that match the given names or
+ wildcards.
-+
+
+ :param userlist: a list of names or wildcards specifying the
+ groups to summarise. If *userlist* is an empty list, all
+ installed and available packages will be summarised
+ :return: (exit_code, [ errors ])
-
++
+ exit_code is::
+
+ 0 = we're done, exit
@@ -675,7 +850,7 @@ index 6056d38..43c0e1d
uservisible=1
if len(userlist) > 0:
-@@ -1327,7 +1547,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1327,7 +1604,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, [_('Done')]
def returnGroupInfo(self, userlist):
@@ -696,7 +871,7 @@ index 6056d38..43c0e1d
for strng in userlist:
group_matched = False
for group in self.comps.return_groups(strng):
-@@ -1340,8 +1572,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1340,8 +1629,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 0, []
def installGroups(self, grouplist):
@@ -717,7 +892,7 @@ index 6056d38..43c0e1d
pkgs_used = []
for group_string in grouplist:
-@@ -1368,8 +1610,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1368,8 +1667,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return 2, [P_('%d package to Install', '%d packages to Install', len(pkgs_used)) % len(pkgs_used)]
def removeGroups(self, grouplist):
@@ -737,7 +912,7 @@ index 6056d38..43c0e1d
pkgs_used = []
for group_string in grouplist:
try:
-@@ -1389,7 +1641,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1389,7 +1698,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
def _promptWanted(self):
# shortcut for the always-off/always-on options
@@ -746,7 +921,7 @@ index 6056d38..43c0e1d
return False
if self.conf.alwaysprompt:
return True
-@@ -1400,7 +1652,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1400,7 +1709,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
# package wasn't explictly given on the command line
for txmbr in self.tsInfo.getMembers():
if txmbr.isDep or \
@@ -754,7 +929,7 @@ index 6056d38..43c0e1d
txmbr.name not in self.extcmds:
return True
-@@ -1408,11 +1659,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1408,11 +1716,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return False
def usage(self):
@@ -768,7 +943,7 @@ index 6056d38..43c0e1d
sys.stdout.write(self.optparser.get_usage())
def _installable(self, pkg, ematch=False):
-@@ -1468,9 +1719,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1468,9 +1776,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
return False
class YumOptionParser(OptionParser):
@@ -780,7 +955,7 @@ index 6056d38..43c0e1d
def __init__(self,base, **kwargs):
# check if this is called with a utils=True/False parameter
-@@ -1488,13 +1739,23 @@ class YumOptionParser(OptionParser):
+@@ -1488,13 +1796,23 @@ class YumOptionParser(OptionParser):
self._addYumBasicOptions()
def error(self, msg):
@@ -806,7 +981,7 @@ index 6056d38..43c0e1d
try:
args = _filtercmdline(
('--noplugins','--version','-q', '-v', "--quiet", "--verbose"),
-@@ -1521,7 +1782,15 @@ class YumOptionParser(OptionParser):
+@@ -1521,7 +1839,15 @@ class YumOptionParser(OptionParser):
return ret
def setupYumConfig(self, args=None):
@@ -823,7 +998,7 @@ index 6056d38..43c0e1d
if not args:
(opts, cmds) = self.parse_args()
else:
-@@ -1536,7 +1805,9 @@ class YumOptionParser(OptionParser):
+@@ -1536,7 +1862,9 @@ class YumOptionParser(OptionParser):
# Handle remaining options
if opts.assumeyes:
@@ -834,7 +1009,7 @@ index 6056d38..43c0e1d
# Instead of going cache-only for a non-root user, try to use a
# user writable cachedir. If that fails fall back to cache-only.
-@@ -1640,6 +1911,14 @@ class YumOptionParser(OptionParser):
+@@ -1640,6 +1968,14 @@ class YumOptionParser(OptionParser):
sys.exit(1)
def getRoot(self,opts):
@@ -849,7 +1024,7 @@ index 6056d38..43c0e1d
self._checkAbsInstallRoot(opts)
# If the conf file is inside the installroot - use that.
# otherwise look for it in the normal root
-@@ -1713,6 +1992,10 @@ class YumOptionParser(OptionParser):
+@@ -1713,6 +2049,10 @@ class YumOptionParser(OptionParser):
help=_("verbose operation"))
group.add_option("-y", "--assumeyes", dest="assumeyes",
action="store_true", help=_("answer yes for all questions"))
@@ -1537,7 +1712,7 @@ index 1a8202a..255c755 100644
Specifies the config file location - can take HTTP and FTP URLs and local file
paths\&.
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
-index 515aa73..bd86eea 100644
+index 515aa73..607e9fc 100644
--- a/docs/yum.conf.5
+++ b/docs/yum.conf.5
@@ -114,15 +114,27 @@ are causing problems from the transaction.
@@ -1580,6 +1755,46 @@ index 515aa73..bd86eea 100644
.br
Command-line option: \fB\-t\fP
+@@ -300,6 +313,14 @@ with the \fBthrottle\fR option (above). If \fBthrottle\fR is a percentage and
+ ignored. Default is `0' (no bandwidth throttling).
+
+ .IP
++\fBip_resolve \fR
++Determines how yum resolves host names.
++
++`4' or `IPv4': resolve to IPv4 addresses only.
++
++`6' or `IPv6': resolve to IPv6 addresses only.
++
++.IP
+ \fBsslcacert \fR
+ Path to the directory containing the databases of the certificate authorities
+ yum should use to verify SSL certificates. Defaults to none - uses system
+@@ -595,6 +616,12 @@ package's dependencies. If any of them are no longer required by any other
+ package then also mark them to be removed.
+ Boolean (1, 0, True, False, yes,no) Defaults to False
+
++.IP
++\fBupgrade_requirements_on_install \fR
++When installing/reinstalling/upgrading packages go through each package's
++installed dependencies and check for an update.
++Boolean (1, 0, True, False, yes,no) Defaults to False
++
+
+
+ .SH "[repository] OPTIONS"
+@@ -755,6 +782,11 @@ repository.
+ Overrides the \fBbandwidth\fR option from the [main] section for this
+ repository.
+
++.IP
++\fBip_resolve \fR
++Overrides the \fBip_resolve\fR option from the [main] section for this
++repository.
++
+
+ .IP
+ \fBsslcacert \fR
diff --git a/etc/0yum.cron b/etc/0yum.cron
deleted file mode 100755
index 0cfaa4b..0000000
@@ -3566,7 +3781,7 @@ index 97a9923..70dde98 100644
diff --git a/utils.py b/utils.py
old mode 100644
new mode 100755
-index ced6ba0..90b6fd4
+index ced6ba0..99533a6
--- a/utils.py
+++ b/utils.py
@@ -13,6 +13,8 @@
@@ -3578,6 +3793,15 @@ index ced6ba0..90b6fd4
import sys
import time
import exceptions
+@@ -21,7 +23,7 @@ import yum
+ from cli import *
+ from yum import Errors
+ from yum import _
+-from yum.i18n import utf8_width
++from yum.i18n import utf8_width, exception2msg
+ from yum import logginglevels
+ from optparse import OptionGroup
+
@@ -29,6 +31,9 @@ import yum.plugins as plugins
from urlgrabber.progress import format_number
@@ -3642,36 +3866,38 @@ index ced6ba0..90b6fd4
ps = get_process_info(pid)
if not ps:
return None
-@@ -130,9 +164,16 @@ def show_lock_owner(pid, logger):
+@@ -129,28 +163,9 @@ def show_lock_owner(pid, logger):
+ return ps
- def exception2msg(e):
+-def exception2msg(e):
- """ DIE python DIE! Which one works:
- to_unicode(e.value); unicode(e); str(e);
- Call this so you don't have to care. """
-+ """Convert an exception to a message. This function will convert
-+ the exception using to_unicode, unicode, or str, whichever works correctly.
-+
-+ :param e: an exception
-+ :return: a string representation of the exception
-+ """
-+
-+ # DIE python DIE! Which one works:
-+ # to_unicode(e.value); unicode(e); str(e);
-+ # Call this so you don't have to care.
- try:
- return to_unicode(e.value)
- except:
-@@ -151,6 +192,8 @@ def exception2msg(e):
-
-
+- try:
+- return to_unicode(e.value)
+- except:
+- pass
+-
+- try:
+- return unicode(e)
+- except:
+- pass
+-
+- try:
+- return str(e)
+- except:
+- pass
+- return "<exception failed to convert to text>"
+-
+-
class YumUtilBase(YumBaseCli):
+ """A class to extend the yum cli for utilities."""
+
def __init__(self,name,ver,usage):
YumBaseCli.__init__(self)
self._parser = YumOptionParser(base=self,utils=True,usage=usage)
-@@ -167,11 +210,22 @@ class YumUtilBase(YumBaseCli):
+@@ -167,11 +182,22 @@ class YumUtilBase(YumBaseCli):
self.run_with_package_names.add("yum-utils")
def exUserCancel(self):
@@ -3694,7 +3920,7 @@ index ced6ba0..90b6fd4
if e.errno == 32:
self.logger.critical(_('\n\nExiting on Broken Pipe'))
else:
-@@ -180,10 +234,13 @@ class YumUtilBase(YumBaseCli):
+@@ -180,10 +206,13 @@ class YumUtilBase(YumBaseCli):
return 1
def exPluginExit(self, e):
@@ -3711,7 +3937,7 @@ index ced6ba0..90b6fd4
exitmsg = exception2msg(e)
if exitmsg:
self.logger.warn('\n\n%s', exitmsg)
-@@ -191,11 +248,20 @@ class YumUtilBase(YumBaseCli):
+@@ -191,11 +220,20 @@ class YumUtilBase(YumBaseCli):
return 1
def exFatal(self, e):
@@ -3732,7 +3958,7 @@ index ced6ba0..90b6fd4
try:
self.closeRpmDB()
self.doUnlock()
-@@ -205,13 +271,27 @@ class YumUtilBase(YumBaseCli):
+@@ -205,13 +243,27 @@ class YumUtilBase(YumBaseCli):
def getOptionParser(self):
@@ -3761,7 +3987,7 @@ index ced6ba0..90b6fd4
lockerr = ""
while True:
try:
-@@ -233,6 +313,13 @@ class YumUtilBase(YumBaseCli):
+@@ -233,6 +285,13 @@ class YumUtilBase(YumBaseCli):
print "%s - %s (yum - %s)" % (self._utilName,self._utilVer,yum.__version__)
def doUtilConfigSetup(self,args = sys.argv[1:],pluginsTypes=(plugins.TYPE_CORE,)):
@@ -3775,7 +4001,7 @@ index ced6ba0..90b6fd4
# Parse only command line options that affect basic yum setup
opts = self._parser.firstParse(args)
-@@ -305,8 +392,9 @@ class YumUtilBase(YumBaseCli):
+@@ -305,8 +364,9 @@ class YumUtilBase(YumBaseCli):
return opts
def doUtilYumSetup(self):
@@ -3787,7 +4013,7 @@ index ced6ba0..90b6fd4
# FIXME - we need another way to do this, I think.
try:
self.waitForLock()
-@@ -319,6 +407,11 @@ class YumUtilBase(YumBaseCli):
+@@ -319,6 +379,11 @@ class YumUtilBase(YumBaseCli):
sys.exit(1)
def doUtilBuildTransaction(self, unfinished_transactions_check=True):
@@ -3799,7 +4025,7 @@ index ced6ba0..90b6fd4
try:
(result, resultmsgs) = self.buildTransaction(unfinished_transactions_check = unfinished_transactions_check)
except plugins.PluginYumExit, e:
-@@ -361,6 +454,7 @@ class YumUtilBase(YumBaseCli):
+@@ -361,6 +426,7 @@ class YumUtilBase(YumBaseCli):
self.verbose_logger.log(logginglevels.INFO_2, _('\nDependencies Resolved'))
def doUtilTransaction(self):
@@ -4886,18 +5112,236 @@ index 1ce4720..25e3022
gobject.threads_init()
dbus.glib.threads_init()
diff --git a/yum.spec b/yum.spec
-index abd203f..825f745 100644
+index abd203f..b78a9f6 100644
--- a/yum.spec
+++ b/yum.spec
-@@ -1,6 +1,6 @@
- Summary: RPM installer/updater
+@@ -1,24 +1,51 @@
+-Summary: RPM installer/updater
++%define move_yum_conf_back 1
++%define auto_sitelib 1
++%define yum_updatesd 0
++%define disable_check 0
++
++%if %{auto_sitelib}
++
++%{!?python_sitelib: %define python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
++
++%else
++%define python_sitelib /usr/lib/python?.?/site-packages
++%endif
++
++# We always used /usr/lib here, even on 64bit ... so it's a bit meh.
++%define yum_pluginslib /usr/lib/yum-plugins
++%define yum_pluginsshare /usr/share/yum-plugins
++
++Summary: RPM package installer/updater/manager
Name: yum
-Version: 3.4.2
+Version: 3.4.3
Release: 0
License: GPLv2+
Group: System Environment/Base
-@@ -193,13 +193,14 @@ exit 0
+ Source: %{name}-%{version}.tar.gz
+ URL: http://yum.baseurl.org/
+-BuildRoot: %{_tmppath}/%{name}-%{version}root
+ BuildArchitectures: noarch
+ BuildRequires: python
+ BuildRequires: gettext
+ BuildRequires: intltool
+-
++# This is really CheckRequires ...
++BuildRequires: python-nose
++BuildRequires: python >= 2.4
++BuildRequires: rpm-python, rpm >= 0:4.4.2
++BuildRequires: python-iniparse
++BuildRequires: python-sqlite
++BuildRequires: python-urlgrabber >= 3.9.0-8
++BuildRequires: yum-metadata-parser >= 1.1.0
++BuildRequires: pygpgme
++# End of CheckRequires
++Conflicts: pirut < 1.1.4
+ Requires: python >= 2.4
+ Requires: rpm-python, rpm >= 0:4.4.2
++Requires: python-iniparse
+ Requires: python-sqlite
+-Requires: urlgrabber >= 3.9.2
++Requires: python-urlgrabber >= 3.9.0-8
+ Requires: yum-metadata-parser >= 1.1.0
+-Requires: python-iniparse
+ Requires: pygpgme
++
+ Conflicts: rpm >= 5-0
+ # Zif is a re-implementation of yum in C, however:
+ #
+@@ -34,18 +61,26 @@ Conflicts: rpm >= 5-0
+ # zif experts).
+ #
+ # ...so we have two sane choices: i) Conflict with it. 2) Stop developing yum.
+-Conflicts: zif
++#
++# Upstream says that #2 will no longer be true after this release.
++Conflicts: zif <= 0.1.3-3.fc15
++
+ Obsoletes: yum-skip-broken <= 1.1.18
++Provides: yum-skip-broken = 1.1.18.yum
+ Obsoletes: yum-basearchonly <= 1.1.9
++Obsoletes: yum-plugin-basearchonly <= 1.1.9
++Provides: yum-basearchonly = 1.1.9.yum
++Provides: yum-plugin-basearchonly = 1.1.9.yum
+ Obsoletes: yum-allow-downgrade < 1.1.20-0
+ Obsoletes: yum-plugin-allow-downgrade < 1.1.22-0
++Provides: yum-allow-downgrade = 1.1.20-0.yum
++Provides: yum-plugin-allow-downgrade = 1.1.22-0.yum
+ Obsoletes: yum-plugin-protect-packages < 1.1.27-0
+-Provides: yum-skip-broken
+-Provides: yum-basearchonly
+-Provides: yum-allow-downgrade
+-Provides: yum-plugin-allow-downgrade
+-Provides: yum-protect-packages
+-Provides: yum-plugin-protect-packages
++Provides: yum-protect-packages = 1.1.27-0.yum
++Provides: yum-plugin-protect-packages = 1.1.27-0.yum
++Obsoletes: yum-plugin-download-order <= 0.2-2
++BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
++
+
+ %description
+ Yum is a utility that can check for and automatically download and
+@@ -58,9 +93,11 @@ Group: Applications/System
+ Requires: yum = %{version}-%{release}
+ Requires: dbus-python
+ Requires: pygobject2
+-Requires(preun): /sbin/chkconfig
++Requires(preun): /sbin/chkconfig
++Requires(post): /sbin/chkconfig
+ Requires(preun): /sbin/service
+-Requires(postun): /sbin/chkconfig
++Requires(post): /sbin/service
++Requires(postun): /sbin/chkconfig
+ Requires(postun): /sbin/service
+
+
+@@ -83,18 +120,46 @@ Requires(postun): /sbin/service
+ These are the files needed to run yum updates as a cron job.
+ Install this package if you want auto yum updates nightly via cron.
+
++
++
+ %prep
+ %setup -q
+
+ %build
+ make
+
++%if !%{disable_check}
++%check
++make check
++%endif
++
+
+ %install
+ [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
+ make DESTDIR=$RPM_BUILD_ROOT install
+-# install -m 644 %{SOURCE1} $RPM_BUILD_ROOT/etc/yum/yum.conf
+-# install -m 755 %{SOURCE2} $RPM_BUILD_ROOT/etc/cron.daily/yum.cron
++install -m 644 %{SOURCE1} $RPM_BUILD_ROOT/%{_sysconfdir}/yum.conf
++mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/yum/pluginconf.d $RPM_BUILD_ROOT/%{yum_pluginslib}
++mkdir -p $RPM_BUILD_ROOT/%{yum_pluginsshare}
++
++%if %{move_yum_conf_back}
++# for now, move repodir/yum.conf back
++mv $RPM_BUILD_ROOT/%{_sysconfdir}/yum/repos.d $RPM_BUILD_ROOT/%{_sysconfdir}/yum.repos.d
++rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/yum/yum.conf
++%endif
++
++%if %{yum_updatesd}
++echo Keeping local yum-updatesd
++%else
++
++# yum-updatesd has moved to the separate source version
++rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/yum/yum-updatesd.conf
++rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/rc.d/init.d/yum-updatesd
++rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/dbus-1/system.d/yum-updatesd.conf
++rm -f $RPM_BUILD_ROOT/%{_sbindir}/yum-updatesd
++rm -f $RPM_BUILD_ROOT/%{_mandir}/man*/yum-updatesd*
++rm -f $RPM_BUILD_ROOT/%{_datadir}/yum-cli/yumupd.py*
++
++%endif
+
+ # Ghost files:
+ mkdir -p $RPM_BUILD_ROOT/var/lib/yum/history
+@@ -102,12 +167,18 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/yum/plugins
+ mkdir -p $RPM_BUILD_ROOT/var/lib/yum/yumdb
+ touch $RPM_BUILD_ROOT/var/lib/yum/uuid
+
++# rpmlint bogus stuff...
++chmod +x $RPM_BUILD_ROOT/%{_datadir}/yum-cli/*.py
++chmod +x $RPM_BUILD_ROOT/%{python_sitelib}/yum/*.py
++chmod +x $RPM_BUILD_ROOT/%{python_sitelib}/rpmUtils/*.py
++
+ %find_lang %name
+
+ %clean
+ [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
+
+
++%if %{yum_updatesd}
+ %post updatesd
+ /sbin/chkconfig --add yum-updatesd
+ /sbin/service yum-updatesd condrestart >/dev/null 2>&1
+@@ -119,6 +190,7 @@ if [ $1 = 0 ]; then
+ /sbin/service yum-updatesd stop >/dev/null 2>&1
+ fi
+ exit 0
++%endif
+
+
+ %post cron
+@@ -165,21 +237,29 @@ exit 0
+
+
+ %files -f %{name}.lang
+-%defattr(-, root, root)
++%defattr(-, root, root, -)
+ %doc README AUTHORS COPYING TODO INSTALL ChangeLog PLUGINS
++%if %{move_yum_conf_back}
++%config(noreplace) %{_sysconfdir}/yum.conf
++%dir %{_sysconfdir}/yum.repos.d
++%else
+ %config(noreplace) %{_sysconfdir}/yum/yum.conf
++%dir %{_sysconfdir}/yum/repos.d
++%endif
+ %config(noreplace) %{_sysconfdir}/yum/version-groups.conf
+ %dir %{_sysconfdir}/yum
+ %dir %{_sysconfdir}/yum/protected.d
+-%dir %{_sysconfdir}/yum/repos.d
+ %dir %{_sysconfdir}/yum/vars
+-%config %{_sysconfdir}/logrotate.d/%{name}
++%config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
+ %{_sysconfdir}/bash_completion.d
++%dir %{_datadir}/yum-cli
+ %{_datadir}/yum-cli/*
++%if %{yum_updatesd}
+ %exclude %{_datadir}/yum-cli/yumupd.py*
++%endif
+ %{_bindir}/yum
+-/usr/lib/python?.?/site-packages/yum
+-/usr/lib/python?.?/site-packages/rpmUtils
++%{python_sitelib}/yum
++%{python_sitelib}/rpmUtils
+ %dir /var/cache/yum
+ %dir /var/lib/yum
+ %ghost /var/lib/yum/uuid
+@@ -188,20 +268,24 @@ exit 0
+ %ghost /var/lib/yum/yumdb
+ %{_mandir}/man*/yum.*
+ %{_mandir}/man*/yum-shell*
+-
++# plugin stuff
++%dir %{_sysconfdir}/yum/pluginconf.d
++%dir %{yum_pluginslib}
++%dir %{yum_pluginsshare}
+
%files cron
%defattr(-,root,root)
%doc COPYING
@@ -4909,16 +5353,22 @@ index abd203f..825f745 100644
%{_sysconfdir}/rc.d/init.d/yum-cron
+%{_sbindir}/yum-cron
%config(noreplace) %{_sysconfdir}/sysconfig/yum-cron
--
--
+%dir %{_datadir}/yum-cron
+%{_datadir}/yum-cron/update.yum
+%{_datadir}/yum-cron/cleanup.yum
-
+-
+-
+-
++%if %{yum_updatesd}
%files updatesd
-@@ -212,6 +213,9 @@ exit 0
+ %defattr(-, root, root)
+ %config(noreplace) %{_sysconfdir}/yum/yum-updatesd.conf
+@@ -210,8 +294,12 @@ exit 0
+ %{_datadir}/yum-cli/yumupd.py*
+ %{_sbindir}/yum-updatesd
%{_mandir}/man*/yum-updatesd*
++%endif
%changelog
+* Thu Jul 28 2011 Matthew Miller <mattdm at mattdm.org>
@@ -4928,10 +5378,320 @@ index abd203f..825f745 100644
- 3.4.1
- umask bug fix.
diff --git a/yum/__init__.py b/yum/__init__.py
-index 99039e0..530bfd4 100644
+index 99039e0..5fb7c00 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
-@@ -881,7 +881,8 @@ class YumBase(depsolve.Depsolve):
+@@ -82,7 +82,7 @@ from packages import YumAvailablePackage, YumLocalPackage, YumInstalledPackage
+ from packages import YumUrlPackage, YumNotFoundPackage
+ from constants import *
+ from yum.rpmtrans import RPMTransaction,SimpleCliCallBack
+-from yum.i18n import to_unicode, to_str
++from yum.i18n import to_unicode, to_str, exception2msg
+
+ import string
+ import StringIO
+@@ -102,10 +102,12 @@ default_grabber.opts.user_agent += " yum/" + __version__
+
+
+ class _YumPreBaseConf:
+- """This is the configuration interface for the YumBase configuration.
+- So if you want to change if plugins are on/off, or debuglevel/etc.
+- you tweak it here, and when yb.conf does it's thing ... it happens. """
+-
++ """This is the configuration interface for the :class:`YumBase`
++ configuration. To change configuration settings such as whether
++ plugins are on or off, or the value of debuglevel, change the
++ values here. Later, when :func:`YumBase.conf` is first called, all
++ of the options will be automatically configured.
++ """
+ def __init__(self):
+ self.fn = '/etc/yum/yum.conf'
+ self.root = '/'
+@@ -125,10 +127,12 @@ class _YumPreBaseConf:
+
+
+ class _YumPreRepoConf:
+- """This is the configuration interface for the repos configuration.
+- So if you want to change callbacks etc. you tweak it here, and when
+- yb.repos does it's thing ... it happens. """
+-
++ """This is the configuration interface for the repos configuration
++ configuration. To change configuration settings such what
++ callbacks are used, change the values here. Later, when
++ :func:`YumBase.repos` is first called, all of the options will be
++ automatically configured.
++ """
+ def __init__(self):
+ self.progressbar = None
+ self.callback = None
+@@ -164,11 +168,11 @@ class _YumCostExclude:
+ return False
+
+ class YumBase(depsolve.Depsolve):
+- """This is a primary structure and base class. It houses the objects and
+- methods needed to perform most things in yum. It is almost an abstract
+- class in that you will need to add your own class above it for most
+- real use."""
+-
++ """This is a primary structure and base class. It houses the
++ objects and methods needed to perform most things in yum. It is
++ almost an abstract class in that you will need to add your own
++ class above it for most real use.
++ """
+ def __init__(self):
+ depsolve.Depsolve.__init__(self)
+ self._conf = None
+@@ -213,6 +217,8 @@ class YumBase(depsolve.Depsolve):
+ for cb in self._cleanup: cb()
+
+ def close(self):
++ """Close the history and repo objects."""
++
+ # We don't want to create the object, so we test if it's been created
+ if self._history is not None:
+ self.history.close()
+@@ -225,15 +231,33 @@ class YumBase(depsolve.Depsolve):
+ return transactioninfo.TransactionData()
+
+ def doGenericSetup(self, cache=0):
+- """do a default setup for all the normal/necessary yum components,
+- really just a shorthand for testing"""
++ """Do a default setup for all the normal or necessary yum
++ components. This function is really just a shorthand for
++ testing purposes.
+
++ :param cache: whether to run in cache only mode, which will
++ run only from the system cache
++ """
+ self.preconf.init_plugins = False
+ self.conf.cache = cache
+
+ def doConfigSetup(self, fn='/etc/yum/yum.conf', root='/', init_plugins=True,
+ plugin_types=(plugins.TYPE_CORE,), optparser=None, debuglevel=None,
+ errorlevel=None):
++ """Deprecated. Perform configuration setup.
++
++ :param fn: the name of the configuration file to use
++ :param root: the root directory to use
++ :param init_plugins: whether to initialize plugins before
++ running yum
++ :param plugin_types: a tuple containing the types to plugins
++ to load
++ :param optparser: the option parser to use for configuration
++ :param debuglevel: the minimum debug logging level to output
++ messages from
++ :param errorlevel: the minimum error logging level to output
++ messages from
++ """
+ warnings.warn(_('doConfigSetup() will go away in a future version of Yum.\n'),
+ Errors.YumFutureDeprecationWarning, stacklevel=2)
+
+@@ -297,7 +321,7 @@ class YumBase(depsolve.Depsolve):
+ # Try the old default
+ fn = '/etc/yum.conf'
+
+- startupconf = config.readStartupConfig(fn, root)
++ startupconf = config.readStartupConfig(fn, root, releasever)
+ startupconf.arch = arch
+ startupconf.basearch = self.arch.basearch
+ if uuid:
+@@ -367,22 +391,36 @@ class YumBase(depsolve.Depsolve):
+ def doLoggingSetup(self, debuglevel, errorlevel,
+ syslog_ident=None, syslog_facility=None,
+ syslog_device='/dev/log'):
+- '''
+- Perform logging related setup.
+-
+- @param debuglevel: Debug logging level to use.
+- @param errorlevel: Error logging level to use.
+- '''
++ """Perform logging related setup.
++
++ :param debuglevel: the minimum debug logging level to output
++ messages from
++ :param errorlevel: the minimum error logging level to output
++ messages from
++ :param syslog_ident: the ident of the syslog to use
++ :param syslog_facility: the name of the syslog facility to use
++ :param syslog_device: the syslog device to use
++ """
+ logginglevels.doLoggingSetup(debuglevel, errorlevel,
+ syslog_ident, syslog_facility,
+ syslog_device)
+
+ def doFileLogSetup(self, uid, logfile):
++ """Set up the logging file.
++
++ :param uid: the user id of the current user
++ :param logfile: the name of the file to use for logging
++ """
+ logginglevels.setFileLog(uid, logfile, self._cleanup)
+
+ def getReposFromConfigFile(self, repofn, repo_age=None, validate=None):
+- """read in repositories from a config .repo file"""
++ """Read in repositories from a config .repo file.
+
++ :param repofn: a string specifying the path of the .repo file
++ to read
++ :param repo_age: the last time that the .repo file was
++ modified, in seconds since the epoch
++ """
+ if repo_age is None:
+ repo_age = os.stat(repofn)[8]
+
+@@ -448,8 +486,11 @@ class YumBase(depsolve.Depsolve):
+ self.logger.warning(e)
+
+ def getReposFromConfig(self):
+- """read in repositories from config main and .repo files"""
+-
++ """Read in repositories from the main yum conf file, and from
++ .repo files. The location of the main yum conf file is given
++ by self.conf.config_file_path, and the location of the
++ directory of .repo files is given by self.conf.reposdir.
++ """
+ # Read .repo files from directories specified by the reposdir option
+ # (typically /etc/yum/repos.d)
+ repo_config_age = self.conf.config_file_age
+@@ -472,12 +513,13 @@ class YumBase(depsolve.Depsolve):
+ self.getReposFromConfigFile(repofn, repo_age=thisrepo_age)
+
+ def readRepoConfig(self, parser, section):
+- '''Parse an INI file section for a repository.
++ """Parse an INI file section for a repository.
+
+- @param parser: ConfParser or similar to read INI file values from.
+- @param section: INI file section to read.
+- @return: YumRepository instance.
+- '''
++ :param parser: :class:`ConfigParser` or similar object to read
++ INI file values from
++ :param section: INI file section to read
++ :return: :class:`yum.yumRepo.YumRepository` instance
++ """
+ repo = yumRepo.YumRepository(section)
+ try:
+ repo.populate(parser, section, self.conf)
+@@ -500,31 +542,31 @@ class YumBase(depsolve.Depsolve):
+ return repo
+
+ def disablePlugins(self):
+- '''Disable yum plugins
+- '''
++ """Disable yum plugins."""
++
+ self.plugins = plugins.DummyYumPlugins()
+
+ def doPluginSetup(self, optparser=None, plugin_types=None, searchpath=None,
+ confpath=None,disabled_plugins=None,enabled_plugins=None):
+- '''Initialise and enable yum plugins.
+-
+- Note: _getConfig() will initialise plugins if instructed to. Only
+- call this method directly if not calling _getConfig() or calling
+- doConfigSetup(init_plugins=False).
+-
+- @param optparser: The OptionParser instance for this run (optional)
+- @param plugin_types: A sequence specifying the types of plugins to load.
+- This should be a sequence containing one or more of the
+- yum.plugins.TYPE_... constants. If None (the default), all plugins
+- will be loaded.
+- @param searchpath: A list of directories to look in for plugins. A
+- default will be used if no value is specified.
+- @param confpath: A list of directories to look in for plugin
+- configuration files. A default will be used if no value is
+- specified.
+- @param disabled_plugins: Plugins to be disabled
+- @param enabled_plugins: Plugins to be enabled
+- '''
++ """Initialise and enable yum plugins.
++ Note: _getConfig() will also initialise plugins if instructed
++ to. Only call this method directly if not calling _getConfig()
++ or calling doConfigSetup(init_plugins=False).
++
++ :param optparser: the :class:`OptionParser` instance to use
++ for this run
++ :param plugin_types: a sequence specifying the types of plugins to load.
++ This should be a sequence containing one or more of the
++ yum.plugins.TYPE_... constants. If None (the default), all plugins
++ will be loaded
++ :param searchpath: a list of directories to look in for plugins. A
++ default will be used if no value is specified
++ :param confpath: a list of directories to look in for plugin
++ configuration files. A default will be used if no value is
++ specified
++ :param disabled_plugins: a list of plugins to be disabled
++ :param enabled_plugins: a list plugins to be enabled
++ """
+ if isinstance(self.plugins, plugins.YumPlugins):
+ raise RuntimeError(_("plugins already initialised"))
+
+@@ -533,6 +575,8 @@ class YumBase(depsolve.Depsolve):
+
+
+ def doRpmDBSetup(self):
++ """Deprecated. Set up the rpm database."""
++
+ warnings.warn(_('doRpmDBSetup() will go away in a future version of Yum.\n'),
+ Errors.YumFutureDeprecationWarning, stacklevel=2)
+
+@@ -552,7 +596,8 @@ class YumBase(depsolve.Depsolve):
+ return self._rpmdb
+
+ def closeRpmDB(self):
+- """closes down the instances of the rpmdb we have wangling around"""
++ """Closes down the instances of rpmdb that could be open."""
++
+ if self._rpmdb is not None:
+ self._rpmdb.ts = None
+ self._rpmdb.dropCachedData()
+@@ -567,6 +612,12 @@ class YumBase(depsolve.Depsolve):
+ self._ts = None
+
+ def doRepoSetup(self, thisrepo=None):
++ """Deprecated. Set up the yum repositories.
++
++ :param thisrepo: the repository to set up. If None, all
++ repositories will be set up
++ :return: the set up repos
++ """
+ warnings.warn(_('doRepoSetup() will go away in a future version of Yum.\n'),
+ Errors.YumFutureDeprecationWarning, stacklevel=2)
+
+@@ -630,6 +681,14 @@ class YumBase(depsolve.Depsolve):
+ self._repos = RepoStorage(self)
+
+ def doSackSetup(self, archlist=None, thisrepo=None):
++ """Deprecated. Populate the package sacks with information
++ from our repositories.
++
++ :param archlist: a list of the names of archs to include. If
++ None, all arches are set up
++ :param thisrepo: the repository to use. If None, all enabled
++ repositories are used
++ """
+ warnings.warn(_('doSackSetup() will go away in a future version of Yum.\n'),
+ Errors.YumFutureDeprecationWarning, stacklevel=2)
+
+@@ -711,6 +770,9 @@ class YumBase(depsolve.Depsolve):
+
+
+ def doUpdateSetup(self):
++ """Deprecated. Set up the update object in the base class and populate the
++ updates, obsoletes, and other lists.
++ """
+ warnings.warn(_('doUpdateSetup() will go away in a future version of Yum.\n'),
+ Errors.YumFutureDeprecationWarning, stacklevel=2)
+
+@@ -765,6 +827,8 @@ class YumBase(depsolve.Depsolve):
+ return self._up
+
+ def doGroupSetup(self):
++ """Deprecated. Create and populate the groups object."""
++
+ warnings.warn(_('doGroupSetup() will go away in a future version of Yum.\n'),
+ Errors.YumFutureDeprecationWarning, stacklevel=2)
+
+@@ -881,7 +945,8 @@ class YumBase(depsolve.Depsolve):
if self._history is None:
pdb_path = self.conf.persistdir + "/history"
self._history = yum.history.YumHistory(root=self.conf.installroot,
@@ -4941,7 +5701,56 @@ index 99039e0..530bfd4 100644
return self._history
# properties so they auto-create themselves with defaults
-@@ -1242,13 +1243,15 @@ class YumBase(depsolve.Depsolve):
+@@ -928,9 +993,10 @@ class YumBase(depsolve.Depsolve):
+
+
+ def doSackFilelistPopulate(self):
+- """convenience function to populate the repos with the filelist metadata
+- it also is simply to only emit a log if anything actually gets populated"""
+-
++ """Convenience function to populate the repositories with the
++ filelist metadata, and emit a log message only if new
++ information is actually populated.
++ """
+ necessary = False
+
+ # I can't think of a nice way of doing this, we have to have the sack here
+@@ -951,8 +1017,12 @@ class YumBase(depsolve.Depsolve):
+ self.repos.populateSack(mdtype='filelists')
+
+ def yumUtilsMsg(self, func, prog):
+- """ Output a message that the tool requires the yum-utils package,
+- if not installed. """
++ """Output a message that the given tool requires the yum-utils
++ package, if it not installed.
++
++ :param func: the function to output the message
++ :param prog: the name of the tool that requires yum-utils
++ """
+ if self.rpmdb.contains(name="yum-utils"):
+ return
+
+@@ -964,8 +1034,17 @@ class YumBase(depsolve.Depsolve):
+ (hibeg, prog, hiend))
+
+ def buildTransaction(self, unfinished_transactions_check=True):
+- """go through the packages in the transaction set, find them in the
+- packageSack or rpmdb, and pack up the ts accordingly"""
++ """Go through the packages in the transaction set, find them
++ in the packageSack or rpmdb, and pack up the transaction set
++ accordingly.
++
++ :param unfinished_transactions_check: whether to check for
++ unfinished transactions before building the new transaction
++ """
++ # FIXME: This is horrible, see below and yummain. Maybe create a real
++ # rescode object? :(
++ self._depsolving_failed = False
++
+ if (unfinished_transactions_check and
+ misc.find_unfinished_transactions(yumlibpath=self.conf.persistdir)):
+ msg = _('There are unfinished transactions remaining. You might ' \
+@@ -1242,13 +1321,15 @@ class YumBase(depsolve.Depsolve):
if None in pkgtup:
return None
return pkgtup
@@ -4961,7 +5770,41 @@ index 99039e0..530bfd4 100644
if pkgtup is None:
return
self._not_found_i[pkgtup] = YumNotFoundPackage(pkgtup)
-@@ -1645,6 +1648,9 @@ class YumBase(depsolve.Depsolve):
+@@ -1454,8 +1535,14 @@ class YumBase(depsolve.Depsolve):
+ return probs
+
+ def runTransaction(self, cb):
+- """takes an rpm callback object, performs the transaction"""
++ """Perform the transaction.
+
++ :param cb: an rpm callback object to use in the transaction
++ :return: a :class:`yum.misc.GenericHolder` containing
++ information about the results of the transaction
++ :raises: :class:`yum.Errors.YumRPMTransError` if there is a
++ transaction cannot be completed
++ """
+ self.plugins.run('pretrans')
+
+ # We may want to put this other places, eventually, but for now it's
+@@ -1571,9 +1658,14 @@ class YumBase(depsolve.Depsolve):
+ return resultobject
+
+ def verifyTransaction(self, resultobject=None):
+- """checks that the transaction did what we expected it to do. Also
+- propagates our external yumdb info"""
+-
++ """Check that the transaction did what was expected, and
++ propagate external yumdb information. Output error messages
++ if the transaction did not do what was expected.
++
++ :param resultobject: the :class:`yum.misc.GenericHolder`
++ object returned from the :func:`runTransaction` call that
++ ran the transaction
++ """
+ # check to see that the rpmdb and the tsInfo roughly matches
+ # push package object metadata outside of rpmdb into yumdb
+ # delete old yumdb metadata entries
+@@ -1645,6 +1737,9 @@ class YumBase(depsolve.Depsolve):
elif loginuid is not None:
po.yumdb_info.installed_by = str(loginuid)
@@ -4971,66 +5814,753 @@ index 99039e0..530bfd4 100644
# Remove old ones after installing new ones, so we can copy values.
for txmbr in self.tsInfo:
if txmbr.output_state in TS_INSTALL_STATES:
-@@ -2939,7 +2945,7 @@ class YumBase(depsolve.Depsolve):
- self.verbose_logger.log(logginglevels.DEBUG_2,
- _('Adding package %s from group %s'), pkg, thisgroup.groupid)
- try:
-- txmbrs = self.install(name = pkg)
-+ txmbrs = self.install(name=pkg, pkg_warning_level='debug2')
- except Errors.InstallError, e:
- self.verbose_logger.debug(_('No package named %s available to be installed'),
- pkg)
-@@ -3049,7 +3055,7 @@ class YumBase(depsolve.Depsolve):
- pkgs = self.pkgSack.searchPkgTuple(pkgtup)
+@@ -1680,10 +1775,11 @@ class YumBase(depsolve.Depsolve):
+ self.verbose_logger.debug('VerifyTransaction time: %0.3f' % (time.time() - vt_st))
- if len(pkgs) == 0:
-- self._add_not_found_a(pkgs, pkgtup)
-+ self._add_not_found_a(pkgs, pkgtup=pkgtup)
- if allow_missing: # This can happen due to excludes after .up has
- return None # happened.
- raise Errors.DepError, _('Package tuple %s could not be found in packagesack') % str(pkgtup)
-@@ -3071,7 +3077,7 @@ class YumBase(depsolve.Depsolve):
-
- pkgs = self.rpmdb.searchPkgTuple(pkgtup)
- if len(pkgs) == 0:
-- self._add_not_found_i(pkgs, pkgtup)
-+ self._add_not_found_i(pkgs, pkgtup=pkgtup)
- raise Errors.RpmDBError, _('Package tuple %s could not be found in rpmdb') % str(pkgtup)
+ def costExcludePackages(self):
+- """ Create an excluder for repos. with higher cost. Eg.
+- repo-A:cost=1 repo-B:cost=2 ... here we setup an excluder on repo-B
+- that looks for pkgs in repo-B."""
+-
++ """Create an excluder for repositories with higher costs. For
++ example, if repo-A:cost=1 and repo-B:cost=2, this function
++ will set up an excluder on repo-B that looks for packages in
++ repo-B.
++ """
+ # if all the repo.costs are equal then don't bother running things
+ costs = {}
+ for r in self.repos.listEnabled():
+@@ -1705,10 +1801,12 @@ class YumBase(depsolve.Depsolve):
+ done = True
+
+ def excludePackages(self, repo=None):
+- """removes packages from packageSacks based on global exclude lists,
+- command line excludes and per-repository excludes, takes optional
+- repo object to use."""
++ """Remove packages from packageSacks based on global exclude
++ lists, command line excludes and per-repository excludes.
+
++ :param repo: a repo object to use. If not given, all
++ repositories are used
++ """
+ if "all" in self.conf.disable_excludes:
+ return
+
+@@ -1735,9 +1833,11 @@ class YumBase(depsolve.Depsolve):
+ self.pkgSack.addPackageExcluder(repoid, exid,'exclude.match', match)
- # Dito. FIXME from getPackageObject() for len() > 1 ... :)
-@@ -3445,6 +3451,21 @@ class YumBase(depsolve.Depsolve):
-
- """
+ def includePackages(self, repo):
+- """removes packages from packageSacks based on list of packages, to include.
+- takes repoid as a mandatory argument."""
+-
++ """Remove packages from packageSacks based on list of
++ packages to include.
++
++ :param repo: the repository to use
++ """
+ includelist = repo.getIncludePkgList()
+ if len(includelist) == 0:
+@@ -1757,8 +1857,11 @@ class YumBase(depsolve.Depsolve):
+ self.pkgSack.addPackageExcluder(repo.id, exid, 'exclude.marked')
+
+ def doLock(self, lockfile = YUM_PID_FILE):
+- """perform the yum locking, raise yum-based exceptions, not OSErrors"""
+-
++ """Acquire the yum lock.
+
-+ # This is kind of hacky, we really need a better way to do errors than
-+ # doing them directly from .install/etc. ... but this is easy. *sigh*.
-+ # We are only using this in "groupinstall" atm. ... so we don't have
-+ # a long list of "blah already installed." messages when people run
-+ # "groupinstall mygroup" in yum-cron etc.
-+ pkg_warn = kwargs.get('pkg_warning_level', 'flibble')
-+ def _dbg2(*args, **kwargs):
-+ self.verbose_logger.log(logginglevels.DEBUG_2, *args, **kwargs)
-+ level2func = {'debug2' : _dbg2,
-+ 'warning' : self.verbose_logger.warning}
-+ if pkg_warn not in level2func:
-+ pkg_warn = 'warning'
-+ pkg_warn = level2func[pkg_warn]
++ :param lockfile: the file to use for the lock
++ :raises: :class:`yum.Errors.LockError`
++ """
+ if self.conf.uid != 0:
+ # If we are a user, assume we are using the root cache ... so don't
+ # bother locking.
+@@ -1804,8 +1907,12 @@ class YumBase(depsolve.Depsolve):
+ self._lockfile = lockfile
+
+ def doUnlock(self, lockfile=None):
+- """do the unlock for yum"""
+-
++ """Release the yum lock.
+
- pkgs = []
- was_pattern = False
- if po:
-@@ -3600,23 +3621,23 @@ class YumBase(depsolve.Depsolve):
- already_obs = pkgs[0]
++ :param lockfile: the lock file to use. If not given, the file
++ that was given as a parameter to the :func:`doLock` call
++ that closed the lock is used
++ """
+ # if we're not root then we don't lock - just return nicely
+ # Note that we can get here from __del__, so if we haven't created
+ # YumBase.conf we don't want to do so here as creating stuff inside
+@@ -1836,25 +1943,36 @@ class YumBase(depsolve.Depsolve):
+ if not os.path.exists(lockdir):
+ os.makedirs(lockdir, mode=0755)
+ fd = os.open(filename, os.O_EXCL|os.O_CREAT|os.O_WRONLY, mode)
++ os.write(fd, contents)
++ os.close(fd)
++ return 1
+ except OSError, 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, int(contents))
+ return 0
+- else:
+- os.write(fd, contents)
+- os.close(fd)
+- return 1
+
+ def _unlock(self, filename):
+ misc.unlink_f(filename)
+
+ def verifyPkg(self, fo, po, raiseError):
+- """verifies the package is what we expect it to be
+- raiseError = defaults to 0 - if 1 then will raise
+- a URLGrabError if the file does not check out.
+- otherwise it returns false for a failure, true for success"""
++ """Check that the checksum of a remote package matches what we
++ expect it to be. If the checksum of the package file is
++ wrong, and the file is also larger than expected, it cannot be
++ redeemed, so delete it.
++
++ :param fo: the file object of the package
++ :param po: the package object to verify
++ :param raiseError: if *raiseError* is 1, and the package
++ does not check out, a :class:`URLGrabError will be raised.
++ Defaults to 0
++ :return: True if the package is verified successfully.
++ Otherwise, False will be returned, unless *raiseError* is
++ 1, in which case a :class:`URLGrabError` will be raised
++ :raises: :class:`URLGrabError` if verification fails, and
++ *raiseError* is 1
++ """
+ failed = False
+
+ if type(fo) is types.InstanceType:
+@@ -1894,9 +2012,16 @@ class YumBase(depsolve.Depsolve):
+
+
+ def verifyChecksum(self, fo, checksumType, csum):
+- """Verify the checksum of the file versus the
+- provided checksum"""
+-
++ """Verify that the checksum of the given file matches the
++ given checksum.
++
++ :param fo: the file object to verify the checksum of
++ :param checksumType: the type of checksum to use
++ :parm csum: the checksum to check against
++ :return: 0 if the checksums match
++ :raises: :class:`URLGrabError` if there is an error performing
++ the checksums, or the checksums do not match
++ """
+ try:
+ filesum = misc.checksum(checksumType, fo)
+ except Errors.MiscError, e:
+@@ -1908,6 +2033,17 @@ class YumBase(depsolve.Depsolve):
+ return 0
+
+ def downloadPkgs(self, pkglist, callback=None, callback_total=None):
++ """Download the packages specified by the given list of
++ package objects.
++
++ :param pkglist: a list of package objects specifying the
++ packages to download
++ :param callback: unused
++ :param callback_total: a callback to output messages about the
++ download operation
++ :return: a dictionary containing errors from the downloading process
++ :raises: :class:`URLGrabError`
++ """
+ def mediasort(apo, bpo):
+ # FIXME: we should probably also use the mediaid; else we
+ # could conceivably ping-pong between different disc1's
+@@ -1998,16 +2134,6 @@ class YumBase(depsolve.Depsolve):
+ os.unlink(local)
+
+ checkfunc = (self.verifyPkg, (po, 1), {})
+- dirstat = os.statvfs(po.repo.pkgdir)
+- if (dirstat.f_bavail * dirstat.f_bsize) <= long(po.size):
+- adderror(po, _('Insufficient space in download directory %s\n'
+- " * free %s\n"
+- " * needed %s") %
+- (po.repo.pkgdir,
+- format_number(dirstat.f_bavail * dirstat.f_bsize),
+- format_number(po.size)))
+- continue
+-
+ try:
+ if i == 1 and not local_size and remote_size == po.size:
+ text = os.path.basename(po.relativepath)
+@@ -2032,7 +2158,7 @@ class YumBase(depsolve.Depsolve):
+ done_repos.add(po.repoid)
+
+ except Errors.RepoError, e:
+- adderror(po, str(e))
++ adderror(po, exception2msg(e))
+ else:
+ po.localpath = mylocal
+ if po in errors:
+@@ -2052,7 +2178,22 @@ class YumBase(depsolve.Depsolve):
+ return errors
+
+ def verifyHeader(self, fo, po, raiseError):
+- """check the header out via it's naevr, internally"""
++ """Check that the header of the given file object and matches
++ the given package.
++
++ :param fo: the file object to check
++ :param po: the package object to check
++ :param raiseError: if *raiseError* is True, a
++ :class:`URLGrabError` will be raised if the header matches
++ the package object, or cannot be read from the file. If
++ *raiseError* is False, 0 will be returned in the above
++ cases
++ :return: 1 if the header matches the package object, and 0 if
++ they do not match, and *raiseError* is False
++ :raises: :class:`URLGrabError` if *raiseError* is True, and
++ the header does not match the package object or cannot be
++ read from the file
++ """
+ if type(fo) is types.InstanceType:
+ fo = fo.filename
+
+@@ -2076,9 +2217,12 @@ class YumBase(depsolve.Depsolve):
+ return 1
+
+ def downloadHeader(self, po):
+- """download a header from a package object.
+- output based on callback, raise yum.Errors.YumBaseError on problems"""
++ """Download a header from a package object.
- if already_obs:
-- self.verbose_logger.warning(_('Package %s is obsoleted by %s which is already installed'),
-- po, already_obs)
-+ pkg_warn(_('Package %s is obsoleted by %s which is already installed'),
-+ po, already_obs)
- else:
- if 'provides_for' in kwargs:
- if not obsoleting_pkg.provides_for(kwargs['provides_for']):
++ :param po: the package object to download the header from
++ :raises: :class:`yum.Errors.RepoError` if there are errors
++ obtaining the header
++ """
+ if hasattr(po, 'pkgtype') and po.pkgtype == 'local':
+ return
+
+@@ -2122,15 +2266,17 @@ class YumBase(depsolve.Depsolve):
+ return
+
+ def sigCheckPkg(self, po):
+- '''
+- Take a package object and attempt to verify GPG signature if required
++ """Verify the GPG signature of the given package object.
+
+- Returns (result, error_string) where result is:
+- - 0 - GPG signature verifies ok or verification is not required.
+- - 1 - GPG verification failed but installation of the right GPG key
+- might help.
+- - 2 - Fatal GPG verification error, give up.
+- '''
++ :param po: the package object to verify the signature of
++ :return: (result, error_string)
++ where result is::
++
++ 0 = GPG signature verifies ok or verification is not required.
++ 1 = GPG verification failed but installation of the right GPG key
++ might help.
++ 2 = Fatal GPG verification error, give up.
++ """
+ if self._override_sigchecks:
+ check = False
+ hasgpgkey = 0
+@@ -2181,6 +2327,9 @@ class YumBase(depsolve.Depsolve):
+ return result, msg
+
+ def cleanUsedHeadersPackages(self):
++ """Delete the header and package files used in the
++ transaction from the yum cache.
++ """
+ filelist = []
+ for txmbr in self.tsInfo:
+ if txmbr.po.state not in TS_INSTALL_STATES:
+@@ -2218,27 +2367,40 @@ class YumBase(depsolve.Depsolve):
+ _('%s removed'), fn)
+
+ def cleanHeaders(self):
++ """Delete the header files from the yum cache."""
++
+ exts = ['hdr']
+ return self._cleanFiles(exts, 'hdrdir', 'header')
+
+ def cleanPackages(self):
++ """Delete the package files from the yum cache."""
++
+ exts = ['rpm']
+ return self._cleanFiles(exts, 'pkgdir', 'package')
+
+ def cleanSqlite(self):
++ """Delete the sqlite files from the yum cache."""
++
+ exts = ['sqlite', 'sqlite.bz2', 'sqlite-journal']
+ return self._cleanFiles(exts, 'cachedir', 'sqlite')
+
+ def cleanMetadata(self):
++ """Delete the metadata files from the yum cache."""
++
+ exts = ['xml.gz', 'xml', 'cachecookie', 'mirrorlist.txt', 'asc']
+ # Metalink is also here, but is a *.xml file
+ return self._cleanFiles(exts, 'cachedir', 'metadata')
+
+ def cleanExpireCache(self):
++ """Delete the local data saying when the metadata and mirror
++ lists were downloaded for each repository."""
++
+ exts = ['cachecookie', 'mirrorlist.txt']
+ return self._cleanFiles(exts, 'cachedir', 'metadata')
+
+ def cleanRpmDB(self):
++ """Delete any cached data from the local rpmdb."""
++
+ cachedir = self.conf.persistdir + "/rpmdb-indexes/"
+ if not os.path.exists(cachedir):
+ filelist = []
+@@ -2272,8 +2434,29 @@ class YumBase(depsolve.Depsolve):
+
+ def doPackageLists(self, pkgnarrow='all', patterns=None, showdups=None,
+ ignore_case=False):
+- """generates lists of packages, un-reduced, based on pkgnarrow option"""
+-
++ """Return a :class:`yum.misc.GenericHolder` containing
++ lists of package objects. The contents of the lists are
++ specified in various ways by the arguments.
++
++ :param pkgnarrow: a string specifying which types of packages
++ lists to produces, such as updates, installed, available,
++ etc.
++ :param patterns: a list of names or wildcards specifying
++ packages to list
++ :param showdups: whether to include duplicate packages in the
++ lists
++ :param ignore_case: whether to ignore case when searching by
++ package names
++ :return: a :class:`yum.misc.GenericHolder` instance with the
++ following lists defined::
++
++ available = list of packageObjects
++ installed = list of packageObjects
++ updates = tuples of packageObjects (updating, installed)
++ extras = list of packageObjects
++ obsoletes = tuples of packageObjects (obsoleting, installed)
++ recent = list of packageObjects
++ """
+ if showdups is None:
+ showdups = self.conf.showdupesfromrepos
+ ygh = misc.GenericHolder(iter=pkgnarrow)
+@@ -2461,14 +2644,13 @@ class YumBase(depsolve.Depsolve):
+
+
+ def findDeps(self, pkgs):
+- """
+- Return the dependencies for a given package object list, as well
+- possible solutions for those dependencies.
++ """Return the dependencies for a given package object list, as well
++ as possible solutions for those dependencies.
+
+- Returns the deps as a dict of dicts::
+- packageobject = [reqs] = [list of satisfying pkgs]
++ :param pkgs: a list of package objects
++ :return: the dependencies as a dictionary of dictionaries:
++ packageobject = [reqs] = [list of satisfying pkgs]
+ """
+-
+ results = {}
+
+ for pkg in pkgs:
+@@ -2495,10 +2677,22 @@ class YumBase(depsolve.Depsolve):
+ # pre 3.2.10 API used to always showdups, so that's the default atm.
+ def searchGenerator(self, fields, criteria, showdups=True, keys=False,
+ searchtags=True, searchrpmdb=True):
+- """Generator method to lighten memory load for some searches.
+- This is the preferred search function to use. Setting keys to True
+- will use the search keys that matched in the sorting, and return
+- the search keys in the results. """
++ """Yield the packages that match the given search criteria.
++ This generator method will lighten memory load for some
++ searches, and is the preferred search function to use.
++
++ :param fields: the fields to search
++ :param criteria: a list of strings specifying the criteria to
++ search for
++ :param showdups: whether to yield duplicate packages from
++ different repositories
++ :param keys: setting *keys* to True will use the search keys
++ that matched in the sorting, and return the search keys in
++ the results
++ :param searchtags: whether to search the package tags
++ :param searchrpmdb: whether to search the rmpdb
++
++ """
+ sql_fields = []
+ for f in fields:
+ sql_fields.append(RPM_TO_SQLITE.get(f, f))
+@@ -2661,6 +2855,14 @@ class YumBase(depsolve.Depsolve):
+ yield (po, vs)
+
+ def searchPackageTags(self, criteria):
++ """Search for and return a list packages that have tags
++ matching the given criteria.
++
++ :param criteria: a list of strings specifying the criteria to
++ search for
++ :return: a list of package objects that have tags matching the
++ given criteria
++ """
+ results = {} # name = [(criteria, taglist)]
+ for c in criteria:
+ c = c.lower()
+@@ -2677,11 +2879,16 @@ class YumBase(depsolve.Depsolve):
+ return results
+
+ def searchPackages(self, fields, criteria, callback=None):
+- """Search specified fields for matches to criteria
+- optional callback specified to print out results
+- as you go. Callback is a simple function of:
+- callback(po, matched values list). It will
+- just return a dict of dict[po]=matched values list"""
++ """Deprecated. Search the specified fields for packages that
++ match the given criteria, and return a list of the results.
++
++ :param fields: the fields to seach
++ :param criteria: a list of strings specifying the criteria to
++ search for
++ :param callback: a function to print out the results as they
++ are found. *callback* should have the form callback(po,
++ matched values list)
++ """
+ warnings.warn(_('searchPackages() will go away in a future version of Yum.\
+ Use searchGenerator() instead. \n'),
+ Errors.YumFutureDeprecationWarning, stacklevel=2)
+@@ -2700,6 +2907,19 @@ class YumBase(depsolve.Depsolve):
+
+ def searchPackageProvides(self, args, callback=None,
+ callback_has_matchfor=False):
++ """Search for and return a list package objects that provide
++ the given files or features.
++
++ :param args: a list of strings specifying the files and
++ features to search for the packages that provide
++ :param callback: a callback function to print out the results
++ as they are found
++ :param callback_has_matchfor: whether the callback function
++ will accept a list of strings to highlight in its output.
++ If this is true, *args* will be passed to *callback* so
++ that the files or features that were searched for can be
++ highlighted
++ """
+ def _arg_data(arg):
+ if not misc.re_glob(arg):
+ isglob = False
+@@ -2818,11 +3038,17 @@ class YumBase(depsolve.Depsolve):
+ return matches
+
+ def doGroupLists(self, uservisible=0, patterns=None, ignore_case=True):
+- """returns two lists of groups, installed groups and available groups
+- optional 'uservisible' bool to tell it whether or not to return
+- only groups marked as uservisible"""
+-
+-
++ """Return two lists of groups: installed groups and available
++ groups.
++
++ :param uservisible: If True, only groups marked as uservisible
++ will be returned. Otherwise, all groups will be returned
++ :param patterns: a list of stings. If given, only groups
++ with names that match the patterns will be included in the
++ lists. If not given, all groups will be included
++ :param ignore_case: whether to ignore case when determining
++ whether group names match the strings in *patterns*
++ """
+ installed = []
+ available = []
+
+@@ -2852,8 +3078,13 @@ class YumBase(depsolve.Depsolve):
+
+
+ def groupRemove(self, grpid):
+- """mark all the packages in this group to be removed"""
+-
++ """Mark all the packages in the given group to be removed.
++
++ :param grpid: the name of the group containing the packages to
++ mark for removal
++ :return: a list of transaction members added to the
++ transaction set by this function
++ """
+ txmbrs_used = []
+
+ thesegroups = self.comps.return_groups(grpid)
+@@ -2872,9 +3103,10 @@ class YumBase(depsolve.Depsolve):
+ return txmbrs_used
+
+ def groupUnremove(self, grpid):
+- """unmark any packages in the group from being removed"""
+-
++ """Unmark any packages in the given group from being removed.
+
++ :param grpid: the name of the group to unmark the packages of
++ """
+ thesegroups = self.comps.return_groups(grpid)
+ if not thesegroups:
+ raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid)
+@@ -2899,12 +3131,16 @@ class YumBase(depsolve.Depsolve):
+
+
+ def selectGroup(self, grpid, group_package_types=[], enable_group_conditionals=None):
+- """mark all the packages in the group to be installed
+- returns a list of transaction members it added to the transaction
+- set
+- Optionally take:
+- group_package_types=List - overrides self.conf.group_package_types
+- enable_group_conditionals=Bool - overrides self.conf.enable_group_conditionals
++ """Mark all the packages in the given group to be installed.
++
++ :param grpid: the name of the group containing the packages to
++ mark for installation
++ :param group_package_types: a list of the types of groups to
++ work with. This overrides self.conf.group_package_types
++ :param enable_group_conditionals: overrides
++ self.conf.enable_group_conditionals
++ :return: a list of transaction members added to the
++ transaction set by this function
+ """
+
+ if not self.comps.has_group(grpid):
+@@ -2939,7 +3175,7 @@ class YumBase(depsolve.Depsolve):
+ self.verbose_logger.log(logginglevels.DEBUG_2,
+ _('Adding package %s from group %s'), pkg, thisgroup.groupid)
+ try:
+- txmbrs = self.install(name = pkg)
++ txmbrs = self.install(name=pkg, pkg_warning_level='debug2')
+ except Errors.InstallError, e:
+ self.verbose_logger.debug(_('No package named %s available to be installed'),
+ pkg)
+@@ -2997,10 +3233,14 @@ class YumBase(depsolve.Depsolve):
+ return txmbrs_used
+
+ def deselectGroup(self, grpid, force=False):
+- """ Without the force option set, this removes packages from being
+- installed that were added as part of installing one of the
+- group(s). If the force option is set, then all installing packages
+- in the group(s) are force removed from the transaction. """
++ """Unmark the packages in the given group from being
++ installed.
++
++ :param grpid: the name of the group containing the packages to
++ unmark from installation
++ :param force: if True, force remove all the packages in the
++ given group from the transaction
++ """
+
+ if not self.comps.has_group(grpid):
+ raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid)
+@@ -3035,12 +3275,21 @@ class YumBase(depsolve.Depsolve):
+ self.tsInfo.remove(pkg.pkgtup)
+
+ def getPackageObject(self, pkgtup, allow_missing=False):
+- """retrieves a packageObject from a pkgtuple - if we need
+- to pick and choose which one is best we better call out
+- to some method from here to pick the best pkgobj if there are
+- more than one response - right now it's more rudimentary."""
+-
+-
++ """Return a package object that corresponds to the given
++ package tuple.
++
++ :param pkgtup: the package tuple specifying the package object
++ to return
++
++ :param allow_missing: If no package corresponding to the given
++ package tuple can be found, None is returned if
++ *allow_missing* is True, and a :class:`yum.Errors.DepError` is
++ raised if *allow_missing* is False.
++ :return: a package object corresponding to the given package tuple
++ :raises: a :class:`yum.Errors.DepError` if no package
++ corresponding to the given package tuple can be found, and
++ *allow_missing* is False
++ """
+ # look it up in the self.localPackages first:
+ for po in self.localPackages:
+ if po.pkgtup == pkgtup:
+@@ -3049,7 +3298,7 @@ class YumBase(depsolve.Depsolve):
+ pkgs = self.pkgSack.searchPkgTuple(pkgtup)
+
+ if len(pkgs) == 0:
+- self._add_not_found_a(pkgs, pkgtup)
++ self._add_not_found_a(pkgs, pkgtup=pkgtup)
+ if allow_missing: # This can happen due to excludes after .up has
+ return None # happened.
+ raise Errors.DepError, _('Package tuple %s could not be found in packagesack') % str(pkgtup)
+@@ -3065,13 +3314,21 @@ class YumBase(depsolve.Depsolve):
+ return result
+
+ def getInstalledPackageObject(self, pkgtup):
+- """ Returns a YumInstalledPackage object for the pkgtup specified, or
+- raises an exception. You should use this instead of
+- searchPkgTuple() if you are assuming there is a value. """
+-
++ """Return a :class:`yum.packages.YumInstalledPackage` object that
++ corresponds to the given package tuple. This function should
++ be used instead of :func:`searchPkgTuple` if you are assuming
++ that the package object exists.
++
++ :param pkgtup: the package tuple specifying the package object
++ to return
++ :return: a :class:`yum.packages.YumInstalledPackage` object corresponding
++ to the given package tuple
++ :raises: a :class:`yum.Errors.RpmDBError` if the specified package
++ object cannot be found
++ """
+ pkgs = self.rpmdb.searchPkgTuple(pkgtup)
+ if len(pkgs) == 0:
+- self._add_not_found_i(pkgs, pkgtup)
++ self._add_not_found_i(pkgs, pkgtup=pkgtup)
+ raise Errors.RpmDBError, _('Package tuple %s could not be found in rpmdb') % str(pkgtup)
+
+ # Dito. FIXME from getPackageObject() for len() > 1 ... :)
+@@ -3079,9 +3336,11 @@ class YumBase(depsolve.Depsolve):
+ return po
+
+ def gpgKeyCheck(self):
+- """checks for the presence of gpg keys in the rpmdb
+- returns 0 if no keys returns 1 if keys"""
++ """Checks for the presence of GPG keys in the rpmdb.
+
++ :return: 0 if there are no GPG keys in the rpmdb, and 1 if
++ there are keys
++ """
+ gpgkeyschecked = self.conf.cachedir + '/.gpgkeyschecked.yum'
+ if os.path.exists(gpgkeyschecked):
+ return 1
+@@ -3106,9 +3365,13 @@ class YumBase(depsolve.Depsolve):
+ return 1
+
+ def returnPackagesByDep(self, depstring):
+- """Pass in a generic [build]require string and this function will
+- pass back the packages it finds providing that dep."""
++ """Return a list of package objects that provide the given
++ dependencies.
+
++ :param depstring: a string specifying the dependency to return
++ the packages that fulfil
++ :return: a list of packages that fulfil the given dependency
++ """
+ if not depstring:
+ return []
+
+@@ -3135,9 +3398,16 @@ class YumBase(depsolve.Depsolve):
+ return self.pkgSack.getProvides(depname, depflags, depver).keys()
+
+ def returnPackageByDep(self, depstring):
+- """Pass in a generic [build]require string and this function will
+- pass back the best(or first) package it finds providing that dep."""
+-
++ """Return the best, or first, package object that provides the
++ given dependencies.
++
++ :param depstring: a string specifying the dependency to return
++ the package that fulfils
++ :return: the best, or first, package that fulfils the given
++ dependency
++ :raises: a :class:`yum.Errors.YumBaseError` if no packages that
++ fulfil the given dependency can be found
++ """
+ # we get all sorts of randomness here
+ errstring = depstring
+ if type(depstring) not in types.StringTypes:
+@@ -3156,9 +3426,14 @@ class YumBase(depsolve.Depsolve):
+ return result
+
+ def returnInstalledPackagesByDep(self, depstring):
+- """Pass in a generic [build]require string and this function will
+- pass back the installed packages it finds providing that dep."""
+-
++ """Return a list of installed package objects that provide the
++ given dependencies.
++
++ :param depstring: a string specifying the dependency to return
++ the packages that fulfil
++ :return: a list of installed packages that fulfil the given
++ dependency
++ """
+ if not depstring:
+ return []
+
+@@ -3202,10 +3477,17 @@ class YumBase(depsolve.Depsolve):
+ return bestlist[0][0]
+
+ def bestPackagesFromList(self, pkglist, arch=None, single_name=False):
+- """Takes a list of packages, returns the best packages.
+- This function is multilib aware so that it will not compare
+- multilib to singlelib packages"""
+-
++ """Return the best packages from a list of packages. This
++ function is multilib aware, so that it will not compare
++ multilib to singlelib packages.
++
++ :param pkglist: the list of packages to return the best
++ packages from
++ :param arch: packages will be selected that are compatible
++ with the architecture specified by *arch*
++ :param single_name: whether to return a single package name
++ :return: a list of the best packages from *pkglist*
++ """
+ returnlist = []
+ compatArchList = self.arch.get_arch_list(arch)
+ multiLib = []
+@@ -3438,13 +3720,35 @@ class YumBase(depsolve.Depsolve):
+ self.tsInfo.probFilterFlags.append(flag)
+
+ def install(self, po=None, **kwargs):
+- """try to mark for install the item specified. Uses provided package
+- object, if available. If not it uses the kwargs and gets the best
+- packages from the keyword options provided
+- returns the list of txmbr of the items it installs
+-
+- """
++ """Mark the specified item for installation. If a package
++ object is given, mark it for installation. Otherwise, mark
++ the best package specified by the key word arguments for
++ installation.
++
++ :param po: a package object to install
++ :param kwargs: if *po* is not specified, these keyword
++ arguments will be used to find the best package to install
++ :return: a list of the transaction members added to the
++ transaction set by this function
++ :raises: :class:`yum.Errors.InstallError` if there is a problem
++ installing the package
++ """
+
++
++ # This is kind of hacky, we really need a better way to do errors than
++ # doing them directly from .install/etc. ... but this is easy. *sigh*.
++ # We are only using this in "groupinstall" atm. ... so we don't have
++ # a long list of "blah already installed." messages when people run
++ # "groupinstall mygroup" in yum-cron etc.
++ pkg_warn = kwargs.get('pkg_warning_level', 'flibble')
++ def _dbg2(*args, **kwargs):
++ self.verbose_logger.log(logginglevels.DEBUG_2, *args, **kwargs)
++ level2func = {'debug2' : _dbg2,
++ 'warning' : self.verbose_logger.warning}
++ if pkg_warn not in level2func:
++ pkg_warn = 'warning'
++ pkg_warn = level2func[pkg_warn]
++
+ pkgs = []
+ was_pattern = False
+ if po:
+@@ -3600,23 +3904,23 @@ class YumBase(depsolve.Depsolve):
+ already_obs = pkgs[0]
+
+ if already_obs:
+- self.verbose_logger.warning(_('Package %s is obsoleted by %s which is already installed'),
+- po, already_obs)
++ pkg_warn(_('Package %s is obsoleted by %s which is already installed'),
++ po, already_obs)
+ else:
+ if 'provides_for' in kwargs:
+ if not obsoleting_pkg.provides_for(kwargs['provides_for']):
- self.verbose_logger.warning(_('Package %s is obsoleted by %s, but obsoleting package does not provide for requirements'),
- po.name, obsoleting_pkg.name)
+ pkg_warn(_('Package %s is obsoleted by %s, but obsoleting package does not provide for requirements'),
@@ -5051,7 +6581,7 @@ index 99039e0..530bfd4 100644
continue
# make sure we don't have a name.arch of this already installed
-@@ -3630,7 +3651,7 @@ class YumBase(depsolve.Depsolve):
+@@ -3630,7 +3934,7 @@ class YumBase(depsolve.Depsolve):
found = True
break
if not found:
@@ -5060,7 +6590,268 @@ index 99039e0..530bfd4 100644
txmbrs = self.update(po=po)
tx_return.extend(txmbrs)
continue
-@@ -4725,7 +4746,9 @@ class YumBase(depsolve.Depsolve):
+@@ -3719,14 +4023,33 @@ class YumBase(depsolve.Depsolve):
+ return txmbr
+
+ def update(self, po=None, requiringPo=None, update_to=False, **kwargs):
+- """try to mark for update the item(s) specified.
+- po is a package object - if that is there, mark it for update,
+- if possible
+- else use **kwargs to match the package needing update
+- if nothing is specified at all then attempt to update everything
++ """Mark the specified items to be updated. If a package
++ object is given, mark it. Else, if a package is specified by
++ the keyword arguments, mark it. Finally, if nothing is given,
++ mark all installed packages to be updated.
++
++
++ :param po: the package object to be marked for updating
++ :param requiringPo: the package object that requires the
++ upgrade
++ :param update_to: if *update_to* is True, the update will only
++ be run if it will update the given package to the given
++ version. For example, if the package foo-1-2 is installed,::
++
++ updatePkgs(["foo-1-2], update_to=False)
++ will work identically to::
+
+- returns the list of txmbr of the items it marked for update"""
+-
++ updatePkgs(["foo"])
++ but::
++
++ updatePkgs(["foo-1-2"], update_to=True)
++
++ will do nothing
++ :param kwargs: if *po* is not given, the names or wildcards in
++ *kwargs* will be used to find the packages to update
++ :return: a list of transaction members added to the
++ transaction set by this function
++ """
+ # check for args - if no po nor kwargs, do them all
+ # if po, do it, ignore all else
+ # if no po do kwargs
+@@ -3985,11 +4308,18 @@ class YumBase(depsolve.Depsolve):
+ return tx_return
+
+ def remove(self, po=None, **kwargs):
+- """try to find and mark for remove the specified package(s) -
+- if po is specified then that package object (if it is installed)
+- will be marked for removal.
+- if no po then look at kwargs, if neither then raise an exception"""
+-
++ """Mark the specified packages for removal. If a package
++ object is given, mark it for removal. Otherwise, mark the
++ package specified by the keyword arguments.
++
++ :param po: the package object to mark for installation
++ :param kwargs: If *po* is not given, the keyword arguments
++ will be used to specify a package to mark for installation
++ :return: a list of the transaction members that were added to
++ the transaction set by this method
++ :raises: :class:`yum.Errors.RemoveError` if nothing is specified
++ to mark for removal
++ """
+ if not po and not kwargs:
+ raise Errors.RemoveError, 'Nothing specified to remove'
+
+@@ -4055,17 +4385,19 @@ class YumBase(depsolve.Depsolve):
+ return tx_return
+
+ def installLocal(self, pkg, po=None, updateonly=False):
++ """Mark a package on the local filesystem (i.e. not from a
++ repository) for installation.
++
++ :param pkg: a string specifying the path to an rpm file in the
++ local filesystem to be marked for installation
++ :param po: a :class:`yum.packages.YumLocalPackage`
++ :param updateonly: if True, the given package will only be
++ marked for installation if it is an upgrade for a package
++ that is already installed. If False, this restriction is
++ not enforced
++ :return: a list of the transaction members added to the
++ transaction set by this method
+ """
+- handles installs/updates of rpms provided on the filesystem in a
+- local dir (ie: not from a repo)
+-
+- Return the added transaction members.
+-
+- @param pkg: a path to an rpm file on disk.
+- @param po: A YumLocalPackage
+- @param updateonly: Whether or not true installs are valid.
+- """
+-
+ # read in the package into a YumLocalPackage Object
+ # append it to self.localPackages
+ # check if it can be installed or updated based on nevra versus rpmdb
+@@ -4183,16 +4515,15 @@ class YumBase(depsolve.Depsolve):
+ return tx_return
+
+ def reinstallLocal(self, pkg, po=None):
++ """Mark a package on the local filesystem (i.e. not from a
++ repository) for reinstallation.
++
++ :param pkg: a string specifying the path to an rpm file in the
++ local filesystem to be marked for reinstallation
++ :param po: a :class:`yum.packages.YumLocalPackage`
++ :return: a list of the transaction members added to the
++ transaction set by this method
+ """
+- handles reinstall of rpms provided on the filesystem in a
+- local dir (ie: not from a repo)
+-
+- Return the added transaction members.
+-
+- @param pkg: a path to an rpm file on disk.
+- @param po: A YumLocalPackage
+- """
+-
+ if not po:
+ try:
+ po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg,
+@@ -4215,9 +4546,19 @@ class YumBase(depsolve.Depsolve):
+ return self.reinstall(po=po)
+
+ def reinstall(self, po=None, **kwargs):
+- """Setup the problem filters to allow a reinstall to work, then
+- pass everything off to install"""
+-
++ """Mark the given package for reinstallation. This is
++ accomplished by setting problem filters to allow a reinstall
++ take place, then calling :func:`install`.
++
++ :param po: the package object to mark for reinstallation
++ :param kwargs: if po is not given, the keyword will be used to
++ specify a package for reinstallation
++ :return: a list of the transaction members added to the
++ transaction set by this method
++ :raises: :class:`yum.Errors.ReinstallRemoveError` or
++ :class:`yum.Errors.ReinstallInstallError` depending the nature
++ of the error that is encountered
++ """
+ self._add_prob_flags(rpm.RPMPROB_FILTER_REPLACEPKG,
+ rpm.RPMPROB_FILTER_REPLACENEWFILES,
+ rpm.RPMPROB_FILTER_REPLACEOLDFILES)
+@@ -4259,16 +4600,15 @@ class YumBase(depsolve.Depsolve):
+ return tx_mbrs
+
+ def downgradeLocal(self, pkg, po=None):
++ """Mark a package on the local filesystem (i.e. not from a
++ repository) to be downgraded.
++
++ :param pkg: a string specifying the path to an rpm file in the
++ local filesystem to be marked to be downgraded
++ :param po: a :class:`yum.packages.YumLocalPackage`
++ :return: a list of the transaction members added to the
++ transaction set by this method
+ """
+- handles downgrades of rpms provided on the filesystem in a
+- local dir (ie: not from a repo)
+-
+- Return the added transaction members.
+-
+- @param pkg: a path to an rpm file on disk.
+- @param po: A YumLocalPackage
+- """
+-
+ if not po:
+ try:
+ po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg,
+@@ -4309,13 +4649,19 @@ class YumBase(depsolve.Depsolve):
+ return False
+
+ def downgrade(self, po=None, **kwargs):
+- """ Try to downgrade a package. Works like:
+- % yum shell <<EOL
+- remove abcd
+- install abcd-<old-version>
+- run
+- EOL """
+-
++ """Mark a package to be downgraded. This is equivalent to
++ first removing the currently installed package, and then
++ installing the older version.
++
++ :param po: the package object to be marked to be downgraded
++ :param kwargs: if a package object is not given, the keyword
++ arguments will be used to specify a package to be marked to
++ be downgraded
++ :return: a list of the transaction members added to the
++ transaction set by this method
++ :raises: :class:`yum.Errors.DowngradeError` if no packages are
++ specified or available for downgrade
++ """
+ if not po and not kwargs:
+ raise Errors.DowngradeError, 'Nothing specified to downgrade'
+
+@@ -4501,8 +4847,14 @@ class YumBase(depsolve.Depsolve):
+ return returndict
+
+ def history_redo(self, transaction):
+- """ Given a valid historical transaction object, try and repeat
+- that transaction. """
++ """Repeat the transaction represented by the given
++ :class:`yum.history.YumHistoryTransaction` object.
++
++ :param transaction: a
++ :class:`yum.history.YumHistoryTransaction` object
++ representing the transaction to be repeated
++ :return: whether the transaction was repeated successfully
++ """
+ # NOTE: This is somewhat basic atm. ... see comment in undo.
+ # Also note that redo doesn't force install Dep-Install packages,
+ # which is probably what is wanted the majority of the time.
+@@ -4538,8 +4890,14 @@ class YumBase(depsolve.Depsolve):
+ return done
+
+ def history_undo(self, transaction):
+- """ Given a valid historical transaction object, try and undo
+- that transaction. """
++ """Undo the transaction represented by the given
++ :class:`yum.history.YumHistoryTransaction` object.
++
++ :param transaction: a
++ :class:`yum.history.YumHistoryTransaction` object
++ representing the transaction to be undone
++ :return: whether the transaction was undone successfully
++ """
+ # 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 :).
+@@ -4689,19 +5047,18 @@ class YumBase(depsolve.Depsolve):
+ self.logger.critical("%s", msg)
+
+ def getKeyForPackage(self, po, askcb = None, fullaskcb = None):
+- """
+- Retrieve a key for a package. If needed, prompt for if the key should
+- be imported using askcb.
+-
+- @param po: Package object to retrieve the key of.
+- @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 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.
++ """Retrieve a key for a package. If needed, use the given
++ callback to prompt whether the key should be imported.
++
++ :param po: the package object to retrieve the key of
++ :param askcb: Callback function to use to ask permission to
++ import a key. The arguments *askck* should take are the
++ package object, the userid of the key, and the keyid
++ :param fullaskcb: Callback function to use to ask permission to
++ import a key. This differs from *askcb* in that it gets
++ passed a dictionary so that we can expand the values passed.
++ :raises: :class:`yum.Errors.YumBaseError` if there are errors
++ retrieving the keys
+ """
+ repo = self.repos.getRepo(po.repoid)
+ keyurls = repo.gpgkey
+@@ -4725,7 +5082,9 @@ class YumBase(depsolve.Depsolve):
# Try installing/updating GPG key
self._getKeyImportMessage(info, keyurl)
rc = False
@@ -5071,7 +6862,7 @@ index 99039e0..530bfd4 100644
rc = True
# grab the .sig/.asc for the keyurl, if it exists
-@@ -4819,8 +4842,11 @@ class YumBase(depsolve.Depsolve):
+@@ -4819,8 +5178,11 @@ class YumBase(depsolve.Depsolve):
if not key_installed:
self._getKeyImportMessage(info, keyurl, keytype)
rc = False
@@ -5084,7 +6875,156 @@ index 99039e0..530bfd4 100644
elif callback:
rc = callback({"repo": repo, "userid": info['userid'],
"hexkeyid": info['hexkeyid'], "keyurl": keyurl,
-@@ -5234,7 +5260,7 @@ class YumBase(depsolve.Depsolve):
+@@ -4861,26 +5223,23 @@ class YumBase(depsolve.Depsolve):
+ 'this repository.') % (repo.name)
+
+ def getKeyForRepo(self, repo, callback=None):
+- """
+- Retrieve a key for a repository If needed, prompt for if the key should
+- be imported using callback
+-
+- @param repo: Repository object to retrieve the key of.
+- @param callback: Callback function to use for asking for verification
+- of a key. Takes a dictionary of key info.
++ """Retrieve a key for a repository. If needed, use the given
++ callback to prompt whether the key should be imported.
++
++ :param repo: repository object to retrieve the key of
++ :param callback: callback function to use for asking for
++ verification of key information
+ """
+ self._getAnyKeyForRepo(repo, repo.gpgdir, repo.gpgkey, is_cakey=False, callback=callback)
+
+ def getCAKeyForRepo(self, repo, callback=None):
+- """
+- Retrieve a key for a repository If needed, prompt for if the key should
+- be imported using callback
+-
+- @param repo: Repository object to retrieve the key of.
+- @param callback: Callback function to use for asking for verification
+- of a key. Takes a dictionary of key info.
+- """
++ """Retrieve a key for a repository. If needed, use the given
++ callback to prompt whether the key should be imported.
+
++ :param repo: repository object to retrieve the key of
++ :param callback: callback function to use for asking for
++ verification of key information
++ """
+ self._getAnyKeyForRepo(repo, repo.gpgcadir, repo.gpgcakey, is_cakey=True, callback=callback)
+
+ def _limit_installonly_pkgs(self):
+@@ -4959,19 +5318,22 @@ class YumBase(depsolve.Depsolve):
+ txmbr.depends_on.append(rel)
+
+ def processTransaction(self, callback=None,rpmTestDisplay=None, rpmDisplay=None):
+- '''
+- Process the current Transaction
+- - Download Packages
+- - Check GPG Signatures.
+- - Run Test RPM Transaction
+- - Run RPM Transaction
+-
+- callback.event method is called at start/end of each process.
+-
+- @param callback: callback object (must have an event method)
+- @param rpmTestDisplay: Name of display class to use in RPM Test Transaction
+- @param rpmDisplay: Name of display class to use in RPM Transaction
+- '''
++ """Process the current transaction. This involves the
++ following steps:
++ - Download the packages
++ - Check the GPG signatures of the packages
++ - Run the test RPM transaction
++ - Run the RPM Transaction
++ The *callback*.event method is called at the start, and
++ between each step.
++
++ :param callback: a callback object, which must have an event
++ method
++ :param rpmTestDisplay: name of the display class to use in the
++ RPM test transaction
++ :param rpmDisplay: name of the display class to use in the rpm
++ transaction
++ """
+
+ if not callback:
+ callback = callbacks.ProcessTransNoOutputCallback()
+@@ -5114,13 +5476,19 @@ class YumBase(depsolve.Depsolve):
+ return results
+
+ def add_enable_repo(self, repoid, baseurls=[], mirrorlist=None, **kwargs):
+- """add and enable a repo with just a baseurl/mirrorlist and repoid
+- requires repoid and at least one of baseurl and mirrorlist
+- additional optional kwargs are:
+- variable_convert=bool (defaults to true)
+- and any other attribute settable to the normal repo setup
+- ex: metadata_expire, enable_groups, gpgcheck, cachedir, etc
+- returns the repo object it added"""
++ """Add and enable a repository.
++
++ :param repoid: a string specifying the name of the repository
++ :param baseurls: a list of strings specifying the urls for
++ the repository. At least one base url, or one mirror, must
++ be given
++ :param mirrorlist: a list of strings specifying a list of
++ mirrors for the repository. At least one base url, or one
++ mirror must be given
++ :param kwargs: key word arguments to set any normal repository
++ attribute
++ :return: the new repository that has been added and enabled
++ """
+ # out of place fixme - maybe we should make this the default repo addition
+ # routine and use it from getReposFromConfigFile(), etc.
+ newrepo = yumRepo.YumRepository(repoid)
+@@ -5167,9 +5535,15 @@ class YumBase(depsolve.Depsolve):
+
+ def setCacheDir(self, force=False, tmpdir=None, reuse=True,
+ suffix='/$basearch/$releasever'):
+- ''' Set a new cache dir, using misc.getCacheDir() and var. replace
+- on suffix. '''
+-
++ """Set a new cache directory.
++
++ :param force: whether to force the cache directory to be
++ changed
++ :param tmpdir: a temporary directory
++ :param reuse: whether the temporary directory can be reused
++ :param suffix: suffix to attach to the directory name
++ :return: whether the new cache directory is successfully set
++ """
+ if not force and os.geteuid() == 0:
+ return True # We are root, not forced, so happy with the global dir.
+ if tmpdir is None:
+@@ -5220,13 +5594,24 @@ class YumBase(depsolve.Depsolve):
+ self.history.write_addon_data('config-repos', myrepos)
+
+ def verify_plugins_cb(self, verify_package):
+- """ Callback to call a plugin hook for pkg.verify(). """
++ """Callback to call a plugin hook for pkg.verify().
++
++ :param verify_package: a conduit for the callback
++ :return: *verify_package*
++ """
+ self.plugins.run('verify_package', verify_package=verify_package)
+ return verify_package
+
+ def save_ts(self, filename=None, auto=False):
+- """saves out a transaction to .yumtx file to be loaded later"""
+-
++ """Save out a transaction to a .yumtx file to be loaded later.
++
++ :param filename: the name of the file to save the transaction
++ in. If *filename* is not given, a name will be generated
++ :param auto: whether to output errors to the logger, rather
++ than raising exceptions
++ :raises: :class:`yum.Errors.YumBaseError` if there are errors
++ saving the transaction
++ """
+ if self.tsInfo._unresolvedMembers:
+ if auto:
+ self.logger.critical(_("Dependencies not solved. Will not save unresolved transaction."))
+@@ -5234,7 +5619,7 @@ class YumBase(depsolve.Depsolve):
raise Errors.YumBaseError(_("Dependencies not solved. Will not save unresolved transaction."))
if not filename:
@@ -5093,7 +7033,26 @@ index 99039e0..530bfd4 100644
fd,filename = tempfile.mkstemp(suffix='.yumtx', prefix=prefix)
f = os.fdopen(fd, 'w')
else:
-@@ -5292,6 +5318,16 @@ class YumBase(depsolve.Depsolve):
+@@ -5266,7 +5651,17 @@ class YumBase(depsolve.Depsolve):
+
+
+ def load_ts(self, filename, ignorerpm=None, ignoremissing=None):
+- """loads a transaction from a .yumtx file"""
++ """Load a transaction from a .yumtx file.
++
++ :param filename: the name of the file to load the transaction
++ from
++ :param ignorerpm: whether to ignore messages from rpm
++ :param ignoremissing: whether to ignore that there may be
++ transaction members missing
++ :return: the members of the loaded transaction
++ :raises: :class:`yum.Errors.YumBaseError` if there are problems
++ loading the transaction
++ """
+ # check rpmversion - if not match throw a fit
+ # check repoversions (and repos)- if not match throw a fit
+ # load each txmbr - if pkgs being updated don't exist, bail w/error
+@@ -5292,6 +5687,16 @@ class YumBase(depsolve.Depsolve):
# 3+numrepos = num pkgs
# 3+numrepos+1 -> EOF= txmembers
@@ -5258,7 +7217,7 @@ index 7ad25ce..a9a8e53 100644
pass
diff --git a/yum/config.py b/yum/config.py
-index d09511f..bbeca66 100644
+index d09511f..ef1b9e1 100644
--- a/yum/config.py
+++ b/yum/config.py
@@ -47,13 +47,12 @@ __pkgs_gpgcheck_default__ = False
@@ -5719,11 +7678,11 @@ index d09511f..bbeca66 100644
- Invalid inputs: -10, -0.1, 45.6L, 123Mb
-
- Return value will always be an integer
+-
+- 1k = 1024 bytes.
+ Valid inputs: 100, 123M, 45.6k, 12.4G, 100K, 786.3, 0.
+ Invalid inputs: -10, -0.1, 45.6L, 123Mb.
-- 1k = 1024 bytes.
--
- ValueError will be raised if the option couldn't be parsed.
+ :param s: the string to parse
+ :return: the number of bytes represented by *s*
@@ -5952,7 +7911,25 @@ index d09511f..bbeca66 100644
alwaysprompt = BoolOption(True)
exactarch = BoolOption(True)
tolerant = BoolOption(True)
-@@ -756,6 +845,12 @@ class YumConf(StartupConf):
+@@ -686,6 +775,9 @@ class YumConf(StartupConf):
+
+ bandwidth = BytesOption(0)
+ throttle = ThrottleOption(0)
++ ip_resolve = CaselessSelectionOption(
++ allowed = ('ipv4', 'ipv6', 'whatever'),
++ mapper = {'4': 'ipv4', '6': 'ipv6'})
+
+ http_caching = SelectionOption('all', ('none', 'packages', 'all'))
+ metadata_expire = SecondsOption(60 * 60 * 6) # Time in seconds (6h).
+@@ -747,6 +839,7 @@ class YumConf(StartupConf):
+
+ clean_requirements_on_remove = BoolOption(False)
+
++ upgrade_requirements_on_install = BoolOption(False)
+
+ history_list_view = SelectionOption('single-user-commands',
+ ('single-user-commands', 'users',
+@@ -756,6 +849,12 @@ class YumConf(StartupConf):
_reposlist = []
def dump(self):
@@ -5965,7 +7942,7 @@ index d09511f..bbeca66 100644
output = '[main]\n'
# we exclude all vars which start with _ or are in this list:
excluded_vars = ('cfg', 'uid', 'yumvar', 'progress_obj', 'failure_obj',
-@@ -778,14 +873,12 @@ class YumConf(StartupConf):
+@@ -778,14 +877,12 @@ class YumConf(StartupConf):
return output
class RepoConf(BaseConfig):
@@ -5983,7 +7960,16 @@ index d09511f..bbeca66 100644
ck = self.__cached_keys
if not isinstance(self, RepoConf):
ck = set()
-@@ -839,23 +932,23 @@ class RepoConf(BaseConfig):
+@@ -823,6 +920,8 @@ class RepoConf(BaseConfig):
+ bandwidth = Inherit(YumConf.bandwidth)
+ throttle = Inherit(YumConf.throttle)
+ timeout = Inherit(YumConf.timeout)
++ ip_resolve = Inherit(YumConf.ip_resolve)
++
+ http_caching = Inherit(YumConf.http_caching)
+ metadata_expire = Inherit(YumConf.metadata_expire)
+ mirrorlist_expire = Inherit(YumConf.mirrorlist_expire)
+@@ -839,23 +938,23 @@ class RepoConf(BaseConfig):
skip_if_unavailable = BoolOption(False)
class VersionGroupConf(BaseConfig):
@@ -5993,12 +7979,13 @@ index d09511f..bbeca66 100644
run_with_packages = BoolOption(False)
- def readStartupConfig(configfile, root):
+-def readStartupConfig(configfile, root):
- '''
- Parse Yum's main configuration file and return a StartupConf instance.
-
- This is required in order to access configuration settings required as Yum
- starts up.
++def readStartupConfig(configfile, root, releasever=None):
+ """Parse Yum's main configuration file and return a
+ :class:`StartupConf` instance. This is required in order to
+ access configuration settings required as Yum starts up.
@@ -6017,7 +8004,21 @@ index d09511f..bbeca66 100644
# ' xemacs syntax hack
-@@ -884,12 +977,11 @@ def readStartupConfig(configfile, root):
+@@ -876,20 +975,24 @@ def readStartupConfig(configfile, root):
+ raise Errors.ConfigError("All plugin search paths must be absolute")
+ # Stuff this here to avoid later re-parsing
+ startupconf._parser = parser
++
+ # setup the release ver here
+- startupconf.releasever = _getsysver(startupconf.installroot, startupconf.distroverpkg)
++ if releasever is None:
++ releasever = _getsysver(startupconf.installroot,
++ startupconf.distroverpkg)
++ startupconf.releasever = releasever
++
+ uuidfile = '%s/%s/uuid' % (startupconf.installroot, startupconf.persistdir)
+ startupconf.uuid = get_uuid(uuidfile)
+
return startupconf
def readMainConfig(startupconf):
@@ -6034,7 +8035,7 @@ index d09511f..bbeca66 100644
# ' xemacs syntax hack
-@@ -956,6 +1048,12 @@ def readMainConfig(startupconf):
+@@ -956,6 +1059,12 @@ def readMainConfig(startupconf):
return yumconf
def readVersionGroupsConfig(configfile="/etc/yum/version-groups.conf"):
@@ -6047,7 +8048,7 @@ index d09511f..bbeca66 100644
parser = ConfigParser()
confpp_obj = ConfigPreProcessor(configfile)
try:
-@@ -970,17 +1068,16 @@ def readVersionGroupsConfig(configfile="/etc/yum/version-groups.conf"):
+@@ -970,17 +1079,16 @@ def readVersionGroupsConfig(configfile="/etc/yum/version-groups.conf"):
def getOption(conf, section, name, option):
@@ -6075,7 +8076,7 @@ index d09511f..bbeca66 100644
try:
val = conf.get(section, name)
except (NoSectionError, NoOptionError):
-@@ -1028,7 +1125,10 @@ def _getsysver(installroot, distroverpkg):
+@@ -1028,7 +1136,10 @@ def _getsysver(installroot, distroverpkg):
if idx.count() == 0:
releasever = '$releasever'
else:
@@ -6087,7 +8088,7 @@ index d09511f..bbeca66 100644
releasever = hdr['version']
del hdr
del idx
-@@ -1036,13 +1136,12 @@ def _getsysver(installroot, distroverpkg):
+@@ -1036,13 +1147,12 @@ def _getsysver(installroot, distroverpkg):
return releasever
def writeRawRepoFile(repo,only=None):
@@ -6106,7 +8107,7 @@ index d09511f..bbeca66 100644
if not _use_iniparse:
return
-@@ -1069,7 +1168,7 @@ def writeRawRepoFile(repo,only=None):
+@@ -1069,7 +1179,7 @@ def writeRawRepoFile(repo,only=None):
# 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
@@ -6463,7 +8464,7 @@ index bca9651..00c17ad 100644
index = self.failures
else:
diff --git a/yum/history.py b/yum/history.py
-index 5385bd1..c91c33a 100644
+index 5385bd1..a9b12cf 100644
--- a/yum/history.py
+++ b/yum/history.py
@@ -97,9 +97,58 @@ def _setupHistorySearchSQL(patterns=None, ignore_case=False):
@@ -6725,7 +8726,7 @@ index 5385bd1..c91c33a 100644
obj.main = row[6] == 'TRUE'
ret.append(obj)
return ret
-@@ -1151,6 +1262,123 @@ class YumHistory:
+@@ -1151,6 +1262,127 @@ class YumHistory:
assert len(ret) == 1
return ret[0]
@@ -6762,7 +8763,7 @@ index 5385bd1..c91c33a 100644
+
+ sql = """INSERT INTO pkg_%(db)sdb (pkgtupid, %(db)sdb_key, %(db)sdb_val)
+ VALUES (?, ?, ?)""" % {'db' : db}
-+ executeSQL(cur, sql, (pid, attr, val))
++ executeSQL(cur, sql, (pid, attr, to_unicode(val)))
+ for row in cur:
+ return row[0]
+
@@ -6780,7 +8781,9 @@ index 5385bd1..c91c33a 100644
+ val = getattr(ipkg, attr, None)
+ if val is None:
+ continue
-+ self._save_anydb_key(ipkg, "rpm", attr, val)
++ if not self._save_anydb_key(ipkg, "rpm", attr, val):
++ return False
++ return True
+
+ def _save_yumdb(self, ipkg):
+ """ Save all the data for yumdb for this installed pkg, assumes
@@ -6789,7 +8792,9 @@ index 5385bd1..c91c33a 100644
+ val = ipkg.yumdb_info.get(attr)
+ if val is None:
+ continue
-+ self._save_anydb_key(ipkg, "yum", attr, val)
++ if not self._save_anydb_key(ipkg, "yum", attr, val):
++ return False
++ return True
+
+ def _wipe_anydb(self, pkg, db):
+ """ Delete all the data for rpmdb/yumdb for this installed pkg. """
@@ -6849,7 +8854,7 @@ index 5385bd1..c91c33a 100644
def _yieldSQLDataList(self, patterns, fields, ignore_case):
"""Yields all the package data for the given params. """
-@@ -1220,6 +1448,47 @@ class YumHistory:
+@@ -1220,6 +1452,47 @@ class YumHistory:
tids.add(row[0])
return tids
@@ -6897,7 +8902,7 @@ index 5385bd1..c91c33a 100644
_update_ops_2 = ['''\
\
CREATE TABLE trans_skip_pkgs (
-@@ -1374,6 +1643,8 @@ class YumHistory:
+@@ -1374,6 +1647,8 @@ class YumHistory:
cur.execute(op)
for op in self._update_ops_2:
cur.execute(op)
@@ -6906,6 +8911,45 @@ index 5385bd1..c91c33a 100644
self._commit()
# Pasted from sqlitesack
+diff --git a/yum/i18n.py b/yum/i18n.py
+index 9889bf6..85ad15e 100755
+--- a/yum/i18n.py
++++ b/yum/i18n.py
+@@ -462,6 +462,34 @@ def str_eq(a, b):
+
+ return False
+
++def exception2msg(e):
++ """Convert an exception to a message. This function will convert
++ the exception using to_unicode, unicode, or str, whichever works correctly.
++
++ :param e: an exception
++ :return: a string representation of the exception
++ """
++
++ # DIE python DIE! Which one works:
++ # to_unicode(e.value); unicode(e); str(e);
++ # Call this so you don't have to care.
++ try:
++ return to_unicode(e.value)
++ except:
++ pass
++
++ try:
++ return unicode(e)
++ except:
++ pass
++
++ try:
++ return str(e)
++ except:
++ pass
++ return "<exception failed to convert to text>"
++
++
+ try:
+ '''
+ Setup the yum translation domain and make _() and P_() translation wrappers
diff --git a/yum/misc.py b/yum/misc.py
index 2f6ddfe..37c572b 100644
--- a/yum/misc.py
@@ -7023,8 +9067,518 @@ index 5ef9951..f72c068 100644
self.__mode_cache = {}
self.__prcoPopulated = False
+diff --git a/yum/plugins.py b/yum/plugins.py
+index bfc49b7..9ddcae6 100644
+--- a/yum/plugins.py
++++ b/yum/plugins.py
+@@ -66,9 +66,9 @@ from yum.i18n import utf8_width
+ API_VERSION = '2.6'
+
+ class DeprecatedInt(int):
+- '''
+- A simple int subclass that used to check when a deprecated constant is used.
+- '''
++ """A simple int subclass that is used to check when a deprecated
++ constant is used.
++ """
+
+ # Plugin types
+ TYPE_CORE = 0
+@@ -105,8 +105,8 @@ SLOT_TO_CONDUIT = {
+ SLOTS = sorted(SLOT_TO_CONDUIT.keys())
+
+ class PluginYumExit(Exception):
+- '''Used by plugins to signal that yum should stop
+- '''
++ """Exception that can be raised by plugins to signal that yum should stop."""
++
+ def __init__(self, value="", translation_domain=""):
+ self.value = value
+ self.translation_domain = translation_domain
+@@ -117,9 +117,7 @@ class PluginYumExit(Exception):
+ return self.value
+
+ class YumPlugins:
+- '''
+- Manager class for Yum plugins.
+- '''
++ """Manager class for Yum plugins."""
+
+ def __init__(self, base, searchpath, optparser=None, types=None,
+ pluginconfpath=None,disabled=None,enabled=None):
+@@ -167,8 +165,13 @@ class YumPlugins:
+ self.run('config')
+
+ def run(self, slotname, **kwargs):
+- '''Run all plugin functions for the given slot.
+- '''
++ """Run all plugin functions for the given slot.
++
++ :param slotname: a string representing the name of the slot to
++ run the plugins for
++ :param kwargs: keyword arguments that will be simply passed on
++ to the plugins
++ """
+ # Determine handler class to use
+ conduitcls = SLOT_TO_CONDUIT.get(slotname, None)
+ if conduitcls is None:
+@@ -356,23 +359,35 @@ class YumPlugins:
+ return parser
+
+ def setCmdLine(self, opts, commands):
+- '''Set the parsed command line options so that plugins can access them
+- '''
++ """Set the parsed command line options so that plugins can
++ access them.
++
++ :param opts: a dictionary containing the values of the command
++ line options
++ :param commands: a list of command line arguments passed to yum
++ """
+ self.cmdline = (opts, commands)
+
+
+ class DummyYumPlugins:
+- '''
+- This class provides basic emulation of the YumPlugins class. It exists so
+- that calls to plugins.run() don't fail if plugins aren't in use.
+- '''
++ """This class provides basic emulation of the :class:`YumPlugins`
++ class. It exists so that calls to plugins.run() don't fail if
++ plugins aren't in use.
++ """
+ def run(self, *args, **kwargs):
++ """Do nothing. All arguments are unused."""
++
+ pass
+
+ def setCmdLine(self, *args, **kwargs):
++ """Do nothing. All arguments are unused."""
++
+ pass
+
+ class PluginConduit:
++ """A conduit class to transfer information between yum and the
++ plugin.
++ """
+ def __init__(self, parent, base, conf):
+ self._parent = parent
+ self._base = base
+@@ -382,14 +397,30 @@ class PluginConduit:
+ self.verbose_logger = logging.getLogger("yum.verbose.plugin")
+
+ def info(self, level, msg):
++ """Send an info message to the logger.
++
++ :param level: the level of the message to send
++ :param msg: the message to send
++ """
+ converted_level = logginglevels.logLevelFromDebugLevel(level)
+ self.verbose_logger.log(converted_level, msg)
+
+ def error(self, level, msg):
++ """Send an error message to the logger.
++
++ :param level: the level of the message to send
++ :param msg: the message to send
++ """
+ converted_level = logginglevels.logLevelFromErrorLevel(level)
+ self.logger.log(converted_level, msg)
+
+ def promptYN(self, msg):
++ """Return a yes or no response, either from assumeyes already
++ being set, or from prompting the user.
++
++ :param msg: the message to prompt the user with
++ :return: 1 if the response is yes, and 0 if the response is no
++ """
+ self.info(2, msg)
+ if self._base.conf.assumeyes:
+ return 1
+@@ -397,88 +428,96 @@ class PluginConduit:
+ return self._base.userconfirm()
+
+ def getYumVersion(self):
++ """Return a string representing the current version of yum."""
++
+ import yum
+ return yum.__version__
+
+ def getOptParser(self):
+- '''Return the optparse.OptionParser instance for this execution of Yum
+-
+- In the "config" and "init" slots a plugin may add extra options to this
+- instance to extend the command line options that Yum exposes.
+-
+- In all other slots a plugin may only read the OptionParser instance.
+- Any modification of the instance at this point will have no effect.
+-
+- See the getCmdLine() method for details on how to retrieve the parsed
+- values of command line options.
+-
+- @return: the global optparse.OptionParser instance used by Yum. May be
+- None if an OptionParser isn't in use.
+- '''
++ """Return the :class:`optparse.OptionParser` instance for this
++ execution of Yum. In the "config" and "init" slots a plugin
++ may add extra options to this instance to extend the command
++ line options that Yum exposes. In all other slots a plugin
++ may only read the :class:`OptionParser` instance. Any
++ modification of the instance at this point will have no
++ effect. See the
++ :func:`PreRepoSetupPluginConduit.getCmdLine` method for
++ details on how to retrieve the parsed values of command line
++ options.
++
++ :return: the global :class:`optparse.OptionParser` instance used by
++ Yum. May be None if an OptionParser isn't in use
++ """
+ # ' xemacs highlighting hack
+ # This isn't API compatible :(
+ # return self._parent.optparser.plugin_option_group
+ return self._parent.optparser
+
+ def confString(self, section, opt, default=None):
+- '''Read a string value from the plugin's own configuration file
++ """Read a string value from the plugin's own configuration file.
+
+- @param section: Configuration file section to read.
+- @param opt: Option name to read.
+- @param default: Value to read if option is missing.
+- @return: String option value read, or default if option was missing.
+- '''
++ :param section: configuration file section to read
++ :param opt: option name to read
++ :param default: value to read if the option is missing
++ :return: string option value read, or default if option was missing
++ """
+ # ' xemacs highlighting hack
+ return config.getOption(self._conf, section, opt, config.Option(default))
+
+ def confInt(self, section, opt, default=None):
+- '''Read an integer value from the plugin's own configuration file
++ """Read an integer value from the plugin's own configuration file.
+
+- @param section: Configuration file section to read.
+- @param opt: Option name to read.
+- @param default: Value to read if option is missing.
+- @return: Integer option value read, or default if option was missing or
+- could not be parsed.
+- '''
++ :param section: configuration file section to read
++ :param opt: option name to read
++ :param default: value to read if the option is missing
++
++ :return: the integer option value read, or *default* if the
++ option was missing or could not be parsed
++ """
+ return config.getOption(self._conf, section, opt, config.IntOption(default))
+
+ def confFloat(self, section, opt, default=None):
+- '''Read a float value from the plugin's own configuration file
+-
+- @param section: Configuration file section to read.
+- @param opt: Option name to read.
+- @param default: Value to read if option is missing.
+- @return: Float option value read, or default if option was missing or
+- could not be parsed.
+- '''
++ """Read a float value from the plugin's own configuration file.
++
++ :param section: configuration file section to read
++ :param opt: option name to read
++ :param default: value to read if the option is missing
++ :return: float option value read, or *default* if the option was
++ missing or could not be parsed
++ """
+ return config.getOption(self._conf, section, opt, config.FloatOption(default))
+
+ def confBool(self, section, opt, default=None):
+- '''Read a boolean value from the plugin's own configuration file
+-
+- @param section: Configuration file section to read.
+- @param opt: Option name to read.
+- @param default: Value to read if option is missing.
+- @return: Boolean option value read, or default if option was missing or
+- could not be parsed.
+- '''
++ """Read a boolean value from the plugin's own configuration file
++
++ :param section: configuration file section to read
++ :param opt: option name to read
++ :param default: value to read if the option is missing
++ :return: boolean option value read, or *default* if the option
++ was missing or could not be parsed
++ """
+ return config.getOption(self._conf, section, opt, config.BoolOption(default))
+
+ def registerPackageName(self, name):
++ """Register the name of a package to use.
++
++ :param name: the name of the package to register
++ """
+ self._base.run_with_package_names.add(name)
+
+
+ class ConfigPluginConduit(PluginConduit):
++ """A conduit for use in the config slot."""
+
+ def registerOpt(self, name, valuetype, where, default):
+- '''Register a yum configuration file option.
+-
+- @param name: Name of the new option.
+- @param valuetype: Option type (PLUG_OPT_BOOL, PLUG_OPT_STRING ...)
+- @param where: Where the option should be available in the config file.
+- (PLUG_OPT_WHERE_MAIN, PLUG_OPT_WHERE_REPO, ...)
+- @param default: Default value for the option if not set by the user.
+- '''
++ """Deprecated. Register a yum configuration file option.
++
++ :param name: name of the new option
++ :param valuetype: option type (PLUG_OPT_BOOL, PLUG_OPT_STRING, etc.)
++ :param where: where the option should be available in the config file
++ (PLUG_OPT_WHERE_MAIN, PLUG_OPT_WHERE_REPO, etc)
++ :param default: default value for the option if it is not set by the user
++ """
+ warnings.warn('registerOpt() will go away in a future version of Yum.\n'
+ 'Please manipulate config.YumConf and config.RepoConf directly.',
+ DeprecationWarning)
+@@ -502,64 +541,93 @@ class ConfigPluginConduit(PluginConduit):
+ setattr(config.RepoConf, name, config.Inherit(option))
+
+ def registerCommand(self, command):
++ """Register a new command.
++
++ :param command: the command to register
++ :raises: :class:`yum.Errors.ConfigError` if the registration
++ of commands is not supported
++ """
+ if hasattr(self._base, 'registerCommand'):
+ self._base.registerCommand(command)
+ else:
+ raise Errors.ConfigError(_('registration of commands not supported'))
+
+ class PostConfigPluginConduit(ConfigPluginConduit):
++ """Conduit for use in the postconfig slot."""
+
+ def getConf(self):
++ """Return a dictionary containing the values of the
++ configuration options.
++
++ :return: a dictionary containing the values of the
++ configuration options
++ """
+ return self._base.conf
+
+ class InitPluginConduit(PluginConduit):
++ """Conduit for use in the init slot."""
+
+ def getConf(self):
++ """Return a dictionary containing the values of the
++ configuration options.
++
++ :return: a dictionary containing the values of the
++ configuration options
++ """
+ return self._base.conf
+
+ def getRepos(self):
+- '''Return Yum's container object for all configured repositories.
++ """Return Yum's container object for all configured repositories.
+
+- @return: Yum's RepoStorage instance
+- '''
++ :return: Yum's :class:`yum.repos.RepoStorage` instance
++ """
+ return self._base.repos
+
+ class ArgsPluginConduit(InitPluginConduit):
++ """Conduit for dealing with command line arguments."""
+
+ def __init__(self, parent, base, conf, args):
+ InitPluginConduit.__init__(self, parent, base, conf)
+ self._args = args
+
+ def getArgs(self):
++ """Return a list of the command line arguments passed to yum.
++
++ :return: a list of the command line arguments passed to yum
++ """
+ return self._args
+
+ class PreRepoSetupPluginConduit(InitPluginConduit):
++ """Conduit for use in the prererosetup slot."""
++
+
+ def getCmdLine(self):
+- '''Return parsed command line options.
++ """Return parsed command line options.
+
+- @return: (options, commands) as returned by OptionParser.parse_args()
+- '''
++ :return: (options, commands) as returned by :class:`OptionParser.parse_args()`
++ """
+ return self._parent.cmdline
+
+ def getRpmDB(self):
+- '''Return a representation of local RPM database. This allows querying
+- of installed packages.
++ """Return a representation of the local RPM database. This
++ allows querying of installed packages.
+
+- @return: rpmUtils.RpmDBHolder instance
+- '''
++ :return: a :class:`yum.rpmUtils.RpmDBHolder` instance
++ """
+ return self._base.rpmdb
+
+ class PostRepoSetupPluginConduit(PreRepoSetupPluginConduit):
++ """Conduit for use in the postreposetup slot."""
+
+ def getGroups(self):
+- '''Return group information.
++ """Return group information.
+
+- @return: yum.comps.Comps instance
+- '''
++ :return: :class:`yum.comps.Comps` instance
++ """
+ return self._base.comps
+
+ class DownloadPluginConduit(PostRepoSetupPluginConduit):
++ """Conduit for use in the download slots."""
+
+ def __init__(self, parent, base, conf, pkglist, errors=None):
+ PostRepoSetupPluginConduit.__init__(self, parent, base, conf)
+@@ -567,24 +635,35 @@ class DownloadPluginConduit(PostRepoSetupPluginConduit):
+ self._errors = errors
+
+ def getDownloadPackages(self):
+- '''Return a list of package objects representing packages to be
++ """Return a list of package objects representing packages to be
+ downloaded.
+- '''
++
++ :return: a list of package object representing packages to be
++ downloaded
++ """
+ return self._pkglist
+
+ def getErrors(self):
+- '''Return a dictionary of download errors.
++ """Return a dictionary of download errors.
+
+- The returned dictionary is indexed by package object. Each element is a
+- list of strings describing the error.
+- '''
++ :return: a dictionary of download errors. This dictionary is
++ indexed by package object. Each element is a list of
++ strings describing the error
++ """
+ if not self._errors:
+ return {}
+ return self._errors
+
+ class MainPluginConduit(PostRepoSetupPluginConduit):
+-
++ """Main conduit class for plugins. Many other conduit classes
++ will inherit from this class.
++ """
+ def getPackages(self, repo=None):
++ """Return a list of packages.
++
++ :param repo: the repo to return a packages from
++ :return: a list of package objects
++ """
+ if repo:
+ arg = repo.id
+ else:
+@@ -592,50 +671,76 @@ class MainPluginConduit(PostRepoSetupPluginConduit):
+ return self._base.pkgSack.returnPackages(arg)
+
+ def getPackageByNevra(self, nevra):
+- '''Retrieve a package object from the packages loaded by Yum using
+- nevra information
++ """Retrieve a package object from the packages loaded by Yum using
++ nevra information.
+
+- @param nevra: A tuple holding (name, epoch, version, release, arch)
++ :param nevra: a tuple holding (name, epoch, version, release, arch)
+ for a package
+- @return: A PackageObject instance (or subclass)
+- '''
++ :return: a :class:`yum.packages.PackageObject` instance (or subclass)
++ """
+ return self._base.getPackageObject(nevra)
+
+ def delPackage(self, po):
++ """Delete the given package from the package sack.
++
++ :param po: the package object to delete
++ """
+ po.repo.sack.delPackage(po)
+
+ def getTsInfo(self):
++ """Return transaction set.
++
++ :return: the transaction set
++ """
+ return self._base.tsInfo
+
+ class DepsolvePluginConduit(MainPluginConduit):
++ """Conduit for use in solving dependencies."""
++
+ def __init__(self, parent, base, conf, rescode=None, restring=[]):
+ MainPluginConduit.__init__(self, parent, base, conf)
+ self.resultcode = rescode
+ self.resultstring = restring
+
+ class CompareProvidersPluginConduit(MainPluginConduit):
++ """Conduit to compare different providers of packages."""
++
+ def __init__(self, parent, base, conf, providers_dict={}, reqpo=None):
+ MainPluginConduit.__init__(self, parent, base, conf)
+ self.packages = providers_dict
+ self.reqpo = reqpo
+
+ class HistoryPluginConduit(MainPluginConduit):
++ """Conduit to access information about the yum history."""
++
+ def __init__(self, parent, base, conf, rescode=None, restring=[]):
+ MainPluginConduit.__init__(self, parent, base, conf)
+ self.history = self._base.history
+
+ class VerifyPluginConduit(MainPluginConduit):
++ """Conduit to verify packages."""
++
+ def __init__(self, parent, base, conf, verify_package):
+ MainPluginConduit.__init__(self, parent, base, conf)
+ self.verify_package = verify_package
+
+ def parsever(apiver):
++ """Parse a string representing an api version.
++
++ :param apiver: a string representing an api version
++ :return: a tuple containing the major and minor version numbers
++ """
+ maj, min = apiver.split('.')
+ return int(maj), int(min)
+
+ def apiverok(a, b):
+- '''Return true if API version "a" supports API version "b"
+- '''
++ """Return true if API version "a" supports API version "b"
++
++ :param a: a string representing an api version
++ :param b: a string representing an api version
++
++ :return: whether version *a* supports version *b*
++ """
+ a = parsever(a)
+ b = parsever(b)
+
diff --git a/yum/rpmsack.py b/yum/rpmsack.py
-index e289a7a..ef6fbd5 100644
+index e289a7a..635f03f 100644
--- a/yum/rpmsack.py
+++ b/yum/rpmsack.py
@@ -48,6 +48,17 @@ def _open_no_umask(*args):
@@ -7074,15 +9628,21 @@ index e289a7a..ef6fbd5 100644
except (IOError, OSError), e:
return
-@@ -1562,7 +1575,7 @@ class RPMDBAdditionalData(object):
+@@ -1562,11 +1575,11 @@ class RPMDBAdditionalData(object):
self._packages = {} # pkgid = dir
if not os.path.exists(self.conf.db_path):
try:
- os.makedirs(self.conf.db_path)
+ _makedirs_no_umask(self.conf.db_path)
++ self.conf.writable = True
except (IOError, OSError), e:
# some sort of useful thing here? A warning?
- return
+- return
+- self.conf.writable = True
++ pass
+ else:
+ if os.access(self.conf.db_path, os.W_OK):
+ self.conf.writable = True
@@ -1708,7 +1721,7 @@ class RPMDBAdditionalDataPackage(object):
def _write(self, attr, value):
# check for self._conf.writable before going on?
@@ -7114,8 +9674,71 @@ index 8a6f6f3..19193ad 100644
pre = "1"
prco_set = (_share_data(ob['name']), _share_data(ob['flags']),
(_share_data(ob['epoch']),
+diff --git a/yum/yumRepo.py b/yum/yumRepo.py
+index e5e9ece..91b7dde 100644
+--- a/yum/yumRepo.py
++++ b/yum/yumRepo.py
+@@ -24,6 +24,7 @@ urlparse.uses_fragment.append("media")
+ import Errors
+ from urlgrabber.grabber import URLGrabber
+ from urlgrabber.grabber import default_grabber
++from urlgrabber.progress import format_number
+ import urlgrabber.mirror
+ from urlgrabber.grabber import URLGrabError
+ import repoMDObject
+@@ -35,6 +36,7 @@ import sqlitesack
+ from yum import config
+ from yum import misc
+ from yum import comps
++from yum import _
+ from constants import *
+ import metalink
+
+@@ -499,6 +501,7 @@ class YumRepository(Repository, config.RepoConf):
+ 'throttle': self.throttle,
+ 'proxies': self.proxy_dict,
+ 'timeout': self.timeout,
++ 'ip_resolve': self.ip_resolve,
+ 'http_headers': tuple(self.__headersListFromDict(cache=cache)),
+ 'ssl_verify_peer': self.sslverify,
+ 'ssl_verify_host': self.sslverify,
+@@ -796,6 +799,16 @@ class YumRepository(Repository, config.RepoConf):
+ except Errors.MediaError, e:
+ verbose_logger.log(logginglevels.DEBUG_2, "Error getting package from media; falling back to url %s" %(e,))
+
++ if size:
++ dirstat = os.statvfs(os.path.dirname(local))
++ avail = dirstat.f_bavail * dirstat.f_bsize
++ if avail < long(size):
++ raise Errors.RepoError, _('''\
++Insufficient space in download directory %s
++ * free %s
++ * needed %s'''
++ ) % (os.path.dirname(local), format_number(avail), format_number(long(size)))
++
+ if url and scheme != "media":
+ ugopts = self._default_grabopts(cache=cache)
+ ug = URLGrabber(progress_obj = self.callback,
+@@ -1020,7 +1033,7 @@ class YumRepository(Repository, config.RepoConf):
+ if grab_can_fail:
+ return None
+ raise Errors.RepoError, 'Error downloading file %s: %s' % (local, e)
+- except (Errors.NoMoreMirrorsRepoError, Errors.RepoError):
++ except Errors.RepoError:
+ misc.unlink_f(tfname)
+ if grab_can_fail:
+ return None
+@@ -1614,7 +1627,7 @@ class YumRepository(Repository, config.RepoConf):
+ text=text,
+ cache=self.http_caching == 'all',
+ size=thisdata.size)
+- except (Errors.NoMoreMirrorsRepoError, Errors.RepoError):
++ except Errors.RepoError:
+ if retrieve_can_fail:
+ return None
+ raise
diff --git a/yumcommands.py b/yumcommands.py
-index 4dcbea7..d9c70f3 100644
+index 4dcbea7..2ab9a28 100644
--- a/yumcommands.py
+++ b/yumcommands.py
@@ -43,16 +43,22 @@ def _err_mini_usage(base, basecmd):
@@ -8779,7 +11402,7 @@ index 4dcbea7..d9c70f3 100644
return _("Display, or use, the transaction history")
def _hcmd_redo(self, base, extcmds):
-@@ -1426,12 +2425,52 @@ class HistoryCommand(YumCommand):
+@@ -1426,12 +2425,54 @@ class HistoryCommand(YumCommand):
def _hcmd_new(self, base, extcmds):
base.history._create_db_file()
@@ -8810,8 +11433,10 @@ index 4dcbea7..d9c70f3 100644
+ continue
+
+ print "Syncing rpm/yum DB data for:", ipkg, "...",
-+ base.history.sync_alldb(ipkg)
-+ print "Done."
++ if base.history.sync_alldb(ipkg):
++ print "Done."
++ else:
++ print "FAILED."
+
def doCheck(self, base, basecmd, extcmds):
+ """Verify that conditions are met so that this command can
@@ -8833,7 +11458,7 @@ index 4dcbea7..d9c70f3 100644
if extcmds and extcmds[0] not in cmds:
base.logger.critical(_('Invalid history sub-command, use: %s.'),
", ".join(cmds))
-@@ -1444,6 +2483,19 @@ class HistoryCommand(YumCommand):
+@@ -1444,6 +2485,19 @@ class HistoryCommand(YumCommand):
raise cli.CliError
def doCommand(self, base, basecmd, extcmds):
@@ -8853,7 +11478,7 @@ index 4dcbea7..d9c70f3 100644
vcmd = 'list'
if extcmds:
vcmd = extcmds[0]
-@@ -1468,12 +2520,26 @@ class HistoryCommand(YumCommand):
+@@ -1468,12 +2522,26 @@ class HistoryCommand(YumCommand):
ret = self._hcmd_rollback(base, extcmds)
elif vcmd == 'new':
ret = self._hcmd_new(base, extcmds)
@@ -8880,7 +11505,7 @@ index 4dcbea7..d9c70f3 100644
vcmd = 'list'
if extcmds:
vcmd = extcmds[0]
-@@ -1481,16 +2547,46 @@ class HistoryCommand(YumCommand):
+@@ -1481,16 +2549,46 @@ class HistoryCommand(YumCommand):
class CheckRpmdbCommand(YumCommand):
@@ -8927,7 +11552,7 @@ index 4dcbea7..d9c70f3 100644
chkcmd = 'all'
if extcmds:
chkcmd = extcmds
-@@ -1505,19 +2601,57 @@ class CheckRpmdbCommand(YumCommand):
+@@ -1505,19 +2603,57 @@ class CheckRpmdbCommand(YumCommand):
return rc, ['%s %s' % (basecmd, chkcmd)]
def needTs(self, base, basecmd, extcmds):
@@ -8985,7 +11610,7 @@ index 4dcbea7..d9c70f3 100644
if not extcmds:
base.logger.critical(_("No saved transaction file specified."))
raise cli.CliError
-@@ -1533,5 +2667,13 @@ class LoadTransactionCommand(YumCommand):
+@@ -1533,5 +2669,13 @@ class LoadTransactionCommand(YumCommand):
def needTs(self, base, basecmd, extcmds):
@@ -9000,11 +11625,19 @@ index 4dcbea7..d9c70f3 100644
return True
diff --git a/yummain.py b/yummain.py
-index 9f79f4f..d6abd70 100755
+index 9f79f4f..4b1112a 100755
--- a/yummain.py
+++ b/yummain.py
-@@ -35,7 +35,7 @@ import cli
- from utils import suppress_keyboard_interrupt_message, show_lock_owner, exception2msg
+@@ -29,13 +29,13 @@ from yum import Errors
+ from yum import plugins
+ from yum import logginglevels
+ from yum import _
+-from yum.i18n import to_unicode, utf8_width
++from yum.i18n import to_unicode, utf8_width, exception2msg
+ import yum.misc
+ import cli
+-from utils import suppress_keyboard_interrupt_message, show_lock_owner, exception2msg
++from utils import suppress_keyboard_interrupt_message, show_lock_owner
def main(args):
- """This does all the real work"""
@@ -9012,6 +11645,28 @@ index 9f79f4f..d6abd70 100755
yum.misc.setup_locale(override_time=True)
+@@ -120,16 +120,16 @@ def main(args):
+ if exception2msg(e) != lockerr:
+ lockerr = exception2msg(e)
+ logger.critical(lockerr)
+- if (e.errno not in (errno.EPERM, errno.EACCES) and
+- not base.conf.exit_on_lock):
++ if e.errno in (errno.EPERM, errno.EACCES, errno.ENOSPC):
++ logger.critical(_("Can't create lock file; exiting"))
++ return 1
++
++ if 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
@@ -238,9 +238,15 @@ def main(args):
rpmdb_warn_checks()
return_code = result
diff --git a/yum.spec b/yum.spec
index 324a0c5..f7bc652 100644
--- a/yum.spec
+++ b/yum.spec
@@ -1,6 +1,7 @@
%define move_yum_conf_back 1
%define auto_sitelib 1
%define yum_updatesd 0
+%define disable_check 1
%if %{auto_sitelib}
@@ -17,7 +18,7 @@
Summary: RPM package installer/updater/manager
Name: yum
Version: 3.4.3
-Release: 6%{?dist}
+Release: 7%{?dist}
License: GPLv2+
Group: System Environment/Base
Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz
@@ -146,6 +147,11 @@ Install this package if you want auto yum updates nightly via cron.
%build
make
+%if !%{disable_check}
+%check
+make check
+%endif
+
%install
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
@@ -267,7 +273,7 @@ exit 0
%{_sysconfdir}/bash_completion.d
%dir %{_datadir}/yum-cli
%{_datadir}/yum-cli/*
-%if !%{yum_updatesd}
+%if %{yum_updatesd}
%exclude %{_datadir}/yum-cli/yumupd.py*
%endif
%{_bindir}/yum
@@ -310,6 +316,13 @@ exit 0
%endif
%changelog
+* Fri Aug 19 2011 James Antill <james at fedoraproject.org> - 3.4.3-7
+- update to latest HEAD
+- Fix syncing of yum DB data in history.
+- Add upgrade_requirements_on_install config. option.
+- Don't look for releasever if it's set directly (anaconda).
+- Expose ip_resolve urlgrabber option.
+
* Fri Aug 5 2011 James Antill <james at fedoraproject.org> - 3.4.3-6
- update to latest HEAD
- Add new yum DB data.
More information about the scm-commits
mailing list