diff --git a/yum-HEAD.patch b/yum-HEAD.patch index 209b197..b9a2e3d 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -109,7 +109,7 @@ index 2f6154e..2e5a052 100644 diff --git a/cli.py b/cli.py old mode 100644 new mode 100755 -index 6056d38..b7f5b5a +index 6056d38..cefc67e --- a/cli.py +++ b/cli.py @@ -25,7 +25,7 @@ import sys @@ -416,7 +416,7 @@ index 6056d38..b7f5b5a yumshell = shell.YumShell(base=self) -@@ -382,8 +490,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -382,17 +490,22 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return yumshell.result, yumshell.resultmsgs def errorSummary(self, errstring): @@ -430,8 +430,23 @@ index 6056d38..b7f5b5a + """ summary = '' # do disk space report first - p = re.compile('needs (\d+)MB on the (\S+) filesystem') -@@ -407,17 +519,45 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +- p = re.compile('needs (\d+)MB on the (\S+) filesystem') ++ p = re.compile('needs (\d+)(K|M)B on the (\S+) filesystem') + disk = {} + for m in p.finditer(errstring): +- if m.group(2) not in disk: +- disk[m.group(2)] = int(m.group(1)) +- if disk[m.group(2)] < int(m.group(1)): +- disk[m.group(2)] = int(m.group(1)) ++ size_in_mb = int(m.group(1)) if m.group(2) == 'M' else round(int(m.group(1))/1024.0, 3) ++ if m.group(3) not in disk: ++ disk[m.group(3)] = size_in_mb ++ if disk[m.group(3)] < size_in_mb: ++ disk[m.group(3)] = size_in_mb + + if disk: + summary += _('Disk Requirements:\n') +@@ -407,17 +520,45 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return summary @@ -487,7 +502,7 @@ index 6056d38..b7f5b5a # at this point we know the args are valid - we don't know their meaning # but we know we're not being sent garbage -@@ -435,14 +575,40 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -435,14 +576,40 @@ class YumBaseCli(yum.YumBase, output.YumOutput): try: self._getTs(needTsRemove) except yum.Errors.YumBaseError, e: @@ -533,7 +548,7 @@ index 6056d38..b7f5b5a # 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 +619,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -453,7 +620,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) @@ -542,7 +557,7 @@ index 6056d38..b7f5b5a # If we are in quiet, and assumeyes isn't on we want to output # at least the transaction list anyway. self.logger.warn(lsts) -@@ -463,7 +629,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -463,7 +630,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput): rmpkgs = [] stuff_to_download = False install_only = True @@ -550,7 +565,7 @@ index 6056d38..b7f5b5a for txmbr in self.tsInfo.getMembers(): if txmbr.ts_state not in ('i', 'u'): install_only = False -@@ -471,7 +636,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -471,7 +637,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput): if po: rmpkgs.append(po) else: @@ -558,7 +573,7 @@ index 6056d38..b7f5b5a stuff_to_download = True po = txmbr.po if po: -@@ -489,19 +653,40 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -489,19 +654,40 @@ class YumBaseCli(yum.YumBase, output.YumOutput): else: self.reportDownloadSize(downloadpkgs, install_only) @@ -604,7 +619,7 @@ index 6056d38..b7f5b5a for key in problems: errors = yum.misc.unique(problems[key]) for error in errors: -@@ -520,8 +705,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -520,8 +706,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): rcd_st = time.time() self.verbose_logger.log(yum.logginglevels.INFO_2, @@ -615,7 +630,7 @@ index 6056d38..b7f5b5a if msgs: rpmlib_only = True for msg in msgs: -@@ -532,21 +718,23 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -532,21 +719,23 @@ class YumBaseCli(yum.YumBase, output.YumOutput): print _("ERROR You need to update rpm to handle:") else: print _('ERROR with transaction check vs depsolve:') @@ -644,7 +659,7 @@ index 6056d38..b7f5b5a self.ts.order() # order the transaction self.ts.clean() # release memory not needed beyond this point -@@ -556,16 +744,16 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -556,16 +745,16 @@ class YumBaseCli(yum.YumBase, output.YumOutput): del testcb if len(tserrors) > 0: @@ -664,7 +679,7 @@ index 6056d38..b7f5b5a # unset the sigquit handler signal.signal(signal.SIGQUIT, signal.SIG_DFL) -@@ -595,9 +783,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -595,9 +784,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): if self.conf.debuglevel < 2: cb.display.output = False @@ -690,7 +705,7 @@ index 6056d38..b7f5b5a self.verbose_logger.debug('Transaction time: %0.3f' % (time.time() - ts_st)) # close things self.verbose_logger.log(yum.logginglevels.INFO_1, -@@ -609,12 +812,14 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -609,12 +813,14 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return resultobject.return_code def gpgsigcheck(self, pkgs): @@ -710,7 +725,7 @@ index 6056d38..b7f5b5a for po in pkgs: result, errmsg = self.sigCheckPkg(po) -@@ -623,7 +828,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -623,7 +829,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): continue elif result == 1: @@ -720,7 +735,7 @@ index 6056d38..b7f5b5a raise yum.Errors.YumBaseError, \ _('Refusing to automatically import keys when running ' \ 'unattended.\nUse "-y" to override.') -@@ -691,12 +897,62 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -691,12 +898,62 @@ class YumBaseCli(yum.YumBase, output.YumOutput): ", ".join(matches)) self.verbose_logger.log(yum.logginglevels.INFO_2, msg) @@ -789,7 +804,7 @@ index 6056d38..b7f5b5a # get the list of available packages # iterate over the user's list # add packages to Transaction holding class if they match. -@@ -710,11 +966,38 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -710,11 +967,38 @@ 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))): @@ -830,7 +845,7 @@ index 6056d38..b7f5b5a except yum.Errors.InstallError: self.verbose_logger.log(yum.logginglevels.INFO_2, _('No package %s%s%s available.'), -@@ -723,6 +1006,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -723,6 +1007,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): self._maybeYouMeant(arg) else: done = True @@ -838,7 +853,7 @@ index 6056d38..b7f5b5a 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 +1016,27 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -732,9 +1017,27 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [_('Nothing to do')] def updatePkgs(self, userlist, quiet=0, update_to=False): @@ -869,7 +884,7 @@ index 6056d38..b7f5b5a # 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 -@@ -745,34 +1047,46 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -745,34 +1048,46 @@ class YumBaseCli(yum.YumBase, output.YumOutput): else: # go through the userlist - look for items that are local rpms. If we find them @@ -933,7 +948,7 @@ index 6056d38..b7f5b5a level = 'diff' if userlist and userlist[0] in ('full', 'diff', 'different'): -@@ -831,6 +1145,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -831,6 +1146,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): continue nayi = napkg.yumdb_info @@ -941,7 +956,7 @@ index 6056d38..b7f5b5a for apkg in self.pkgSack.searchPkgTuple(napkg.pkgtup): if ('checksum_type' in nayi and 'checksum_data' in nayi and -@@ -861,19 +1176,58 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -861,19 +1177,58 @@ class YumBaseCli(yum.YumBase, output.YumOutput): dupdates.extend(self.downgrade(name=n, epoch=e, ver=v, rel=r)) if dupdates: @@ -1008,7 +1023,7 @@ index 6056d38..b7f5b5a if not rms: self._checkMaybeYouMeant(arg, always_output=False, rpmdb_only=True) all_rms.extend(rms) -@@ -884,12 +1238,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -884,12 +1239,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [_('No Packages marked for removal')] def downgradePkgs(self, userlist): @@ -1036,7 +1051,7 @@ index 6056d38..b7f5b5a for arg in userlist: if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or os.path.exists(arg))): -@@ -905,26 +1271,44 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -905,26 +1272,44 @@ class YumBaseCli(yum.YumBase, output.YumOutput): self.term.MODE['bold'], arg, self.term.MODE['normal']) self._maybeYouMeant(arg) @@ -1085,7 +1100,7 @@ index 6056d38..b7f5b5a except yum.Errors.ReinstallRemoveError: self._checkMaybeYouMeant(arg, always_output=False) except yum.Errors.ReinstallInstallError, e: -@@ -940,22 +1324,38 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -940,22 +1325,38 @@ 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) @@ -1128,7 +1143,7 @@ index 6056d38..b7f5b5a installing = False for pkg in filelist: -@@ -971,23 +1371,29 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -971,23 +1372,29 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 2, [_('Package(s) to install')] return 0, [_('Nothing to do')] @@ -1174,7 +1189,7 @@ index 6056d38..b7f5b5a pkgnarrow = 'all' done_hidden_available = False -@@ -1003,7 +1409,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1003,7 +1410,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): pkgnarrow = extcmds.pop(0) ypl = self.doPackageLists(pkgnarrow=pkgnarrow, patterns=extcmds, @@ -1183,7 +1198,7 @@ index 6056d38..b7f5b5a if self.conf.showdupesfromrepos: ypl.available += ypl.reinstall_available -@@ -1017,8 +1423,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1017,8 +1424,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return ypl def search(self, args): @@ -1211,7 +1226,7 @@ index 6056d38..b7f5b5a # call the yum module search function with lists of tags to search # and what to search for -@@ -1053,7 +1476,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1053,7 +1477,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): print "" else: mkeys = set(keys) @@ -1220,7 +1235,7 @@ index 6056d38..b7f5b5a okeys = keys pos.add(po) akeys.update(keys) -@@ -1104,13 +1527,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1104,13 +1528,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): self.logger.warning(_('Warning: No matches found for: %s'), arg) if not akeys: @@ -1248,7 +1263,7 @@ index 6056d38..b7f5b5a pkgs = [] for arg in args: if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or -@@ -1118,10 +1552,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1118,10 +1553,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput): thispkg = yum.packages.YumUrlPackage(self, self.ts, arg) pkgs.append(thispkg) elif self.conf.showdupesfromrepos: @@ -1263,7 +1278,7 @@ index 6056d38..b7f5b5a except yum.Errors.PackageSackError: pass -@@ -1131,10 +1567,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1131,10 +1568,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [] def provides(self, args): @@ -1287,7 +1302,7 @@ index 6056d38..b7f5b5a old_sdup = self.conf.showdupesfromrepos # For output, as searchPackageProvides() is always in showdups mode self.conf.showdupesfromrepos = True -@@ -1147,6 +1592,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1147,6 +1593,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): paths = set(sys.path + os.environ['PATH'].split(':')) nargs = [] for arg in args: @@ -1296,7 +1311,7 @@ index 6056d38..b7f5b5a if yum.misc.re_filename(arg) or yum.misc.re_glob(arg): continue for path in paths: -@@ -1158,25 +1605,82 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1158,25 +1606,82 @@ class YumBaseCli(yum.YumBase, output.YumOutput): self.conf.showdupesfromrepos = old_sdup if len(matching) == 0: @@ -1385,7 +1400,7 @@ index 6056d38..b7f5b5a hdrcode = pkgcode = xmlcode = dbcode = expccode = 0 pkgresults = hdrresults = xmlresults = dbresults = expcresults = [] msg = self.fmtKeyValFill(_('Cleaning repos: '), -@@ -1184,7 +1688,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1184,7 +1689,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): self.verbose_logger.log(yum.logginglevels.INFO_2, msg) if 'all' in userlist: self.verbose_logger.log(yum.logginglevels.INFO_2, @@ -1394,7 +1409,7 @@ index 6056d38..b7f5b5a pkgcode, pkgresults = self.cleanPackages() hdrcode, hdrresults = self.cleanHeaders() xmlcode, xmlresults = self.cleanMetadata() -@@ -1200,10 +1704,10 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1200,10 +1705,10 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return code, [] if 'headers' in userlist: @@ -1407,7 +1422,7 @@ index 6056d38..b7f5b5a pkgcode, pkgresults = self.cleanPackages() if 'metadata' in userlist: self.logger.debug(_('Cleaning up xml metadata')) -@@ -1228,159 +1732,345 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1228,159 +1733,345 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return code, [] def returnGroupLists(self, userlist): @@ -1844,7 +1859,7 @@ index 6056d38..b7f5b5a return 0, [_('No packages to remove from groups')] else: return 2, [P_('%d package to remove', '%d packages to remove', len(pkgs_used)) % len(pkgs_used)] -@@ -1389,7 +2079,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1389,7 +2080,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): def _promptWanted(self): # shortcut for the always-off/always-on options @@ -1853,7 +1868,7 @@ index 6056d38..b7f5b5a return False if self.conf.alwaysprompt: return True -@@ -1397,10 +2087,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1397,10 +2088,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): # prompt if: # package was added to fill a dependency # package is being removed @@ -1865,7 +1880,7 @@ index 6056d38..b7f5b5a txmbr.name not in self.extcmds: return True -@@ -1408,11 +2097,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1408,11 +2098,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return False def usage(self): @@ -1879,7 +1894,7 @@ index 6056d38..b7f5b5a sys.stdout.write(self.optparser.get_usage()) def _installable(self, pkg, ematch=False): -@@ -1468,9 +2157,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1468,9 +2158,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return False class YumOptionParser(OptionParser): @@ -1891,7 +1906,7 @@ index 6056d38..b7f5b5a def __init__(self,base, **kwargs): # check if this is called with a utils=True/False parameter -@@ -1488,13 +2177,23 @@ class YumOptionParser(OptionParser): +@@ -1488,13 +2178,23 @@ class YumOptionParser(OptionParser): self._addYumBasicOptions() def error(self, msg): @@ -1917,7 +1932,7 @@ index 6056d38..b7f5b5a try: args = _filtercmdline( ('--noplugins','--version','-q', '-v', "--quiet", "--verbose"), -@@ -1521,7 +2220,15 @@ class YumOptionParser(OptionParser): +@@ -1521,7 +2221,15 @@ class YumOptionParser(OptionParser): return ret def setupYumConfig(self, args=None): @@ -1934,7 +1949,7 @@ index 6056d38..b7f5b5a if not args: (opts, cmds) = self.parse_args() else: -@@ -1533,16 +2240,30 @@ class YumOptionParser(OptionParser): +@@ -1533,16 +2241,30 @@ class YumOptionParser(OptionParser): try: # config file is parsed and moving us forward # set some things in it. @@ -1971,7 +1986,7 @@ index 6056d38..b7f5b5a self.base.conf.cache = 1 if opts.obsoletes: -@@ -1574,11 +2295,8 @@ class YumOptionParser(OptionParser): +@@ -1574,13 +2296,11 @@ class YumOptionParser(OptionParser): if opts.color != 'auto': self.base.term.reinit(color=opts.color) @@ -1983,9 +1998,13 @@ index 6056d38..b7f5b5a + self.base.conf.disable_excludes = self._splitArg(opts.disableexcludes) + self.base.conf.disable_includes = self._splitArg(opts.disableincludes) - for exclude in self._splitArg(opts.exclude): +- for exclude in self._splitArg(opts.exclude): ++ self.base.cmdline_excludes = self._splitArg(opts.exclude) ++ for exclude in self.base.cmdline_excludes: try: -@@ -1610,10 +2328,6 @@ class YumOptionParser(OptionParser): + excludelist = self.base.conf.exclude + excludelist.append(exclude) +@@ -1610,10 +2330,6 @@ class YumOptionParser(OptionParser): self.base.usage() sys.exit(1) @@ -1996,7 +2015,7 @@ index 6056d38..b7f5b5a # Disable all gpg key checking, if requested. if opts.nogpgcheck: # Altering the normal configs. doesn't work too well, esp. with -@@ -1623,7 +2337,7 @@ class YumOptionParser(OptionParser): +@@ -1623,7 +2339,7 @@ class YumOptionParser(OptionParser): repo._override_sigchecks = True except ValueError, e: @@ -2005,7 +2024,7 @@ index 6056d38..b7f5b5a self.base.usage() sys.exit(1) -@@ -1640,10 +2354,18 @@ class YumOptionParser(OptionParser): +@@ -1640,10 +2356,18 @@ class YumOptionParser(OptionParser): sys.exit(1) def getRoot(self,opts): @@ -2025,7 +2044,7 @@ index 6056d38..b7f5b5a if os.access(opts.installroot+'/'+opts.conffile, os.R_OK): opts.conffile = opts.installroot+'/'+opts.conffile elif opts.conffile == '/etc/yum/yum.conf': -@@ -1701,6 +2423,9 @@ class YumOptionParser(OptionParser): +@@ -1701,6 +2425,9 @@ class YumOptionParser(OptionParser): group.add_option("--showduplicates", dest="showdupesfromrepos", action="store_true", help=_("show duplicates, in repos, in list/search commands")) @@ -2035,7 +2054,7 @@ index 6056d38..b7f5b5a group.add_option("-e", "--errorlevel", dest="errorlevel", default=None, help=_("error output level"), type='int', metavar='[error level]') -@@ -1713,6 +2438,10 @@ class YumOptionParser(OptionParser): +@@ -1713,6 +2440,10 @@ class YumOptionParser(OptionParser): help=_("verbose operation")) group.add_option("-y", "--assumeyes", dest="assumeyes", action="store_true", help=_("answer yes for all questions")) @@ -2046,7 +2065,7 @@ index 6056d38..b7f5b5a group.add_option("--version", action="store_true", help=_("show Yum version and exit")) group.add_option("--installroot", help=_("set install root"), -@@ -1730,6 +2459,9 @@ class YumOptionParser(OptionParser): +@@ -1730,6 +2461,9 @@ class YumOptionParser(OptionParser): group.add_option("", "--disableexcludes", default=[], action="append", help=_("disable exclude from main, for a repo or for everything"), metavar='[repo]') @@ -2056,7 +2075,7 @@ index 6056d38..b7f5b5a group.add_option("--obsoletes", action="store_true", help=_("enable obsoletes processing during updates")) group.add_option("--noplugins", action="store_true", -@@ -1748,9 +2480,29 @@ class YumOptionParser(OptionParser): +@@ -1748,9 +2482,29 @@ class YumOptionParser(OptionParser): help=_("control whether color is used")) group.add_option("", "--releasever", dest="releasever", default=None, help=_("set value of $releasever in yum config and repo files")) @@ -2853,7 +2872,7 @@ index 0000000..7ce1aef + the mailing list, yum@lists.baseurl.org, or consult bugzilla. +.fi diff --git a/docs/yum.8 b/docs/yum.8 -index 1a8202a..998a5ad 100644 +index 1a8202a..a0038f6 100644 --- a/docs/yum.8 +++ b/docs/yum.8 @@ -25,6 +25,8 @@ gnome\-packagekit application\&. @@ -3491,7 +3510,7 @@ index 1a8202a..998a5ad 100644 +.br + +.br -+Configuration Options: \fBfssnap_automatic_pre\fP, \fBfssnap_automatic_post\fP, \fBfssnap_automatic_keep\fP, \fBfssnap_percentage\fP, \fBfssnap_devices\fP ++Configuration Options: \fBfssnap_automatic_pre\fP, \fBfssnap_automatic_post\fP, \fBfssnap_automatic_keep\fP, \fBfssnap_percentage\fP, \fBfssnap_devices\fP, \fBfssnap_abort_on_errors\fP + +.IP +.IP "\fBfs\fP" @@ -3666,7 +3685,7 @@ index 1a8202a..998a5ad 100644 http://yum.baseurl.org/wiki/Faq yum search yum diff --git a/docs/yum.conf.5 b/docs/yum.conf.5 -index 515aa73..97acbe4 100644 +index 515aa73..5c349cb 100644 --- a/docs/yum.conf.5 +++ b/docs/yum.conf.5 @@ -64,7 +64,7 @@ options are: 'critical', 'emergency', 'error', 'warn' and 'debug'. @@ -3678,7 +3697,7 @@ index 515aa73..97acbe4 100644 The default is: yum glob:/etc/yum/protected.d/*.conf So any packages which should be protected can do so by including a file in -@@ -114,37 +114,49 @@ are causing problems from the transaction. +@@ -114,37 +114,59 @@ are causing problems from the transaction. Either `1' or `0'. Determines whether or not yum prompts for confirmation of critical actions. Default is `0' (do prompt). .br @@ -3733,17 +3752,26 @@ index 515aa73..97acbe4 100644 +can be used to remove packages in any way that "yum list" will show packages. Shell globs using wildcards (eg. * and ?) are allowed. --.IP ++Can be disabled using disable_excludes or --disableexcludes. ++Command-line option: \fB\-x\fP ++ + .IP -\fBexactarch\fR -Either `1' or `0'. Set to `1' to make yum update only update the architectures -of packages that you have installed. ie: with this enabled yum will not install -an i686 package to update an i386 package. Default is `1'. -+Can be disabled using --disableexcludes. -+Command-line option: \fB\-x\fP ++\fBdisable_excludes\fR ++A way to permanently set the --disableexcludes command line option. ++ ++.IP ++\fBquery_install_excludes\fR ++This applies the command line exclude option (only, not the configuration ++exclude above) to installed packages being shown in some query commands ++(currently: list/info/search/provides). .IP \fBinstallonlypkgs \fR -@@ -161,7 +173,7 @@ will also apply to kernel-debug-devel, etc. +@@ -161,7 +183,7 @@ will also apply to kernel-debug-devel, etc. Number of packages listed in installonlypkgs to keep installed at the same time. Setting to 0 disables this feature. Default is '0'. Note that this functionality used to be in the "installonlyn" plugin, where this option was @@ -3752,7 +3780,7 @@ index 515aa73..97acbe4 100644 Note that as of version 3.2.24, yum will now look in the yumdb for a installonly attribute on installed packages. If that attribute is "keep", then they will never be removed. -@@ -188,12 +200,32 @@ Default is `true'. +@@ -188,12 +210,32 @@ Default is `true'. Command-line option: \fB\-\-obsoletes\fP .IP @@ -3785,7 +3813,7 @@ index 515aa73..97acbe4 100644 .IP \fBgroupremove_leaf_only \fR -@@ -215,6 +247,43 @@ of packages in groups will be installed when 'groupinstall' is called. +@@ -215,6 +257,43 @@ of packages in groups will be installed when 'groupinstall' is called. Default is: default, mandatory .IP @@ -3794,7 +3822,7 @@ index 515aa73..97acbe4 100644 +group install/upgrade/remove commands. + +Simple acts like you did yum group cmd $(repoquery --group --list group), so -+it is vrery easy to reason about what will happen. Alas. this is often not what ++it is very easy to reason about what will happen. Alas. this is often not what +people want to happen. + +Compat. works much like simple, except that when you run "group upgrade" it @@ -3829,7 +3857,7 @@ index 515aa73..97acbe4 100644 \fBinstallroot \fR Specifies an alternative installroot, relative to which all packages will be installed. -@@ -222,15 +291,34 @@ installed. +@@ -222,15 +301,34 @@ installed. Command-line option: \fB\-\-installroot\fP .IP @@ -3868,7 +3896,7 @@ index 515aa73..97acbe4 100644 .IP \fBtsflags\fR -@@ -240,6 +328,14 @@ with newer rpm versions. +@@ -240,6 +338,14 @@ with newer rpm versions. You can set all/any of them. However, if you don't know what these do in the context of an rpm transaction set you're best leaving it alone. Default is an empty list. @@ -3883,7 +3911,7 @@ index 515aa73..97acbe4 100644 .IP \fBrecent\fR -@@ -291,6 +387,16 @@ the maximum available bandwidth. +@@ -291,6 +397,16 @@ the maximum available bandwidth. Set to `0' to disable bandwidth throttling. This is the default. @@ -3900,7 +3928,7 @@ index 515aa73..97acbe4 100644 .IP \fBbandwidth \fR Use to specify the maximum available network bandwidth in bytes/second. Used -@@ -300,6 +406,50 @@ with the \fBthrottle\fR option (above). If \fBthrottle\fR is a percentage and +@@ -300,6 +416,50 @@ with the \fBthrottle\fR option (above). If \fBthrottle\fR is a percentage and ignored. Default is `0' (no bandwidth throttling). .IP @@ -3951,7 +3979,7 @@ index 515aa73..97acbe4 100644 \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 -@@ -331,6 +481,15 @@ Path to the SSL client key yum should use to connect to repos/remote sites +@@ -331,6 +491,15 @@ Path to the SSL client key yum should use to connect to repos/remote sites Defaults to none. .IP @@ -3967,7 +3995,7 @@ index 515aa73..97acbe4 100644 \fBhistory_record \fR Boolean - should yum record history entries for transactions. This takes some disk space, and some extra time in the transactions. But it allows how to know a -@@ -391,7 +550,9 @@ syslog logging is disabled. Default is `/dev/log'. +@@ -391,7 +560,9 @@ syslog logging is disabled. Default is `/dev/log'. .IP \fBproxy \fR @@ -3978,7 +4006,7 @@ index 515aa73..97acbe4 100644 .IP \fBproxy_username \fR -@@ -438,6 +599,31 @@ It's also possible to use the word "never", meaning that the metadata will +@@ -438,6 +609,31 @@ It's also possible to use the word "never", meaning that the metadata will never expire. Note that when using a metalink file the metalink must always be newer than the metadata for the repository, due to the validation, so this timeout also applies to the metalink file. @@ -4010,7 +4038,7 @@ index 515aa73..97acbe4 100644 .IP \fBmirrorlist_expire \fR -@@ -462,12 +648,12 @@ always did, however it now does some checking on the index and reverts if +@@ -462,12 +658,12 @@ always did, however it now does some checking on the index and reverts if it classifies it as bad. `group:primary' - Download the primary metadata with the index. This contains @@ -4028,7 +4056,7 @@ index 515aa73..97acbe4 100644 `group:main' - With the primary and updateinfo download the filelists metadata and the group metadata. The filelists data is required for operations like -@@ -480,6 +666,19 @@ not listed above is the other metadata, which contains the changelog information +@@ -480,6 +676,19 @@ not listed above is the other metadata, which contains the changelog information which is used by yum-changelog. This is what "yum makecache" uses. .IP @@ -4048,7 +4076,7 @@ index 515aa73..97acbe4 100644 \fBmultilib_policy \fR Can be set to 'all' or 'best'. All means install all possible arches for any package you want to install. Therefore yum install foo will install foo.i386 and foo.x86_64 on x86_64, -@@ -523,6 +722,13 @@ Default is `normal'. +@@ -523,6 +732,13 @@ Default is `normal'. See color_list_installed_older for possible values. .IP @@ -4062,7 +4090,7 @@ index 515aa73..97acbe4 100644 \fBcolor_list_installed_extra \fR The colorization/highlighting for packages in list/info installed which has no available package with the same name and arch. -@@ -558,6 +764,13 @@ Default is `bold,underline,green. +@@ -558,6 +774,13 @@ Default is `bold,underline,green. See color_list_installed_older for possible values. .IP @@ -4076,7 +4104,7 @@ index 515aa73..97acbe4 100644 \fBcolor_search_match \fR The colorization/highlighting for text matches in search. Default is `bold'. -@@ -587,15 +800,104 @@ be downloaded. The updates list is what is printed when you run "yum update", +@@ -587,15 +810,119 @@ be downloaded. The updates list is what is printed when you run "yum update", Default is `normal'. See color_list_installed_older for possible values. @@ -4153,7 +4181,7 @@ index 515aa73..97acbe4 100644 +.IP +\fBfssnap_automatic_keep\fR +How many old snapshots should yum keep when trying to automatically create a -+new snapshot. Setting to 0 disables this feature. Default is '0'. ++new snapshot. Setting to 0 disables this feature. Default is '1'. + +.IP +\fBfssnap_automatic_percentage\fR @@ -4167,6 +4195,21 @@ index 515aa73..97acbe4 100644 +Default is: !*/swap !*/lv_swap glob:/etc/yum/fssnap.d/*.conf + +.IP ++\fBfssnap_abort_on_errors\fR ++When fssnap_automatic_pre or fssnap_automatic_post is enabled, it's possible to specify which ++fssnap errors should make the transaction fail. The default is `any'. ++ ++`broken-setup' - Abort current transaction if snapshot support is unavailable because ++lvm is missing or broken. ++ ++`snapshot-failure' - Abort current transaction if creating a snapshot fails (e.g. there is not enough ++free space to make a snapshot). ++ ++`any' - Abort current transaction if any of the above occurs. ++ ++`none' - Never abort a transaction in case of errors. ++ ++.IP +\fBdepsolve_loop_limit\fR +Set the number of times any attempt to depsolve before we just give up. This +shouldn't be needed as yum should always solve or fail, however it has been @@ -4181,7 +4224,7 @@ index 515aa73..97acbe4 100644 .SH "[repository] OPTIONS" .LP -@@ -668,6 +970,10 @@ value of mirrorlist is copied to metalink (if metalink is not set). +@@ -668,6 +995,10 @@ value of mirrorlist is copied to metalink (if metalink is not set). Either `1' or `0'. This tells yum whether or not use this repository. .IP @@ -4192,7 +4235,7 @@ index 515aa73..97acbe4 100644 \fBgpgcheck\fR Either `1' or `0'. This tells yum whether or not it should perform a GPG signature check on the packages gotten from this repository. -@@ -702,12 +1008,18 @@ key will be automatically imported without user confirmation. +@@ -702,12 +1033,18 @@ key will be automatically imported without user confirmation. Same as the [main] \fBexclude\fR option but only for this repository. Substitution variables, described below, are honored here. @@ -4215,7 +4258,7 @@ index 515aa73..97acbe4 100644 .IP \fBenablegroups\fR -@@ -755,6 +1067,20 @@ repository. +@@ -755,6 +1092,20 @@ repository. Overrides the \fBbandwidth\fR option from the [main] section for this repository. @@ -4236,7 +4279,7 @@ index 515aa73..97acbe4 100644 .IP \fBsslcacert \fR -@@ -776,6 +1102,10 @@ repository. +@@ -776,6 +1127,10 @@ repository. Overrides the \fBsslclientkey\fR option from the [main] section for this repository. @@ -4247,7 +4290,7 @@ index 515aa73..97acbe4 100644 .IP \fBmetadata_expire \fR -@@ -783,6 +1113,11 @@ Overrides the \fBmetadata_expire\fR option from the [main] section for this +@@ -783,6 +1138,11 @@ Overrides the \fBmetadata_expire\fR option from the [main] section for this repository. .IP @@ -4259,7 +4302,7 @@ index 515aa73..97acbe4 100644 \fBmirrorlist_expire \fR Overrides the \fBmirrorlist_expire\fR option from the [main] section for this repository. -@@ -824,7 +1159,16 @@ as greater/less than any other. defaults to 1000 +@@ -824,7 +1184,16 @@ as greater/less than any other. defaults to 1000 If set to True yum will continue running if this repository cannot be contacted for any reason. This should be set carefully as all repos are consulted for any given command. Defaults to False. @@ -4276,7 +4319,7 @@ index 515aa73..97acbe4 100644 .SH "URL INCLUDE SYNTAX" .LP -@@ -861,8 +1205,8 @@ package. +@@ -861,8 +1230,8 @@ package. .IP \fB$arch\fR @@ -4287,7 +4330,7 @@ index 515aa73..97acbe4 100644 .IP \fB$basearch\fR -@@ -882,8 +1226,10 @@ the same name. If the shell environment variable does not exist then the +@@ -882,8 +1251,10 @@ the same name. If the shell environment variable does not exist then the configuration file variable will not be replaced. .LP @@ -5414,7 +5457,7 @@ index e587f96..e716c01 100644 create 0600 root root } diff --git a/output.py b/output.py -index b6aa277..2787d86 100755 +index b6aa277..091b58e 100755 --- a/output.py +++ b/output.py @@ -1,6 +1,6 @@ @@ -6264,7 +6307,7 @@ index b6aa277..2787d86 100755 symbols = [ ' ', # (none) 'k', # kilo 'M', # mega -@@ -870,16 +1305,31 @@ class YumOutput: +@@ -870,15 +1305,37 @@ class YumOutput: @staticmethod def format_time(seconds, use_hours=0): @@ -6288,7 +6331,6 @@ index b6aa277..2787d86 100755 - If matchfor is passed, all the strings in that list will be - highlighted within the output. - verbose overrides logginglevel, if passed. """ -- + """Output search/provides type callback matches. + + :param po: the package object that matched the search @@ -6299,10 +6341,16 @@ index b6aa277..2787d86 100755 + :param verbose: whether to output extra verbose information + :param highlight: highlighting options for the highlighted matches + """ ++ if (po.repo.id == "installed" and ++ self.conf.query_install_excludes and self.cmdline_excludes): ++ # Very similar to _cmdline_exclude from yumcommands ++ e,m,u = yum.packages.parsePackages([po], self.cmdline_excludes) ++ if e or m: ++ return + if self.conf.showdupesfromrepos: msg = '%s : ' % po - else: -@@ -923,7 +1373,15 @@ class YumOutput: +@@ -923,7 +1380,15 @@ class YumOutput: item = self._enc(item) can_overflow = False else: @@ -6319,7 +6367,7 @@ index b6aa277..2787d86 100755 if matchfor: item = self._sub_highlight(item, highlight, matchfor, -@@ -935,14 +1393,34 @@ class YumOutput: +@@ -935,14 +1400,34 @@ class YumOutput: print '\n\n' def matchcallback_verbose(self, po, values, matchfor=None): @@ -6355,7 +6403,7 @@ index b6aa277..2787d86 100755 for pkg in packages: # Just to be on the safe side, if for some reason getting # the package size fails, log the error and don't report download -@@ -971,18 +1449,18 @@ class YumOutput: +@@ -971,18 +1456,18 @@ class YumOutput: if (not error): if locsize: @@ -6382,7 +6430,7 @@ index b6aa277..2787d86 100755 totsize = 0 error = False for pkg in packages: -@@ -997,13 +1475,19 @@ class YumOutput: +@@ -997,13 +1482,19 @@ class YumOutput: self.logger.error(_('There was an error calculating installed size')) break if (not error): @@ -6407,7 +6455,7 @@ index b6aa277..2787d86 100755 self.tsInfo.makelists(True, True) pkglist_lines = [] data = {'n' : {}, 'v' : {}, 'r' : {}} -@@ -1032,11 +1516,43 @@ class YumOutput: +@@ -1032,11 +1523,43 @@ class YumOutput: for (d, v) in (("n",len(n)), ("v",len(evr)), ("r",len(repoid))): data[d].setdefault(v, 0) data[d][v] += 1 @@ -6454,7 +6502,7 @@ index b6aa277..2787d86 100755 (_('Updating'), self.tsInfo.updated), (_('Removing'), self.tsInfo.removed), (_('Reinstalling'), self.tsInfo.reinstalled), -@@ -1102,19 +1618,72 @@ class YumOutput: +@@ -1102,19 +1625,72 @@ class YumOutput: Transaction Summary %s """) % ('=' * self.term.columns)) @@ -6537,7 +6585,7 @@ index b6aa277..2787d86 100755 out = '' self.tsInfo.makelists() -@@ -1179,17 +1748,19 @@ Transaction Summary +@@ -1179,17 +1755,19 @@ Transaction Summary return out def setupProgressCallbacks(self): @@ -6560,7 +6608,7 @@ index b6aa277..2787d86 100755 callback = CacheProgressCallback() # setup our failure report for failover -@@ -1200,13 +1771,14 @@ Transaction Summary +@@ -1200,13 +1778,14 @@ Transaction Summary interrupt_callback = self.interrupt_callback if hasattr(self, 'prerepoconf'): self.prerepoconf.progressbar = progressbar @@ -6576,7 +6624,7 @@ index b6aa277..2787d86 100755 self.repos.callback = callback self.repos.setFailureCallback(failure_callback) self.repos.setInterruptCallback(interrupt_callback) -@@ -1216,10 +1788,12 @@ Transaction Summary +@@ -1216,10 +1795,12 @@ Transaction Summary self.dsCallback = dscb def setupProgessCallbacks(self): @@ -6590,27 +6638,27 @@ index b6aa277..2787d86 100755 confirm_func = self._cli_confirm_gpg_key_import gpg_import_func = self.getKeyForRepo gpgca_import_func = self.getCAKeyForRepo -@@ -1233,14 +1807,12 @@ Transaction Summary +@@ -1233,14 +1814,12 @@ Transaction Summary self.repos.gpgca_import_func = gpgca_import_func def interrupt_callback(self, cbobj): - '''Handle CTRL-C's during downloads -- -- If a CTRL-C occurs a URLGrabError will be raised to push the download -- onto the next mirror. -- -- If two CTRL-C's occur in quick succession then yum will exit. + '''Handle CTRL-C's during downloads. If a CTRL-C occurs a + URLGrabError will be raised to push the download onto the next + mirror. If two CTRL-C's occur in quick succession then yum + will exit. +- If a CTRL-C occurs a URLGrabError will be raised to push the download +- onto the next mirror. +- +- If two CTRL-C's occur in quick succession then yum will exit. +- - @param cbobj: urlgrabber callback obj + :param cbobj: :class:`urlgrabber.grabber.CallbackObject` ''' delta_exit_chk = 2.0 # Delta between C-c's so we treat as exit delta_exit_str = _("two") # Human readable version of above -@@ -1253,7 +1825,7 @@ Transaction Summary +@@ -1253,7 +1832,7 @@ Transaction Summary # For translators: This is output like: # Current download cancelled, interrupt (ctrl-c) again within two seconds # to exit. @@ -6619,7 +6667,7 @@ index b6aa277..2787d86 100755 msg = _(""" Current download cancelled, %sinterrupt (ctrl-c) again%s within %s%s%s seconds to exit. -@@ -1269,6 +1841,14 @@ to exit. +@@ -1269,6 +1848,14 @@ to exit. def download_callback_total_cb(self, remote_pkgs, remote_size, download_start_timestamp): @@ -6634,7 +6682,7 @@ index b6aa277..2787d86 100755 if len(remote_pkgs) <= 1: return if not hasattr(urlgrabber.progress, 'TerminalLine'): -@@ -1280,7 +1860,7 @@ to exit. +@@ -1280,7 +1867,7 @@ to exit. if dl_time <= 0: # This stops divide by zero, among other problems dl_time = 0.01 ui_size = tl.add(' | %5sB' % self.format_number(remote_size)) @@ -6643,17 +6691,17 @@ index b6aa277..2787d86 100755 ui_end = tl.add(' ' * 5) ui_bs = tl.add(' %5sB/s' % self.format_number(remote_size / dl_time)) msg = "%s%s%s%s%s" % (utf8_width_fill(_("Total"), tl.rest(), tl.rest()), -@@ -1434,10 +2014,21 @@ to exit. +@@ -1434,10 +2021,21 @@ to exit. return tids, printall def historyListCmd(self, extcmds): - """ Shows the user a list of data about the history. """ + """Output a list of information about the history of yum + transactions. - ++ + :param extcmds: list of extra command line arguments + :return: (exit_code, [errors]) -+ + + exit_code is:: + + 0 = we're done, exit @@ -6666,7 +6714,7 @@ index b6aa277..2787d86 100755 return 1, ['Failed history list'] limit = 20 -@@ -1564,6 +2155,16 @@ to exit. +@@ -1564,6 +2162,16 @@ to exit. return old[0] def historyInfoCmd(self, extcmds): @@ -6683,7 +6731,7 @@ index b6aa277..2787d86 100755 def str2int(x): try: return int(x) -@@ -1656,6 +2257,9 @@ to exit. +@@ -1656,6 +2264,9 @@ to exit. def _hpkg2from_repo(self, hpkg): """ Given a pkg, find the ipkg.ui_from_repo ... if none, then get an apkg. ... and put a ? in there. """ @@ -6693,7 +6741,7 @@ index b6aa277..2787d86 100755 ipkgs = self.rpmdb.searchPkgTuple(hpkg.pkgtup) if not ipkgs: apkgs = self.pkgSack.searchPkgTuple(hpkg.pkgtup) -@@ -1672,13 +2276,12 @@ to exit. +@@ -1672,13 +2283,12 @@ to exit. 'o' : _('Updated'), 'n' : _('Downgraded')} _pkg_states_available = {'i' : _('Installed'), 'e' : _('Not installed'), 'o' : _('Older'), 'n' : _('Newer')} @@ -6710,7 +6758,7 @@ index b6aa277..2787d86 100755 prefix = " " * prefix_len if was_installed: _pkg_states = _pkg_states_installed -@@ -1702,9 +2305,11 @@ to exit. +@@ -1702,9 +2312,11 @@ to exit. else: (hibeg, hiend) = self._highlight('normal') state = utf8_width_fill(state, _pkg_states['maxlen']) @@ -6724,7 +6772,7 @@ index b6aa277..2787d86 100755 if type(old.tid) == type([]): print _("Transaction ID :"), "%u..%u" % (old.tid[0], old.tid[-1]) -@@ -1778,8 +2383,8 @@ to exit. +@@ -1778,8 +2390,8 @@ to exit. default_addons = set(['config-main', 'config-repos', 'saved_tx']) non_default = set(addon_info).difference(default_addons) if len(non_default) > 0: @@ -6735,7 +6783,7 @@ index b6aa277..2787d86 100755 if old.trans_with: # This is _possible_, but not common -@@ -1794,7 +2399,9 @@ to exit. +@@ -1794,7 +2406,9 @@ to exit. print _("Packages Skipped:") pkg_max_len = max((len(str(hpkg)) for hpkg in old.trans_skip)) for hpkg in old.trans_skip: @@ -6746,7 +6794,7 @@ index b6aa277..2787d86 100755 if old.rpmdb_problems: print _("Rpmdb Problems:") -@@ -1833,6 +2440,13 @@ to exit. +@@ -1833,6 +2447,13 @@ to exit. 'Updated' : _('Updated'), } def historyInfoCmdPkgsAltered(self, old, pats=[]): @@ -6760,7 +6808,7 @@ index b6aa277..2787d86 100755 last = None # Note that these don't use _simple_pkg() because we are showing what # happened to them in the transaction ... not the difference between the -@@ -1886,6 +2500,10 @@ to exit. +@@ -1886,6 +2507,10 @@ to exit. self._hpkg2from_repo(hpkg)) def historySummaryCmd(self, extcmds): @@ -6771,7 +6819,7 @@ index b6aa277..2787d86 100755 tids, printall = self._history_list_transactions(extcmds) if tids is None: return 1, ['Failed history info'] -@@ -1946,6 +2564,10 @@ to exit. +@@ -1946,6 +2571,10 @@ to exit. utf8_width_fill(uiacts, 16, 16), count) def historyAddonInfoCmd(self, extcmds): @@ -6782,7 +6830,7 @@ index b6aa277..2787d86 100755 tid = None if len(extcmds) > 1: tid = extcmds[1] -@@ -1983,16 +2605,19 @@ to exit. +@@ -1983,16 +2612,19 @@ to exit. for item in extcmds[2:]: if item in addon_info: @@ -6808,7 +6856,7 @@ index b6aa277..2787d86 100755 tids = self.history.search(extcmds) limit = None if extcmds and not tids: -@@ -2078,9 +2703,94 @@ to exit. +@@ -2078,9 +2710,94 @@ to exit. if lastdbv.end_rpmdbversion != rpmdbv: self._rpmdb_warn_checks() @@ -6904,7 +6952,7 @@ index b6aa277..2787d86 100755 def __init__(self, ayum=None): """requires yum-cli log and errorlog functions as arguments""" -@@ -2089,6 +2799,25 @@ class DepSolveProgressCallBack: +@@ -2089,6 +2806,25 @@ class DepSolveProgressCallBack: self.ayum = ayum def pkgAdded(self, pkgtup, mode): @@ -6930,7 +6978,7 @@ index b6aa277..2787d86 100755 modedict = { 'i': _('installed'), 'u': _('an update'), 'e': _('erased'), -@@ -2104,43 +2833,86 @@ class DepSolveProgressCallBack: +@@ -2104,43 +2840,86 @@ class DepSolveProgressCallBack: modeterm) def start(self): @@ -7021,7 +7069,7 @@ index b6aa277..2787d86 100755 needname, needflags, needversion = reqTup yb = self.ayum -@@ -2164,6 +2936,18 @@ class DepSolveProgressCallBack: +@@ -2164,6 +2943,18 @@ class DepSolveProgressCallBack: done = True msg += _('\n %s') % yum.misc.prco_tuple_to_string(pkgtup) if not done: @@ -7040,7 +7088,7 @@ index b6aa277..2787d86 100755 msg += _('\n Not found') return msg -@@ -2225,46 +3009,106 @@ class DepSolveProgressCallBack: +@@ -2225,46 +3016,106 @@ class DepSolveProgressCallBack: return msg def procConflict(self, name, confname): @@ -7152,7 +7200,7 @@ index b6aa277..2787d86 100755 def _pkgname_ui(ayum, pkgname, ts_states=None): """ Get more information on a simple pkgname, if we can. We need to search -@@ -2316,10 +3160,7 @@ def _pkgname_ui(ayum, pkgname, ts_states=None): +@@ -2316,10 +3167,7 @@ def _pkgname_ui(ayum, pkgname, ts_states=None): return pkgname class YumCliRPMCallBack(RPMBaseCallback): @@ -7164,7 +7212,7 @@ index b6aa277..2787d86 100755 width = property(lambda x: _term_width()) -@@ -2337,21 +3178,34 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2337,21 +3185,34 @@ class YumCliRPMCallBack(RPMBaseCallback): # Installing things have pkg objects passed to the events, so only need to # lookup for erased/obsoleted. def pkgname_ui(self, pkgname, ts_states=('e', 'od', 'ud', None)): @@ -7209,7 +7257,7 @@ index b6aa277..2787d86 100755 if type(package) not in types.StringTypes: pkgname = str(package) -@@ -2363,9 +3217,25 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2363,9 +3224,25 @@ class YumCliRPMCallBack(RPMBaseCallback): percent = 0 else: percent = (te_current*100L)/te_total @@ -7236,7 +7284,7 @@ index b6aa277..2787d86 100755 pkgname=pkgname, wid1=wid1) msg = fmt % (utf8_width_fill(process, wid1, wid1), utf8_width_fill(pkgname, wid2, wid2)) -@@ -2377,6 +3247,11 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2377,6 +3254,11 @@ class YumCliRPMCallBack(RPMBaseCallback): print " " def scriptout(self, package, msgs): @@ -7248,7 +7296,7 @@ index b6aa277..2787d86 100755 if msgs: sys.stdout.write(to_unicode(msgs)) sys.stdout.flush() -@@ -2396,7 +3271,7 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2396,7 +3278,7 @@ class YumCliRPMCallBack(RPMBaseCallback): pnl = utf8_width(pkgname) overhead = (2 * l) + 2 # Length of done, above @@ -7257,7 +7305,7 @@ index b6aa277..2787d86 100755 overhead += 1 # Space between pn and done overhead += 2 # Ends for progress overhead += 1 # Space for end -@@ -2429,8 +3304,30 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2429,8 +3311,30 @@ class YumCliRPMCallBack(RPMBaseCallback): wid2 = pnl return fmt, wid1, wid2 @@ -188110,10 +188158,10 @@ index 97a9923..6cede1e 100644 @staticmethod diff --git a/test/simpleupdatetests.py b/test/simpleupdatetests.py -index 6177fb1..bc74de6 100644 +index 6177fb1..0c981c5 100644 --- a/test/simpleupdatetests.py +++ b/test/simpleupdatetests.py -@@ -990,3 +990,262 @@ class SimpleUpdateTests(OperationsTests): +@@ -990,3 +990,277 @@ class SimpleUpdateTests(OperationsTests): # Nothing to do... self.assert_(res==0, msg) @@ -188376,6 +188424,21 @@ index 6177fb1..bc74de6 100644 + + self.assert_(res=='ok', msg) + self.assertResult((bar11,baz12)) ++ ++ def testInstall_kernel_intermediate(self): ++ # Make sure we don't break this again... ++ k11 = FakePackage('kernel', '1', '1', '0', 'i386') ++ k12 = FakePackage('kernel', '1', '2', '0', 'i386') ++ k13 = FakePackage('kernel', '1', '3', '0', 'i386') ++ k14 = FakePackage('kernel', '1', '4', '0', 'i386') ++ k15 = FakePackage('kernel', '1', '5', '0', 'i386') ++ ++ res, msg = self.runOperation(['install', 'kernel-1-2'], ++ [k11, k13, k14], ++ [k11, k12, k13, k14, k15]) ++ ++ self.assert_(res=='ok', msg) ++ self.assertResult((k11, k12, k13, k14)) diff --git a/test/skipbroken-tests.py b/test/skipbroken-tests.py index 812785a..e2abc4c 100644 --- a/test/skipbroken-tests.py @@ -191426,7 +191489,7 @@ index c1af4ad..f69c061 100644 pass diff --git a/yum/__init__.py b/yum/__init__.py -index 99039e0..a8a4e80 100644 +index 99039e0..c62af2c 100644 --- a/yum/__init__.py +++ b/yum/__init__.py @@ -21,6 +21,7 @@ The Yum RPM software updater. @@ -191476,7 +191539,19 @@ index 99039e0..a8a4e80 100644 import string import StringIO -@@ -102,10 +113,12 @@ default_grabber.opts.user_agent += " yum/" + __version__ +@@ -91,6 +102,11 @@ from weakref import proxy as weakref + + from urlgrabber.grabber import default_grabber + ++try: ++ import cashe ++except ImportError: ++ cashe = None ++ + __version__ = '3.4.3' + __version_info__ = tuple([ int(num) for num in __version__.split('.')]) + +@@ -102,10 +118,12 @@ default_grabber.opts.user_agent += " yum/" + __version__ class _YumPreBaseConf: @@ -191493,7 +191568,7 @@ index 99039e0..a8a4e80 100644 def __init__(self): self.fn = '/etc/yum/yum.conf' self.root = '/' -@@ -125,12 +138,15 @@ class _YumPreBaseConf: +@@ -125,12 +143,15 @@ class _YumPreBaseConf: class _YumPreRepoConf: @@ -191513,7 +191588,7 @@ index 99039e0..a8a4e80 100644 self.callback = None self.failure_callback = None self.interrupt_callback = None -@@ -164,11 +180,11 @@ class _YumCostExclude: +@@ -164,11 +185,11 @@ class _YumCostExclude: return False class YumBase(depsolve.Depsolve): @@ -191530,7 +191605,7 @@ index 99039e0..a8a4e80 100644 def __init__(self): depsolve.Depsolve.__init__(self) self._conf = None -@@ -177,9 +193,12 @@ class YumBase(depsolve.Depsolve): +@@ -177,9 +198,12 @@ class YumBase(depsolve.Depsolve): self._up = None self._comps = None self._history = None @@ -191543,7 +191618,7 @@ index 99039e0..a8a4e80 100644 self._ts_save_file = None self.skipped_packages = [] # packages skip by the skip-broken code self._not_found_a = {} -@@ -204,6 +223,9 @@ class YumBase(depsolve.Depsolve): +@@ -204,6 +228,9 @@ class YumBase(depsolve.Depsolve): self.run_with_package_names = set() self._cleanup = [] @@ -191553,7 +191628,7 @@ index 99039e0..a8a4e80 100644 def __del__(self): self.close() -@@ -213,10 +235,15 @@ class YumBase(depsolve.Depsolve): +@@ -213,10 +240,15 @@ class YumBase(depsolve.Depsolve): for cb in self._cleanup: cb() def close(self): @@ -191569,7 +191644,7 @@ index 99039e0..a8a4e80 100644 if self._repos: self._repos.close() -@@ -225,15 +252,33 @@ class YumBase(depsolve.Depsolve): +@@ -225,15 +257,33 @@ class YumBase(depsolve.Depsolve): return transactioninfo.TransactionData() def doGenericSetup(self, cache=0): @@ -191605,7 +191680,7 @@ index 99039e0..a8a4e80 100644 warnings.warn(_('doConfigSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -297,15 +342,17 @@ class YumBase(depsolve.Depsolve): +@@ -297,15 +347,17 @@ class YumBase(depsolve.Depsolve): # Try the old default fn = '/etc/yum.conf' @@ -191626,7 +191701,7 @@ index 99039e0..a8a4e80 100644 if debuglevel != None: startupconf.debuglevel = debuglevel -@@ -336,6 +383,12 @@ class YumBase(depsolve.Depsolve): +@@ -336,6 +388,12 @@ class YumBase(depsolve.Depsolve): self._conf = config.readMainConfig(startupconf) @@ -191639,7 +191714,18 @@ index 99039e0..a8a4e80 100644 # We don't want people accessing/altering preconf after it becomes # worthless. So we delete it, and thus. it'll raise AttributeError del self.preconf -@@ -367,22 +420,36 @@ class YumBase(depsolve.Depsolve): +@@ -344,6 +402,10 @@ class YumBase(depsolve.Depsolve): + for pkgname in self.conf.history_record_packages: + self.run_with_package_names.add(pkgname) + ++ self._cashe = None ++ if cashe is not None: ++ self._cashe = cashe.CAShe(self.conf.cashedir) ++ + # run the postconfig plugin hook + self.plugins.run('postconfig') + # Note that Pungi has historically replaced _getConfig(), and it sets +@@ -367,22 +429,36 @@ class YumBase(depsolve.Depsolve): def doLoggingSetup(self, debuglevel, errorlevel, syslog_ident=None, syslog_facility=None, syslog_device='/dev/log'): @@ -191683,7 +191769,7 @@ index 99039e0..a8a4e80 100644 if repo_age is None: repo_age = os.stat(repofn)[8] -@@ -391,8 +458,7 @@ class YumBase(depsolve.Depsolve): +@@ -391,8 +467,7 @@ class YumBase(depsolve.Depsolve): try: parser.readfp(confpp_obj) except ParsingError, e: @@ -191693,7 +191779,7 @@ index 99039e0..a8a4e80 100644 # Check sections in the .repo file that was just slurped up for section in parser.sections(): -@@ -429,17 +495,41 @@ class YumBase(depsolve.Depsolve): +@@ -429,17 +504,41 @@ class YumBase(depsolve.Depsolve): thisrepo.base_persistdir = self.conf._repos_persistdir @@ -191738,7 +191824,7 @@ index 99039e0..a8a4e80 100644 # Got our list of repo objects, add them to the repos # collection try: -@@ -447,9 +537,18 @@ class YumBase(depsolve.Depsolve): +@@ -447,9 +546,18 @@ class YumBase(depsolve.Depsolve): except Errors.RepoError, e: self.logger.warning(e) @@ -191759,7 +191845,7 @@ index 99039e0..a8a4e80 100644 # Read .repo files from directories specified by the reposdir option # (typically /etc/yum/repos.d) repo_config_age = self.conf.config_file_age -@@ -463,21 +562,26 @@ class YumBase(depsolve.Depsolve): +@@ -463,21 +571,26 @@ class YumBase(depsolve.Depsolve): # if we don't do this then anaconda likes to not work. if os.path.exists(self.conf.installroot+'/'+reposdir): reposdir = self.conf.installroot + '/' + reposdir @@ -191791,17 +191877,21 @@ index 99039e0..a8a4e80 100644 repo = yumRepo.YumRepository(section) try: repo.populate(parser, section, self.conf) -@@ -493,38 +597,40 @@ class YumBase(depsolve.Depsolve): +@@ -493,38 +606,44 @@ class YumBase(depsolve.Depsolve): repo.name = to_unicode(repo.name) # Set attributes not from the config file + repo.old_base_cache_dir = getattr(self, '_old_cachedir', '') repo.basecachedir = self.conf.cachedir repo.yumvar.update(self.conf.yumvar) ++ repo._cashe = self._cashe repo.cfg = parser - + # Enable parallel downloading + repo._async = repo.async ++ # Allow caching local repos ++ if repo.keepcache and any(u.startswith('file:') for u in repo.baseurl): ++ repo.copy_local = True return repo def disablePlugins(self): @@ -191854,7 +191944,7 @@ index 99039e0..a8a4e80 100644 if isinstance(self.plugins, plugins.YumPlugins): raise RuntimeError(_("plugins already initialised")) -@@ -533,6 +639,8 @@ class YumBase(depsolve.Depsolve): +@@ -533,6 +652,8 @@ class YumBase(depsolve.Depsolve): def doRpmDBSetup(self): @@ -191863,7 +191953,7 @@ index 99039e0..a8a4e80 100644 warnings.warn(_('doRpmDBSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -552,7 +660,8 @@ class YumBase(depsolve.Depsolve): +@@ -552,7 +673,8 @@ class YumBase(depsolve.Depsolve): return self._rpmdb def closeRpmDB(self): @@ -191873,7 +191963,7 @@ index 99039e0..a8a4e80 100644 if self._rpmdb is not None: self._rpmdb.ts = None self._rpmdb.dropCachedData() -@@ -561,12 +670,19 @@ class YumBase(depsolve.Depsolve): +@@ -561,12 +683,19 @@ class YumBase(depsolve.Depsolve): self._tsInfo = None self._up = None self.comps = None @@ -191893,7 +191983,7 @@ index 99039e0..a8a4e80 100644 warnings.warn(_('doRepoSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -577,6 +693,12 @@ class YumBase(depsolve.Depsolve): +@@ -577,6 +706,12 @@ class YumBase(depsolve.Depsolve): if hasattr(self, 'prerepoconf'): self.conf # touch the config class first @@ -191906,7 +191996,7 @@ index 99039e0..a8a4e80 100644 self.getReposFromConfig() # For rhnplugin, and in theory other stuff, calling -@@ -588,7 +710,8 @@ class YumBase(depsolve.Depsolve): +@@ -588,7 +723,8 @@ class YumBase(depsolve.Depsolve): prerepoconf = self.prerepoconf del self.prerepoconf @@ -191916,7 +192006,7 @@ index 99039e0..a8a4e80 100644 self.repos.callback = prerepoconf.callback self.repos.setFailureCallback(prerepoconf.failure_callback) self.repos.setInterruptCallback(prerepoconf.interrupt_callback) -@@ -602,24 +725,6 @@ class YumBase(depsolve.Depsolve): +@@ -602,24 +738,6 @@ class YumBase(depsolve.Depsolve): if doSetup: @@ -191941,7 +192031,7 @@ index 99039e0..a8a4e80 100644 repo_st = time.time() self._repos.doSetup(thisrepo) self.verbose_logger.debug('repo time: %0.3f' % (time.time() - repo_st)) -@@ -630,6 +735,14 @@ class YumBase(depsolve.Depsolve): +@@ -630,6 +748,14 @@ class YumBase(depsolve.Depsolve): self._repos = RepoStorage(self) def doSackSetup(self, archlist=None, thisrepo=None): @@ -191956,7 +192046,7 @@ index 99039e0..a8a4e80 100644 warnings.warn(_('doSackSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -711,6 +824,9 @@ class YumBase(depsolve.Depsolve): +@@ -711,6 +837,9 @@ class YumBase(depsolve.Depsolve): def doUpdateSetup(self): @@ -191966,7 +192056,7 @@ index 99039e0..a8a4e80 100644 warnings.warn(_('doUpdateSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -765,6 +881,8 @@ class YumBase(depsolve.Depsolve): +@@ -765,6 +894,8 @@ class YumBase(depsolve.Depsolve): return self._up def doGroupSetup(self): @@ -191975,7 +192065,7 @@ index 99039e0..a8a4e80 100644 warnings.warn(_('doGroupSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -776,7 +894,12 @@ class YumBase(depsolve.Depsolve): +@@ -776,7 +907,12 @@ class YumBase(depsolve.Depsolve): # if we unset the comps object, we need to undo which repos have # been added to the group file as well if self._repos: @@ -191989,7 +192079,7 @@ index 99039e0..a8a4e80 100644 repo.groups_added = False self._comps = val -@@ -801,7 +924,8 @@ class YumBase(depsolve.Depsolve): +@@ -801,7 +937,8 @@ class YumBase(depsolve.Depsolve): continue if not repo.ready(): @@ -191999,7 +192089,7 @@ index 99039e0..a8a4e80 100644 try: groupremote = repo.getGroupLocation() except Errors.RepoMDError, e: -@@ -813,6 +937,21 @@ class YumBase(depsolve.Depsolve): +@@ -813,6 +950,21 @@ class YumBase(depsolve.Depsolve): overwrite = self.conf.overwrite_groups self._comps = comps.Comps(overwrite_groups = overwrite) @@ -192021,7 +192111,7 @@ index 99039e0..a8a4e80 100644 for repo in reposWithGroups: if repo.groups_added: # already added the groups from this repo continue -@@ -820,16 +959,14 @@ class YumBase(depsolve.Depsolve): +@@ -820,16 +972,14 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.log(logginglevels.DEBUG_4, _('Adding group file from repository: %s'), repo) groupfile = repo.getGroups() @@ -192043,7 +192133,7 @@ index 99039e0..a8a4e80 100644 self.logger.critical(msg) else: repo.groups_added = True -@@ -837,7 +974,10 @@ class YumBase(depsolve.Depsolve): +@@ -837,7 +987,10 @@ class YumBase(depsolve.Depsolve): if self._comps.compscount == 0: raise Errors.GroupsError, _('No Groups Available in any repository') @@ -192055,7 +192145,7 @@ index 99039e0..a8a4e80 100644 self.verbose_logger.debug('group time: %0.3f' % (time.time() - group_st)) return self._comps -@@ -868,22 +1008,72 @@ class YumBase(depsolve.Depsolve): +@@ -868,22 +1021,72 @@ class YumBase(depsolve.Depsolve): # feed it into _tags.add() self._tags.add(repo.id, tag_sqlite) except (Errors.RepoError, Errors.PkgTagsError), e: @@ -192130,7 +192220,7 @@ index 99039e0..a8a4e80 100644 # properties so they auto-create themselves with defaults repos = property(fget=lambda self: self._getRepos(), fset=lambda self, value: setattr(self, "_repos", value), -@@ -921,16 +1111,31 @@ class YumBase(depsolve.Depsolve): +@@ -921,16 +1124,31 @@ class YumBase(depsolve.Depsolve): fdel=lambda self: setattr(self, "_history", None), doc="Yum History Object") @@ -192166,7 +192256,7 @@ index 99039e0..a8a4e80 100644 necessary = False # I can't think of a nice way of doing this, we have to have the sack here -@@ -951,25 +1156,37 @@ class YumBase(depsolve.Depsolve): +@@ -951,25 +1169,37 @@ class YumBase(depsolve.Depsolve): self.repos.populateSack(mdtype='filelists') def yumUtilsMsg(self, func, prog): @@ -192215,7 +192305,7 @@ index 99039e0..a8a4e80 100644 self.logger.critical(msg) self.yumUtilsMsg(self.logger.critical, "yum-complete-transaction") time.sleep(3) -@@ -1004,7 +1221,7 @@ class YumBase(depsolve.Depsolve): +@@ -1004,7 +1234,7 @@ class YumBase(depsolve.Depsolve): # If transaction was changed by postresolve plugins then we should run skipbroken again (rescode, restring) = self._doSkipBroken(rescode, restring, clear_skipped=False ) @@ -192224,7 +192314,7 @@ index 99039e0..a8a4e80 100644 self.tsInfo.pkgSack.dropCachedData() # FIXME: This is horrible, see below and yummain. Maybe create a real -@@ -1044,6 +1261,39 @@ class YumBase(depsolve.Depsolve): +@@ -1044,6 +1274,39 @@ class YumBase(depsolve.Depsolve): if first.verEQ(other): continue msg = _('Protected multilib versions: %s != %s') @@ -192264,7 +192354,7 @@ index 99039e0..a8a4e80 100644 xrestring.append(msg % (first, other)) if xrestring: rescode = 1 -@@ -1227,7 +1477,7 @@ class YumBase(depsolve.Depsolve): +@@ -1227,7 +1490,7 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.info(msg) self.skipped_packages.extend(skipped_list) # make the skipped packages public else: @@ -192273,7 +192363,7 @@ index 99039e0..a8a4e80 100644 self.verbose_logger.info("Skip-broken could not solve problems") return 1, orig_restring return rescode, restring -@@ -1242,13 +1492,15 @@ class YumBase(depsolve.Depsolve): +@@ -1242,13 +1505,15 @@ class YumBase(depsolve.Depsolve): if None in pkgtup: return None return pkgtup @@ -192293,7 +192383,7 @@ index 99039e0..a8a4e80 100644 if pkgtup is None: return self._not_found_i[pkgtup] = YumNotFoundPackage(pkgtup) -@@ -1267,7 +1519,7 @@ class YumBase(depsolve.Depsolve): +@@ -1267,7 +1532,7 @@ class YumBase(depsolve.Depsolve): for pkg in txmbr.obsoleted_by: # check if the obsoleting txmbr is in the transaction # else remove the obsoleted txmbr @@ -192302,7 +192392,7 @@ index 99039e0..a8a4e80 100644 if not self.tsInfo.exists(pkg.pkgtup): self.verbose_logger.debug('SKIPBROKEN: Remove extra obsoleted %s (%s)' % (txmbr.po,pkg) ) self.tsInfo.remove(txmbr.po.pkgtup) -@@ -1275,14 +1527,14 @@ class YumBase(depsolve.Depsolve): +@@ -1275,14 +1540,14 @@ class YumBase(depsolve.Depsolve): def _checkUpdatedLeftovers(self): """ If multiple packages is updated the same package @@ -192319,7 +192409,7 @@ index 99039e0..a8a4e80 100644 if not self.tsInfo.exists(pkg.pkgtup): self.verbose_logger.debug('SKIPBROKEN: Remove extra updated %s (%s)' % (txmbr.po,pkg) ) self.tsInfo.remove(txmbr.po.pkgtup) -@@ -1379,9 +1631,19 @@ class YumBase(depsolve.Depsolve): +@@ -1379,9 +1644,19 @@ class YumBase(depsolve.Depsolve): def _getDepsToRemove(self,po, deptree, toRemove): for dep in deptree.get(po, []): # Loop trough all deps of po @@ -192339,7 +192429,7 @@ index 99039e0..a8a4e80 100644 toRemove.add(dep) self._getDepsToRemove(dep, deptree, toRemove) -@@ -1454,7 +1716,46 @@ class YumBase(depsolve.Depsolve): +@@ -1454,7 +1729,66 @@ class YumBase(depsolve.Depsolve): return probs def runTransaction(self, cb): @@ -192352,6 +192442,13 @@ index 99039e0..a8a4e80 100644 + :raises: :class:`yum.Errors.YumRPMTransError` if there is a + transaction cannot be completed + """ ++ if (self.conf.fssnap_automatic_pre or self.conf.fssnap_automatic_post) and not self.fssnap.available: ++ msg = _("Snapshot support not available.") ++ if self.conf.fssnap_abort_on_errors in ('broken-setup', 'any'): ++ raise Errors.YumRPMTransError(msg="Aborting transaction.", errors=msg) ++ else: ++ self.verbose_logger.critical(msg) ++ + if self.fssnap.available and ((self.conf.fssnap_automatic_pre or + self.conf.fssnap_automatic_post) and + self.conf.fssnap_automatic_keep): @@ -192373,21 +192470,34 @@ index 99039e0..a8a4e80 100644 + if num > self.conf.fssnap_automatic_keep: + todel.append(snap['dev']) + # Display something to the user? -+ self.fssnap.del_snapshots(devices=todel) ++ snaps = self.fssnap.del_snapshots(devices=todel) ++ if len(snaps): ++ self.verbose_logger.info(_("Deleted %u snapshots.") % len(snaps)) + + if (self.fssnap.available and + (not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST) and + self.conf.fssnap_automatic_pre)): + if not self.fssnap.has_space(self.conf.fssnap_percentage): -+ msg = _("Not enough space to create pre. FS snapshot, aborting transaction.") -+ raise Errors.YumRPMTransError(msg=msg, errors=[]) ++ msg = _("Not enough space to create pre. FS snapshot.") ++ if self.conf.fssnap_abort_on_errors in ('snapshot-failure', 'any'): ++ raise Errors.YumRPMTransError(msg="Aborting transaction", errors=msg) ++ else: ++ self.verbose_logger.critical(msg) + else: + tags = {'*': ['reason=automatic']} # FIXME: pre. tags -+ self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags) ++ snaps = self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags) ++ if not snaps: ++ msg = _("Failed to create snapshot") ++ if self.conf.fssnap_abort_on_errors in ('snapshot-failure', 'any'): ++ raise Errors.YumRPMTransError(msg="Aborting transaction", errors=msg) ++ else: ++ self.verbose_logger.critical(msg) ++ for (odev, ndev) in snaps: ++ self.verbose_logger.info(_("Created snapshot from %s, results is: %s") % (odev, ndev)) self.plugins.run('pretrans') -@@ -1516,10 +1817,23 @@ class YumBase(depsolve.Depsolve): +@@ -1516,10 +1850,23 @@ class YumBase(depsolve.Depsolve): pass self._ts_save_file = None @@ -192411,7 +192521,7 @@ index 99039e0..a8a4e80 100644 # make resultobject - just a plain yumgenericholder object resultobject = misc.GenericHolder() -@@ -1544,8 +1858,7 @@ class YumBase(depsolve.Depsolve): +@@ -1544,8 +1891,7 @@ class YumBase(depsolve.Depsolve): errors=errors) @@ -192421,7 +192531,7 @@ index 99039e0..a8a4e80 100644 self.cleanUsedHeadersPackages() for i in ('ts_all_fn', 'ts_done_fn'): -@@ -1567,13 +1880,35 @@ class YumBase(depsolve.Depsolve): +@@ -1567,13 +1913,38 @@ class YumBase(depsolve.Depsolve): self.plugins.run('posttrans') # sync up what just happened versus what is in the rpmdb if not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST): @@ -192438,11 +192548,14 @@ index 99039e0..a8a4e80 100644 + self.conf.fssnap_automatic_post)): + if not self.fssnap.has_space(self.conf.fssnap_percentage): + msg = _("Not enough space to create post trans FS snapshot.") -+ self.logger.critical(msg) ++ self.verbose_logger.critical(msg) + else: + tags = {'*': ['reason=automatic']} # FIXME: post tags -+ self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags) -+ ++ snaps = self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags) ++ if not snaps: ++ self.verbose_logger.critical(_("Failed to create snapshot")) ++ for (odev, ndev) in snaps: ++ self.verbose_logger.info(_("Created snapshot from %s, results is: %s") % (odev, ndev)) return resultobject - def verifyTransaction(self, resultobject=None): @@ -192462,7 +192575,7 @@ index 99039e0..a8a4e80 100644 # 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 -@@ -1584,24 +1919,58 @@ class YumBase(depsolve.Depsolve): +@@ -1584,24 +1955,58 @@ class YumBase(depsolve.Depsolve): # that there is not also an install of this pkg in the tsInfo (reinstall) # for any kind of install add from_repo to the yumdb, and the cmdline # and the install reason @@ -192523,7 +192636,7 @@ index 99039e0..a8a4e80 100644 if hasattr(self, 'args') and self.args: po.yumdb_info.command_line = ' '.join(self.args) elif hasattr(self, 'cmds') and self.cmds: -@@ -1630,6 +1999,10 @@ class YumBase(depsolve.Depsolve): +@@ -1630,6 +2035,10 @@ class YumBase(depsolve.Depsolve): if md: po.yumdb_info.from_repo_timestamp = str(md.timestamp) @@ -192534,7 +192647,7 @@ index 99039e0..a8a4e80 100644 loginuid = misc.getloginuid() if txmbr.updates or txmbr.downgrades or txmbr.reinstall: if txmbr.updates: -@@ -1640,11 +2013,16 @@ class YumBase(depsolve.Depsolve): +@@ -1640,11 +2049,16 @@ class YumBase(depsolve.Depsolve): opo = po if 'installed_by' in opo.yumdb_info: po.yumdb_info.installed_by = opo.yumdb_info.installed_by @@ -192551,7 +192664,7 @@ index 99039e0..a8a4e80 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: -@@ -1662,10 +2040,13 @@ class YumBase(depsolve.Depsolve): +@@ -1662,10 +2076,13 @@ class YumBase(depsolve.Depsolve): ' but is not!' % txmbr.po)) # Note: Get Panu to do te.Failed() so we don't have to txmbr.output_state = TS_FAILED @@ -192565,7 +192678,7 @@ index 99039e0..a8a4e80 100644 self.verbose_logger.log(logginglevels.DEBUG_2, 'What is this? %s' % txmbr.po) self.plugins.run('postverifytrans') -@@ -1680,10 +2061,11 @@ class YumBase(depsolve.Depsolve): +@@ -1680,10 +2097,11 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.debug('VerifyTransaction time: %0.3f' % (time.time() - vt_st)) def costExcludePackages(self): @@ -192581,7 +192694,7 @@ index 99039e0..a8a4e80 100644 # if all the repo.costs are equal then don't bother running things costs = {} for r in self.repos.listEnabled(): -@@ -1705,10 +2087,12 @@ class YumBase(depsolve.Depsolve): +@@ -1705,10 +2123,12 @@ class YumBase(depsolve.Depsolve): done = True def excludePackages(self, repo=None): @@ -192597,7 +192710,7 @@ index 99039e0..a8a4e80 100644 if "all" in self.conf.disable_excludes: return -@@ -1735,9 +2119,14 @@ class YumBase(depsolve.Depsolve): +@@ -1735,9 +2155,14 @@ class YumBase(depsolve.Depsolve): self.pkgSack.addPackageExcluder(repoid, exid,'exclude.match', match) def includePackages(self, repo): @@ -192615,7 +192728,7 @@ index 99039e0..a8a4e80 100644 includelist = repo.getIncludePkgList() if len(includelist) == 0: -@@ -1757,8 +2146,11 @@ class YumBase(depsolve.Depsolve): +@@ -1757,8 +2182,11 @@ class YumBase(depsolve.Depsolve): self.pkgSack.addPackageExcluder(repo.id, exid, 'exclude.marked') def doLock(self, lockfile = YUM_PID_FILE): @@ -192629,7 +192742,7 @@ index 99039e0..a8a4e80 100644 if self.conf.uid != 0: # If we are a user, assume we are using the root cache ... so don't # bother locking. -@@ -1773,39 +2165,39 @@ class YumBase(depsolve.Depsolve): +@@ -1773,39 +2201,39 @@ class YumBase(depsolve.Depsolve): lockfile = os.path.normpath(lockfile) # get rid of silly preceding extra / mypid=str(os.getpid()) @@ -192697,7 +192810,7 @@ index 99039e0..a8a4e80 100644 # 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 -@@ -1830,31 +2222,74 @@ class YumBase(depsolve.Depsolve): +@@ -1830,31 +2258,74 @@ class YumBase(depsolve.Depsolve): self._unlock(lockfile) self._lockfile = None @@ -192784,7 +192897,7 @@ index 99039e0..a8a4e80 100644 failed = False if type(fo) is types.InstanceType: -@@ -1877,14 +2312,14 @@ class YumBase(depsolve.Depsolve): +@@ -1877,14 +2348,14 @@ class YumBase(depsolve.Depsolve): cursize = os.stat(fo)[6] totsize = long(po.size) if cursize >= totsize and not po.repo.cache: @@ -192803,7 +192916,7 @@ index 99039e0..a8a4e80 100644 raise URLGrabError(-1, msg) else: return False -@@ -1894,9 +2329,16 @@ class YumBase(depsolve.Depsolve): +@@ -1894,9 +2365,16 @@ class YumBase(depsolve.Depsolve): def verifyChecksum(self, fo, checksumType, csum): @@ -192823,7 +192936,7 @@ index 99039e0..a8a4e80 100644 try: filesum = misc.checksum(checksumType, fo) except Errors.MiscError, e: -@@ -1908,13 +2350,26 @@ class YumBase(depsolve.Depsolve): +@@ -1908,13 +2386,26 @@ class YumBase(depsolve.Depsolve): return 0 def downloadPkgs(self, pkglist, callback=None, callback_total=None): @@ -192851,7 +192964,7 @@ index 99039e0..a8a4e80 100644 if a is None: return -1 if b is None: -@@ -1925,12 +2380,11 @@ class YumBase(depsolve.Depsolve): +@@ -1925,12 +2416,11 @@ class YumBase(depsolve.Depsolve): return 1 return 0 @@ -192866,7 +192979,7 @@ index 99039e0..a8a4e80 100644 # We close the history DB here because some plugins (presto) use # threads. And sqlite really doesn't like threads. And while I don't -@@ -1943,116 +2397,215 @@ class YumBase(depsolve.Depsolve): +@@ -1943,116 +2433,215 @@ class YumBase(depsolve.Depsolve): self.history.close() self.plugins.run('predownload', pkglist=pkglist) @@ -193171,7 +193284,7 @@ index 99039e0..a8a4e80 100644 if type(fo) is types.InstanceType: fo = fo.filename -@@ -2076,9 +2629,12 @@ class YumBase(depsolve.Depsolve): +@@ -2076,9 +2665,12 @@ class YumBase(depsolve.Depsolve): return 1 def downloadHeader(self, po): @@ -193186,7 +193299,7 @@ index 99039e0..a8a4e80 100644 if hasattr(po, 'pkgtype') and po.pkgtype == 'local': return -@@ -2097,8 +2653,8 @@ class YumBase(depsolve.Depsolve): +@@ -2097,8 +2689,8 @@ class YumBase(depsolve.Depsolve): return else: if self.conf.cache: @@ -193197,7 +193310,7 @@ index 99039e0..a8a4e80 100644 if self.dsCallback: self.dsCallback.downloadHeader(po.name) -@@ -2122,15 +2678,17 @@ class YumBase(depsolve.Depsolve): +@@ -2122,15 +2714,17 @@ class YumBase(depsolve.Depsolve): return def sigCheckPkg(self, po): @@ -193223,7 +193336,7 @@ index 99039e0..a8a4e80 100644 if self._override_sigchecks: check = False hasgpgkey = 0 -@@ -2181,6 +2739,9 @@ class YumBase(depsolve.Depsolve): +@@ -2181,6 +2775,9 @@ class YumBase(depsolve.Depsolve): return result, msg def cleanUsedHeadersPackages(self): @@ -193233,7 +193346,7 @@ index 99039e0..a8a4e80 100644 filelist = [] for txmbr in self.tsInfo: if txmbr.po.state not in TS_INSTALL_STATES: -@@ -2189,6 +2750,8 @@ class YumBase(depsolve.Depsolve): +@@ -2189,6 +2786,8 @@ class YumBase(depsolve.Depsolve): continue if txmbr.po.repoid not in self.repos.repos: continue @@ -193242,7 +193355,7 @@ index 99039e0..a8a4e80 100644 # make sure it's not a local file repo = self.repos.repos[txmbr.po.repoid] -@@ -2218,27 +2781,42 @@ class YumBase(depsolve.Depsolve): +@@ -2218,27 +2817,42 @@ class YumBase(depsolve.Depsolve): _('%s removed'), fn) def cleanHeaders(self): @@ -193287,7 +193400,7 @@ index 99039e0..a8a4e80 100644 cachedir = self.conf.persistdir + "/rpmdb-indexes/" if not os.path.exists(cachedir): filelist = [] -@@ -2271,9 +2849,31 @@ class YumBase(depsolve.Depsolve): +@@ -2271,9 +2885,31 @@ class YumBase(depsolve.Depsolve): return 0, [msg] def doPackageLists(self, pkgnarrow='all', patterns=None, showdups=None, @@ -193322,7 +193435,7 @@ index 99039e0..a8a4e80 100644 if showdups is None: showdups = self.conf.showdupesfromrepos ygh = misc.GenericHolder(iter=pkgnarrow) -@@ -2295,6 +2895,8 @@ class YumBase(depsolve.Depsolve): +@@ -2295,6 +2931,8 @@ class YumBase(depsolve.Depsolve): ndinst = {} # Newest versions by name.arch for po in self.rpmdb.returnPackages(patterns=patterns, ignore_case=ic): @@ -193331,7 +193444,7 @@ index 99039e0..a8a4e80 100644 dinst[po.pkgtup] = po if showdups: continue -@@ -2304,8 +2906,13 @@ class YumBase(depsolve.Depsolve): +@@ -2304,8 +2942,13 @@ class YumBase(depsolve.Depsolve): installed = dinst.values() if showdups: @@ -193346,7 +193459,7 @@ index 99039e0..a8a4e80 100644 else: try: avail = self.pkgSack.returnNewestByNameArch(patterns=patterns, -@@ -2323,16 +2930,31 @@ class YumBase(depsolve.Depsolve): +@@ -2323,16 +2966,31 @@ class YumBase(depsolve.Depsolve): key = (pkg.name, pkg.arch) if pkg.pkgtup in dinst: reinstall_available.append(pkg) @@ -193381,7 +193494,7 @@ index 99039e0..a8a4e80 100644 if len(matches) > 1: updates.append(matches[0]) self.verbose_logger.log(logginglevels.DEBUG_1, -@@ -2352,13 +2974,19 @@ class YumBase(depsolve.Depsolve): +@@ -2352,13 +3010,19 @@ class YumBase(depsolve.Depsolve): elif pkgnarrow == 'installed': installed = self.rpmdb.returnPackages(patterns=patterns, ignore_case=ic) @@ -193402,7 +193515,7 @@ index 99039e0..a8a4e80 100644 else: try: avail = self.pkgSack.returnNewestByNameArch(patterns=patterns, -@@ -2392,9 +3020,21 @@ class YumBase(depsolve.Depsolve): +@@ -2392,9 +3056,21 @@ class YumBase(depsolve.Depsolve): avail = set(avail) for po in self.rpmdb.returnPackages(patterns=patterns, ignore_case=ic): @@ -193424,7 +193537,7 @@ index 99039e0..a8a4e80 100644 # obsoleting packages (and what they obsolete) elif pkgnarrow == 'obsoletes': self.conf.obsoletes = 1 -@@ -2402,6 +3042,7 @@ class YumBase(depsolve.Depsolve): +@@ -2402,6 +3078,7 @@ class YumBase(depsolve.Depsolve): for (pkgtup, instTup) in self.up.getObsoletesTuples(): (n,a,e,v,r) = pkgtup pkgs = self.pkgSack.searchNevra(name=n, arch=a, ver=v, rel=r, epoch=e) @@ -193432,7 +193545,7 @@ index 99039e0..a8a4e80 100644 instpo = self.getInstalledPackageObject(instTup) for po in pkgs: obsoletes.append(po) -@@ -2433,7 +3074,12 @@ class YumBase(depsolve.Depsolve): +@@ -2433,7 +3110,12 @@ class YumBase(depsolve.Depsolve): recentlimit = now-(self.conf.recent*86400) if showdups: avail = self.pkgSack.returnPackages(patterns=patterns, @@ -193446,7 +193559,7 @@ index 99039e0..a8a4e80 100644 else: try: avail = self.pkgSack.returnNewestByNameArch(patterns=patterns, -@@ -2461,14 +3107,13 @@ class YumBase(depsolve.Depsolve): +@@ -2461,14 +3143,13 @@ class YumBase(depsolve.Depsolve): def findDeps(self, pkgs): @@ -193466,7 +193579,7 @@ index 99039e0..a8a4e80 100644 results = {} for pkg in pkgs: -@@ -2495,10 +3140,22 @@ class YumBase(depsolve.Depsolve): +@@ -2495,10 +3176,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): @@ -193493,7 +193606,7 @@ index 99039e0..a8a4e80 100644 sql_fields = [] for f in fields: sql_fields.append(RPM_TO_SQLITE.get(f, f)) -@@ -2614,7 +3271,7 @@ class YumBase(depsolve.Depsolve): +@@ -2614,7 +3307,7 @@ class YumBase(depsolve.Depsolve): # ...but without showdups we want to output _just_ #3, which requires # we find the newest EVR po for the best "matching value". Without keys # it's the same, except we just want the newest EVR. @@ -193502,7 +193615,7 @@ index 99039e0..a8a4e80 100644 # either, so it's pretty thankless. HTH. HAND. # By default just sort using package sorting sort_func = operator.itemgetter(0) -@@ -2661,6 +3318,14 @@ class YumBase(depsolve.Depsolve): +@@ -2661,6 +3354,14 @@ class YumBase(depsolve.Depsolve): yield (po, vs) def searchPackageTags(self, criteria): @@ -193517,7 +193630,7 @@ index 99039e0..a8a4e80 100644 results = {} # name = [(criteria, taglist)] for c in criteria: c = c.lower() -@@ -2677,11 +3342,16 @@ class YumBase(depsolve.Depsolve): +@@ -2677,11 +3378,16 @@ class YumBase(depsolve.Depsolve): return results def searchPackages(self, fields, criteria, callback=None): @@ -193539,7 +193652,7 @@ index 99039e0..a8a4e80 100644 warnings.warn(_('searchPackages() will go away in a future version of Yum.\ Use searchGenerator() instead. \n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -2700,13 +3370,23 @@ class YumBase(depsolve.Depsolve): +@@ -2700,13 +3406,23 @@ class YumBase(depsolve.Depsolve): def searchPackageProvides(self, args, callback=None, callback_has_matchfor=False): @@ -193567,7 +193680,7 @@ index 99039e0..a8a4e80 100644 else: isglob = True canBeFile = misc.re_filename(arg) -@@ -2723,7 +3403,7 @@ class YumBase(depsolve.Depsolve): +@@ -2723,7 +3439,7 @@ class YumBase(depsolve.Depsolve): where = self.returnPackagesByDep(arg) else: usedDepString = False @@ -193576,7 +193689,7 @@ index 99039e0..a8a4e80 100644 self.verbose_logger.log(logginglevels.DEBUG_1, P_('Searching %d package', 'Searching %d packages', len(where)), len(where)) -@@ -2817,29 +3497,170 @@ class YumBase(depsolve.Depsolve): +@@ -2817,26 +3533,167 @@ class YumBase(depsolve.Depsolve): return matches @@ -193622,9 +193735,6 @@ index 99039e0..a8a4e80 100644 - for grp in grps: - if grp.installed: - if uservisible: -- if grp.user_visible: -- installed.append(grp) -- else: + if not ipkgs: + ret[pkg_name] = 'blacklisted-available' + continue @@ -193763,13 +193873,10 @@ index 99039e0..a8a4e80 100644 + + if grp_installed: + if uservisible: -+ if grp.user_visible: -+ installed.append(grp) -+ else: - installed.append(grp) - else: - if uservisible: -@@ -2847,34 +3668,97 @@ class YumBase(depsolve.Depsolve): + if grp.user_visible: + installed.append(grp) + else: +@@ -2847,34 +3704,97 @@ class YumBase(depsolve.Depsolve): available.append(grp) else: available.append(grp) @@ -193875,7 +193982,7 @@ index 99039e0..a8a4e80 100644 thesegroups = self.comps.return_groups(grpid) if not thesegroups: raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -2898,18 +3782,53 @@ class YumBase(depsolve.Depsolve): +@@ -2898,18 +3818,53 @@ class YumBase(depsolve.Depsolve): self.tsInfo.remove(txmbr.po.pkgtup) @@ -193939,7 +194046,7 @@ index 99039e0..a8a4e80 100644 txmbrs_used = [] thesegroups = self.comps.return_groups(grpid) -@@ -2920,12 +3839,18 @@ class YumBase(depsolve.Depsolve): +@@ -2920,12 +3875,18 @@ class YumBase(depsolve.Depsolve): if group_package_types: package_types = group_package_types @@ -193958,7 +194065,7 @@ index 99039e0..a8a4e80 100644 pkgs = [] if 'mandatory' in package_types: pkgs.extend(thisgroup.mandatory_packages) -@@ -2934,12 +3859,56 @@ class YumBase(depsolve.Depsolve): +@@ -2934,12 +3895,56 @@ class YumBase(depsolve.Depsolve): if 'optional' in package_types: pkgs.extend(thisgroup.optional_packages) @@ -194016,7 +194123,7 @@ index 99039e0..a8a4e80 100644 except Errors.InstallError, e: self.verbose_logger.debug(_('No package named %s available to be installed'), pkg) -@@ -2953,7 +3922,9 @@ class YumBase(depsolve.Depsolve): +@@ -2953,7 +3958,9 @@ class YumBase(depsolve.Depsolve): group_conditionals = enable_group_conditionals count_cond_test = 0 @@ -194027,7 +194134,7 @@ index 99039e0..a8a4e80 100644 for condreq, cond in thisgroup.conditional_packages.iteritems(): if self.isPackageInstalled(cond): try: -@@ -2990,17 +3961,23 @@ class YumBase(depsolve.Depsolve): +@@ -2990,17 +3997,23 @@ class YumBase(depsolve.Depsolve): if cond not in self.tsInfo.conditionals: self.tsInfo.conditionals[cond] = [] self.tsInfo.conditionals[cond].extend(pkgs) @@ -194058,7 +194165,7 @@ index 99039e0..a8a4e80 100644 if not self.comps.has_group(grpid): raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -3008,7 +3985,8 @@ class YumBase(depsolve.Depsolve): +@@ -3008,7 +4021,8 @@ class YumBase(depsolve.Depsolve): thesegroups = self.comps.return_groups(grpid) if not thesegroups: raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) @@ -194068,7 +194175,7 @@ index 99039e0..a8a4e80 100644 for thisgroup in thesegroups: thisgroup.selected = False -@@ -3034,13 +4012,114 @@ class YumBase(depsolve.Depsolve): +@@ -3034,13 +4048,114 @@ class YumBase(depsolve.Depsolve): for pkg in self.tsInfo.conditionals.get(txmbr.name, []): self.tsInfo.remove(pkg.pkgtup) @@ -194189,7 +194296,7 @@ index 99039e0..a8a4e80 100644 # look it up in the self.localPackages first: for po in self.localPackages: if po.pkgtup == pkgtup: -@@ -3049,7 +4128,7 @@ class YumBase(depsolve.Depsolve): +@@ -3049,7 +4164,7 @@ class YumBase(depsolve.Depsolve): pkgs = self.pkgSack.searchPkgTuple(pkgtup) if len(pkgs) == 0: @@ -194198,7 +194305,7 @@ index 99039e0..a8a4e80 100644 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 +4144,21 @@ class YumBase(depsolve.Depsolve): +@@ -3065,13 +4180,21 @@ class YumBase(depsolve.Depsolve): return result def getInstalledPackageObject(self, pkgtup): @@ -194225,7 +194332,7 @@ index 99039e0..a8a4e80 100644 raise Errors.RpmDBError, _('Package tuple %s could not be found in rpmdb') % str(pkgtup) # Dito. FIXME from getPackageObject() for len() > 1 ... :) -@@ -3079,9 +4166,11 @@ class YumBase(depsolve.Depsolve): +@@ -3079,9 +4202,11 @@ class YumBase(depsolve.Depsolve): return po def gpgKeyCheck(self): @@ -194239,7 +194346,7 @@ index 99039e0..a8a4e80 100644 gpgkeyschecked = self.conf.cachedir + '/.gpgkeyschecked.yum' if os.path.exists(gpgkeyschecked): return 1 -@@ -3106,9 +4195,13 @@ class YumBase(depsolve.Depsolve): +@@ -3106,9 +4231,13 @@ class YumBase(depsolve.Depsolve): return 1 def returnPackagesByDep(self, depstring): @@ -194255,7 +194362,7 @@ index 99039e0..a8a4e80 100644 if not depstring: return [] -@@ -3132,12 +4225,23 @@ class YumBase(depsolve.Depsolve): +@@ -3132,12 +4261,23 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _('Invalid version flag from: %s') % str(depstring) depflags = SYMBOLFLAGS[flagsymbol] @@ -194282,7 +194389,7 @@ index 99039e0..a8a4e80 100644 # we get all sorts of randomness here errstring = depstring if type(depstring) not in types.StringTypes: -@@ -3149,16 +4253,22 @@ class YumBase(depsolve.Depsolve): +@@ -3149,16 +4289,22 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _('No Package found for %s') % errstring ps = ListPackageSack(pkglist) @@ -194309,7 +194416,7 @@ index 99039e0..a8a4e80 100644 if not depstring: return [] -@@ -3182,14 +4292,53 @@ class YumBase(depsolve.Depsolve): +@@ -3182,14 +4328,53 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _('Invalid version flag from: %s') % str(depstring) depflags = SYMBOLFLAGS[flagsymbol] @@ -194365,7 +194472,7 @@ index 99039e0..a8a4e80 100644 if len(pkglist) == 0: -@@ -3198,14 +4347,23 @@ class YumBase(depsolve.Depsolve): +@@ -3198,14 +4383,23 @@ class YumBase(depsolve.Depsolve): if len(pkglist) == 1: return pkglist[0] @@ -194395,7 +194502,7 @@ index 99039e0..a8a4e80 100644 returnlist = [] compatArchList = self.arch.get_arch_list(arch) multiLib = [] -@@ -3222,9 +4380,9 @@ class YumBase(depsolve.Depsolve): +@@ -3222,9 +4416,9 @@ class YumBase(depsolve.Depsolve): singleLib.append(po) # we now have three lists. find the best package(s) of each @@ -194408,7 +194515,7 @@ index 99039e0..a8a4e80 100644 if single_name and multi and single and multi.name != single.name: # Sinlge _must_ match multi, if we want a single package name -@@ -3238,7 +4396,7 @@ class YumBase(depsolve.Depsolve): +@@ -3238,7 +4432,7 @@ class YumBase(depsolve.Depsolve): # if there's a noarch and it's newer than the multilib, we want # just the noarch. otherwise, we want multi + single elif multi: @@ -194417,7 +194524,7 @@ index 99039e0..a8a4e80 100644 if best.arch == "noarch": returnlist.append(no) else: -@@ -3246,7 +4404,7 @@ class YumBase(depsolve.Depsolve): +@@ -3246,7 +4440,7 @@ class YumBase(depsolve.Depsolve): if single: returnlist.append(single) # similar for the non-multilib case elif single: @@ -194426,7 +194533,7 @@ index 99039e0..a8a4e80 100644 if best.arch == "noarch": returnlist.append(no) else: -@@ -3350,28 +4508,71 @@ class YumBase(depsolve.Depsolve): +@@ -3350,28 +4544,71 @@ class YumBase(depsolve.Depsolve): done = True slow = next_func(slow) @@ -194508,7 +194615,7 @@ index 99039e0..a8a4e80 100644 try: txmbrs = self.groupRemove(group_string) except yum.Errors.GroupsError: -@@ -3387,6 +4588,8 @@ class YumBase(depsolve.Depsolve): +@@ -3387,6 +4624,8 @@ class YumBase(depsolve.Depsolve): assert pattern[0] == '@' grpid = pattern[1:] @@ -194517,7 +194624,7 @@ index 99039e0..a8a4e80 100644 thesegroups = self.comps.return_groups(grpid) if not thesegroups: raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -3398,7 +4601,11 @@ class YumBase(depsolve.Depsolve): +@@ -3398,7 +4637,11 @@ class YumBase(depsolve.Depsolve): def _minus_deselect(self, pattern): """ Remove things from the transaction, like kickstart. """ assert pattern[0] == '-' @@ -194530,7 +194637,7 @@ index 99039e0..a8a4e80 100644 if pat and pat[0] == '@': pat = pat[1:] -@@ -3437,14 +4644,87 @@ class YumBase(depsolve.Depsolve): +@@ -3437,14 +4680,90 @@ class YumBase(depsolve.Depsolve): if flag not in self.tsInfo.probFilterFlags: self.tsInfo.probFilterFlags.append(flag) @@ -194544,6 +194651,9 @@ index 99039e0..a8a4e80 100644 + # don't have to. + return po.pkgtup in self.up.updating_dict + ++ if self.allowedMultipleInstalls(po): ++ return False ++ + for ipkg in ipkgs: + if po.verLE(ipkg): + continue @@ -194624,7 +194734,7 @@ index 99039e0..a8a4e80 100644 pkgs = [] was_pattern = False if po: -@@ -3464,9 +4744,14 @@ class YumBase(depsolve.Depsolve): +@@ -3464,9 +4783,14 @@ class YumBase(depsolve.Depsolve): if kwargs['pattern'] and kwargs['pattern'][0] == '@': return self._at_groupinstall(kwargs['pattern']) @@ -194639,7 +194749,7 @@ index 99039e0..a8a4e80 100644 ignore_case=False) pkgs.extend(mypkgs) # if we have anything left unmatched, let's take a look for it -@@ -3477,20 +4762,14 @@ class YumBase(depsolve.Depsolve): +@@ -3477,20 +4801,14 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.debug(_('Checking for virtual provide or file-provide for %s'), arg) @@ -194668,7 +194778,7 @@ index 99039e0..a8a4e80 100644 else: nevra_dict = self._nevra_kwarg_parse(kwargs) -@@ -3499,6 +4778,8 @@ class YumBase(depsolve.Depsolve): +@@ -3499,6 +4817,8 @@ class YumBase(depsolve.Depsolve): ver=nevra_dict['version'], rel=nevra_dict['release']) self._add_not_found_a(pkgs, nevra_dict) @@ -194677,7 +194787,7 @@ index 99039e0..a8a4e80 100644 if pkgs: # if was_pattern or nevra-dict['arch'] is none, take the list # of arches based on our multilib_compat config and -@@ -3577,17 +4858,21 @@ class YumBase(depsolve.Depsolve): +@@ -3577,17 +4897,21 @@ class YumBase(depsolve.Depsolve): continue # make sure this shouldn't be passed to update: @@ -194703,7 +194813,7 @@ index 99039e0..a8a4e80 100644 obsoleting_pkg = self._test_loop(po, self._pkg2obspkg) if obsoleting_pkg is not None: # this is not a definitive check but it'll make sure we don't -@@ -3600,23 +4885,23 @@ class YumBase(depsolve.Depsolve): +@@ -3600,23 +4924,23 @@ class YumBase(depsolve.Depsolve): already_obs = pkgs[0] if already_obs: @@ -194734,7 +194844,7 @@ index 99039e0..a8a4e80 100644 continue # make sure we don't have a name.arch of this already installed -@@ -3630,8 +4915,8 @@ class YumBase(depsolve.Depsolve): +@@ -3630,8 +4954,8 @@ class YumBase(depsolve.Depsolve): found = True break if not found: @@ -194745,7 +194855,7 @@ index 99039e0..a8a4e80 100644 tx_return.extend(txmbrs) continue -@@ -3719,19 +5004,47 @@ class YumBase(depsolve.Depsolve): +@@ -3719,19 +5043,47 @@ class YumBase(depsolve.Depsolve): return txmbr def update(self, po=None, requiringPo=None, update_to=False, **kwargs): @@ -194800,7 +194910,7 @@ index 99039e0..a8a4e80 100644 tx_return = [] if not po and not kwargs: # update everything (the easy case) self.verbose_logger.log(logginglevels.DEBUG_2, _('Updating Everything')) -@@ -3765,7 +5078,15 @@ class YumBase(depsolve.Depsolve): +@@ -3765,7 +5117,15 @@ class YumBase(depsolve.Depsolve): if new is None: continue tx_return.extend(self.update(po=new)) @@ -194817,7 +194927,7 @@ index 99039e0..a8a4e80 100644 return tx_return # complications -@@ -3787,13 +5108,16 @@ class YumBase(depsolve.Depsolve): +@@ -3787,13 +5147,16 @@ class YumBase(depsolve.Depsolve): return self._minus_deselect(kwargs['pattern']) if kwargs['pattern'] and kwargs['pattern'][0] == '@': @@ -194836,7 +194946,7 @@ index 99039e0..a8a4e80 100644 if not instpkgs and not availpkgs: depmatches = [] -@@ -3805,6 +5129,8 @@ class YumBase(depsolve.Depsolve): +@@ -3805,6 +5168,8 @@ class YumBase(depsolve.Depsolve): except yum.Errors.YumBaseError, e: self.logger.critical(_('%s') % e) @@ -194845,7 +194955,7 @@ index 99039e0..a8a4e80 100644 if update_to: availpkgs.extend(depmatches) else: -@@ -3816,9 +5142,12 @@ class YumBase(depsolve.Depsolve): +@@ -3816,9 +5181,12 @@ class YumBase(depsolve.Depsolve): try: if update_to: m = [] @@ -194859,7 +194969,7 @@ index 99039e0..a8a4e80 100644 m = self.pkgSack.returnNewestByNameArch(patterns=pats) except Errors.PackageSackError: m = [] -@@ -3843,7 +5172,7 @@ class YumBase(depsolve.Depsolve): +@@ -3843,7 +5211,7 @@ class YumBase(depsolve.Depsolve): availpkgs = self._compare_providers(availpkgs, requiringPo) availpkgs = map(lambda x: x[0], availpkgs) elif not availpkgs: @@ -194868,7 +194978,7 @@ index 99039e0..a8a4e80 100644 # for any thing specified # get the list of available pkgs matching it (or take the po) -@@ -3879,6 +5208,7 @@ class YumBase(depsolve.Depsolve): +@@ -3879,6 +5247,7 @@ class YumBase(depsolve.Depsolve): if obsoleting_pkg is None: continue obs_pkgs.append(obsoleting_pkg) @@ -194876,7 +194986,7 @@ index 99039e0..a8a4e80 100644 for obsoleting_pkg in packagesNewestByName(obs_pkgs): tx_return.extend(self.install(po=obsoleting_pkg)) for available_pkg in availpkgs: -@@ -3920,11 +5250,29 @@ class YumBase(depsolve.Depsolve): +@@ -3920,11 +5289,29 @@ class YumBase(depsolve.Depsolve): tx_return.append(txmbr) for available_pkg in availpkgs: @@ -194906,7 +195016,7 @@ index 99039e0..a8a4e80 100644 self.verbose_logger.log(logginglevels.DEBUG_2, _('Not Updating Package that is obsoleted: %s'), available_pkg) tx_return.extend(self.update(po=obsoleting_pkg)) continue -@@ -3985,11 +5333,18 @@ class YumBase(depsolve.Depsolve): +@@ -3985,11 +5372,18 @@ class YumBase(depsolve.Depsolve): return tx_return def remove(self, po=None, **kwargs): @@ -194930,7 +195040,7 @@ index 99039e0..a8a4e80 100644 if not po and not kwargs: raise Errors.RemoveError, 'Nothing specified to remove' -@@ -4008,6 +5363,10 @@ class YumBase(depsolve.Depsolve): +@@ -4008,6 +5402,10 @@ class YumBase(depsolve.Depsolve): return self._at_groupremove(kwargs['pattern']) (e,m,u) = self.rpmdb.matchPackageNames([kwargs['pattern']]) @@ -194941,7 +195051,7 @@ index 99039e0..a8a4e80 100644 pkgs.extend(e) pkgs.extend(m) if u: -@@ -4018,6 +5377,10 @@ class YumBase(depsolve.Depsolve): +@@ -4018,6 +5416,10 @@ class YumBase(depsolve.Depsolve): except yum.Errors.YumBaseError, e: self.logger.critical(_('%s') % e) @@ -194952,7 +195062,7 @@ index 99039e0..a8a4e80 100644 if not depmatches: arg = to_unicode(arg) self.logger.critical(_('No Match for argument: %s') % to_unicode(arg)) -@@ -4055,17 +5418,19 @@ class YumBase(depsolve.Depsolve): +@@ -4055,17 +5457,19 @@ class YumBase(depsolve.Depsolve): return tx_return def installLocal(self, pkg, po=None, updateonly=False): @@ -194982,7 +195092,7 @@ index 99039e0..a8a4e80 100644 # 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 +5548,15 @@ class YumBase(depsolve.Depsolve): +@@ -4183,16 +5587,15 @@ class YumBase(depsolve.Depsolve): return tx_return def reinstallLocal(self, pkg, po=None): @@ -195007,7 +195117,7 @@ index 99039e0..a8a4e80 100644 if not po: try: po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg, -@@ -4215,13 +5579,29 @@ class YumBase(depsolve.Depsolve): +@@ -4215,13 +5618,29 @@ class YumBase(depsolve.Depsolve): return self.reinstall(po=po) def reinstall(self, po=None, **kwargs): @@ -195040,7 +195150,7 @@ index 99039e0..a8a4e80 100644 tx_mbrs = [] if po: # The po, is the "available" po ... we want the installed po tx_mbrs.extend(self.remove(pkgtup=po.pkgtup)) -@@ -4240,10 +5620,11 @@ class YumBase(depsolve.Depsolve): +@@ -4240,10 +5659,11 @@ class YumBase(depsolve.Depsolve): # pkgs that are obsolete. old_conf_obs = self.conf.obsoletes self.conf.obsoletes = False @@ -195054,7 +195164,7 @@ index 99039e0..a8a4e80 100644 self.conf.obsoletes = old_conf_obs if len(members) == 0: self.tsInfo.remove(item.pkgtup) -@@ -4259,16 +5640,15 @@ class YumBase(depsolve.Depsolve): +@@ -4259,16 +5679,15 @@ class YumBase(depsolve.Depsolve): return tx_mbrs def downgradeLocal(self, pkg, po=None): @@ -195079,7 +195189,7 @@ index 99039e0..a8a4e80 100644 if not po: try: po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg, -@@ -4309,13 +5689,19 @@ class YumBase(depsolve.Depsolve): +@@ -4309,13 +5728,19 @@ class YumBase(depsolve.Depsolve): return False def downgrade(self, po=None, **kwargs): @@ -195106,7 +195216,7 @@ index 99039e0..a8a4e80 100644 if not po and not kwargs: raise Errors.DowngradeError, 'Nothing specified to downgrade' -@@ -4397,6 +5783,10 @@ class YumBase(depsolve.Depsolve): +@@ -4397,6 +5822,10 @@ class YumBase(depsolve.Depsolve): # installed version. Indexed fromn the latest installed pkgtup. downgrade_apkgs = {} for pkg in sorted(apkgs): @@ -195117,7 +195227,7 @@ index 99039e0..a8a4e80 100644 na = (pkg.name, pkg.arch) # Here we allow downgrades from .i386 => .noarch, or .i586 => .i386 -@@ -4421,6 +5811,9 @@ class YumBase(depsolve.Depsolve): +@@ -4421,6 +5850,9 @@ class YumBase(depsolve.Depsolve): warned_nas.add(na) continue @@ -195127,7 +195237,7 @@ index 99039e0..a8a4e80 100644 if pkg.verGE(lipkg): if na not in warned_nas: msg = _('Only Upgrade available on package: %s') % pkg -@@ -4457,7 +5850,7 @@ class YumBase(depsolve.Depsolve): +@@ -4457,7 +5889,7 @@ class YumBase(depsolve.Depsolve): if e and v and r: evr = '%s:%s-%s' % (e, v, r) elif v and r: @@ -195136,7 +195246,7 @@ index 99039e0..a8a4e80 100644 elif e and v: evr = '%s:%s' % (e, v) elif v: # e and r etc. is just too weird to print -@@ -4500,12 +5893,24 @@ class YumBase(depsolve.Depsolve): +@@ -4500,12 +5932,24 @@ class YumBase(depsolve.Depsolve): return returndict @@ -195164,7 +195274,7 @@ index 99039e0..a8a4e80 100644 old_conf_obs = self.conf.obsoletes self.conf.obsoletes = False done = False -@@ -4515,19 +5920,46 @@ class YumBase(depsolve.Depsolve): +@@ -4515,19 +5959,46 @@ class YumBase(depsolve.Depsolve): done = True for pkg in transaction.trans_data: if pkg.state == 'Downgrade': @@ -195211,7 +195321,7 @@ index 99039e0..a8a4e80 100644 if self.install(pkgtup=pkg.pkgtup): done = True for pkg in transaction.trans_data: -@@ -4538,8 +5970,14 @@ class YumBase(depsolve.Depsolve): +@@ -4538,8 +6009,14 @@ class YumBase(depsolve.Depsolve): return done def history_undo(self, transaction): @@ -195228,7 +195338,7 @@ index 99039e0..a8a4e80 100644 # 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 :). -@@ -4616,7 +6054,7 @@ class YumBase(depsolve.Depsolve): +@@ -4616,7 +6093,7 @@ class YumBase(depsolve.Depsolve): except urlgrabber.grabber.URLGrabError, e: raise Errors.YumBaseError(_('GPG key retrieval failed: ') + @@ -195237,7 +195347,7 @@ index 99039e0..a8a4e80 100644 # check for a .asc file accompanying it - that's our gpg sig on the key # suck it down and do the check -@@ -4649,7 +6087,7 @@ class YumBase(depsolve.Depsolve): +@@ -4649,7 +6126,7 @@ class YumBase(depsolve.Depsolve): keys_info = misc.getgpgkeyinfo(rawkey, multiple=True) except ValueError, e: raise Errors.YumBaseError(_('Invalid GPG Key from %s: %s') % @@ -195246,7 +195356,7 @@ index 99039e0..a8a4e80 100644 keys = [] for keyinfo in keys_info: thiskey = {} -@@ -4674,39 +6112,49 @@ class YumBase(depsolve.Depsolve): +@@ -4674,39 +6151,49 @@ class YumBase(depsolve.Depsolve): if pkgs: pkgs = sorted(pkgs)[-1] msg = (_('Importing %s key 0x%s:\n' @@ -195314,7 +195424,7 @@ index 99039e0..a8a4e80 100644 user_cb_fail = False for keyurl in keyurls: keys = self._retrievePublicKey(keyurl, repo) -@@ -4725,7 +6173,9 @@ class YumBase(depsolve.Depsolve): +@@ -4725,7 +6212,9 @@ class YumBase(depsolve.Depsolve): # Try installing/updating GPG key self._getKeyImportMessage(info, keyurl) rc = False @@ -195325,7 +195435,7 @@ index 99039e0..a8a4e80 100644 rc = True # grab the .sig/.asc for the keyurl, if it exists -@@ -4751,8 +6201,8 @@ class YumBase(depsolve.Depsolve): +@@ -4751,8 +6240,8 @@ class YumBase(depsolve.Depsolve): ts = self.rpmdb.readOnlyTS() result = ts.pgpImportPubkey(misc.procgpgkey(info['raw_key'])) if result != 0: @@ -195336,7 +195446,7 @@ index 99039e0..a8a4e80 100644 self.logger.info(_('Key imported successfully')) key_installed = True -@@ -4760,18 +6210,20 @@ class YumBase(depsolve.Depsolve): +@@ -4760,18 +6249,20 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _("Didn't install any keys") if not key_installed: @@ -195362,7 +195472,7 @@ index 99039e0..a8a4e80 100644 def _getAnyKeyForRepo(self, repo, destdir, keyurl_list, is_cakey=False, callback=None): """ -@@ -4788,6 +6240,18 @@ class YumBase(depsolve.Depsolve): +@@ -4788,6 +6279,18 @@ class YumBase(depsolve.Depsolve): """ key_installed = False @@ -195381,7 +195491,7 @@ index 99039e0..a8a4e80 100644 user_cb_fail = False for keyurl in keyurl_list: keys = self._retrievePublicKey(keyurl, repo, getSig=not is_cakey) -@@ -4819,8 +6283,11 @@ class YumBase(depsolve.Depsolve): +@@ -4819,8 +6322,11 @@ class YumBase(depsolve.Depsolve): if not key_installed: self._getKeyImportMessage(info, keyurl, keytype) rc = False @@ -195394,7 +195504,7 @@ index 99039e0..a8a4e80 100644 elif callback: rc = callback({"repo": repo, "userid": info['userid'], "hexkeyid": info['hexkeyid'], "keyurl": keyurl, -@@ -4835,7 +6302,8 @@ class YumBase(depsolve.Depsolve): +@@ -4835,7 +6341,8 @@ class YumBase(depsolve.Depsolve): # Import the key result = misc.import_key_to_pubring(info['raw_key'], info['hexkeyid'], gpgdir=destdir) if not result: @@ -195404,7 +195514,7 @@ index 99039e0..a8a4e80 100644 self.logger.info(_('Key imported successfully')) key_installed = True # write out the key id to imported_cakeys in the repos basedir -@@ -4851,36 +6319,35 @@ class YumBase(depsolve.Depsolve): +@@ -4851,36 +6358,35 @@ class YumBase(depsolve.Depsolve): pass if not key_installed and user_cb_fail: @@ -195457,7 +195567,7 @@ index 99039e0..a8a4e80 100644 self._getAnyKeyForRepo(repo, repo.gpgcadir, repo.gpgcakey, is_cakey=True, callback=callback) def _limit_installonly_pkgs(self): -@@ -4889,7 +6356,7 @@ class YumBase(depsolve.Depsolve): +@@ -4889,7 +6395,7 @@ class YumBase(depsolve.Depsolve): New in 3.2.24: Obey yumdb_info.installonly data. """ def _sort_and_filter_installonly(pkgs): @@ -195466,7 +195576,7 @@ index 99039e0..a8a4e80 100644 using the yumdb. """ ret_beg = [] ret_mid = [] -@@ -4917,6 +6384,10 @@ class YumBase(depsolve.Depsolve): +@@ -4917,6 +6423,10 @@ class YumBase(depsolve.Depsolve): if self.conf.installonly_limit < 1 : return @@ -195477,7 +195587,7 @@ index 99039e0..a8a4e80 100644 toremove = [] # We "probably" want to use either self.ts or self.rpmdb.ts if either -@@ -4926,23 +6397,30 @@ class YumBase(depsolve.Depsolve): +@@ -4926,23 +6436,30 @@ class YumBase(depsolve.Depsolve): # so self.rpmdb.ts should be valid. ts = self.rpmdb.readOnlyTS() (cur_kernel_v, cur_kernel_r) = misc.get_running_kernel_version_release(ts) @@ -195516,7 +195626,7 @@ index 99039e0..a8a4e80 100644 for po in installed: if (po.version, po.release) == (cur_kernel_v, cur_kernel_r): # don't remove running -@@ -4959,19 +6437,22 @@ class YumBase(depsolve.Depsolve): +@@ -4959,19 +6476,22 @@ class YumBase(depsolve.Depsolve): txmbr.depends_on.append(rel) def processTransaction(self, callback=None,rpmTestDisplay=None, rpmDisplay=None): @@ -195552,7 +195662,7 @@ index 99039e0..a8a4e80 100644 if not callback: callback = callbacks.ProcessTransNoOutputCallback() -@@ -5062,8 +6543,8 @@ class YumBase(depsolve.Depsolve): +@@ -5062,8 +6582,8 @@ class YumBase(depsolve.Depsolve): raise Errors.YumRPMCheckError, retmsgs retmsgs = [_('ERROR with transaction check vs depsolve:')] retmsgs.extend(msgs) @@ -195563,7 +195673,7 @@ index 99039e0..a8a4e80 100644 raise Errors.YumRPMCheckError,retmsgs tsConf = {} -@@ -5114,13 +6595,19 @@ class YumBase(depsolve.Depsolve): +@@ -5114,13 +6634,19 @@ class YumBase(depsolve.Depsolve): return results def add_enable_repo(self, repoid, baseurls=[], mirrorlist=None, **kwargs): @@ -195590,7 +195700,7 @@ index 99039e0..a8a4e80 100644 # 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 +6654,15 @@ class YumBase(depsolve.Depsolve): +@@ -5167,9 +6693,15 @@ class YumBase(depsolve.Depsolve): def setCacheDir(self, force=False, tmpdir=None, reuse=True, suffix='/$basearch/$releasever'): @@ -195609,7 +195719,7 @@ index 99039e0..a8a4e80 100644 if not force and os.geteuid() == 0: return True # We are root, not forced, so happy with the global dir. if tmpdir is None: -@@ -5179,7 +6672,7 @@ class YumBase(depsolve.Depsolve): +@@ -5179,7 +6711,7 @@ class YumBase(depsolve.Depsolve): try: cachedir = misc.getCacheDir(tmpdir, reuse) except (IOError, OSError), e: @@ -195618,7 +195728,7 @@ index 99039e0..a8a4e80 100644 cachedir = None if cachedir is None: -@@ -5190,6 +6683,8 @@ class YumBase(depsolve.Depsolve): +@@ -5190,6 +6722,8 @@ class YumBase(depsolve.Depsolve): self.prerepoconf.cachedir = cachedir else: self.repos.setCacheDir(cachedir) @@ -195627,7 +195737,7 @@ index 99039e0..a8a4e80 100644 self.conf.cachedir = cachedir return True # We got a new cache dir -@@ -5220,13 +6715,24 @@ class YumBase(depsolve.Depsolve): +@@ -5220,13 +6754,24 @@ class YumBase(depsolve.Depsolve): self.history.write_addon_data('config-repos', myrepos) def verify_plugins_cb(self, verify_package): @@ -195655,7 +195765,7 @@ index 99039e0..a8a4e80 100644 if self.tsInfo._unresolvedMembers: if auto: self.logger.critical(_("Dependencies not solved. Will not save unresolved transaction.")) -@@ -5234,7 +6740,7 @@ class YumBase(depsolve.Depsolve): +@@ -5234,7 +6779,7 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError(_("Dependencies not solved. Will not save unresolved transaction.")) if not filename: @@ -195664,7 +195774,7 @@ index 99039e0..a8a4e80 100644 fd,filename = tempfile.mkstemp(suffix='.yumtx', prefix=prefix) f = os.fdopen(fd, 'w') else: -@@ -5244,13 +6750,17 @@ class YumBase(depsolve.Depsolve): +@@ -5244,13 +6789,17 @@ class YumBase(depsolve.Depsolve): msg = "%s\n" % self.rpmdb.simpleVersion(main_only=True)[0] msg += "%s\n" % self.ts.getTsFlags() @@ -195685,7 +195795,7 @@ index 99039e0..a8a4e80 100644 msg += "%s\n" % len(self.tsInfo.getMembers()) for txmbr in self.tsInfo.getMembers(): msg += txmbr._dump() -@@ -5260,42 +6770,84 @@ class YumBase(depsolve.Depsolve): +@@ -5260,42 +6809,84 @@ class YumBase(depsolve.Depsolve): except (IOError, OSError), e: self._ts_save_file = None if auto: @@ -195782,7 +195892,7 @@ index 99039e0..a8a4e80 100644 if ignorerpm: msg += _(" ignoring, as requested.") self.logger.critical(_(msg)) -@@ -5318,8 +6870,17 @@ class YumBase(depsolve.Depsolve): +@@ -5318,8 +6909,17 @@ class YumBase(depsolve.Depsolve): numrepos = int(data[2].strip()) repos = [] rindex=3+numrepos @@ -195801,7 +195911,7 @@ index 99039e0..a8a4e80 100644 # pkgs/txmbrs numpkgs = int(data[rindex].strip()) -@@ -5329,6 +6890,7 @@ class YumBase(depsolve.Depsolve): +@@ -5329,6 +6929,7 @@ class YumBase(depsolve.Depsolve): pkgcount = 0 pkgprob = False curpkg = None @@ -195809,7 +195919,7 @@ index 99039e0..a8a4e80 100644 for l in data[pkgstart:]: l = l.rstrip() # our main txmbrs -@@ -5356,6 +6918,7 @@ class YumBase(depsolve.Depsolve): +@@ -5356,6 +6957,7 @@ class YumBase(depsolve.Depsolve): if not ignoremissing: raise Errors.YumBaseError(msg) else: @@ -195817,7 +195927,7 @@ index 99039e0..a8a4e80 100644 self.logger.critical(msg) else: pkgcount += 1 -@@ -5432,12 +6995,18 @@ class YumBase(depsolve.Depsolve): +@@ -5432,12 +7034,18 @@ class YumBase(depsolve.Depsolve): if pkgprob: msg = _("Transaction members, relations are missing or ts has been modified,") if ignoremissing: @@ -195836,7 +195946,7 @@ index 99039e0..a8a4e80 100644 return self.tsInfo.getMembers() def _remove_old_deps(self): -@@ -5470,18 +7039,6 @@ class YumBase(depsolve.Depsolve): +@@ -5470,18 +7078,6 @@ class YumBase(depsolve.Depsolve): if requiring == required: # if they are self-requiring skip them continue @@ -195855,7 +195965,7 @@ index 99039e0..a8a4e80 100644 #for tbi_pkg in self.tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES): # for reqtuple in tbi_pkg.po.requires: # if required.provides_for(reqtuple): -@@ -5533,7 +7090,24 @@ class YumBase(depsolve.Depsolve): +@@ -5533,7 +7129,24 @@ class YumBase(depsolve.Depsolve): # Debugging output self.verbose_logger.log(logginglevels.DEBUG_2, _("%s has revdep %s which was user-installed."), pkg, curpkg) ok_to_remove[pkg] = False @@ -195880,7 +195990,7 @@ index 99039e0..a8a4e80 100644 visited[curpkg] = True all_leaves_visited = True leaves = curpkg.requiring_packages() -@@ -5547,4 +7121,3 @@ class YumBase(depsolve.Depsolve): +@@ -5547,4 +7160,3 @@ class YumBase(depsolve.Depsolve): # Debugging output self.verbose_logger.log(logginglevels.DEBUG_2, _("%s has no user-installed revdeps."), pkg) return False @@ -196554,7 +196664,7 @@ index 65f6d5e..92e87ba 100755 print >> sys.stderr, "newcomps.py: No such file:\'%s\'" % sys.argv[1] sys.exit(1) diff --git a/yum/config.py b/yum/config.py -index d09511f..8eab5bc 100644 +index d09511f..fc1bdc4 100644 --- a/yum/config.py +++ b/yum/config.py @@ -38,22 +38,30 @@ if not _use_iniparse: @@ -197260,7 +197370,7 @@ index d09511f..8eab5bc 100644 installroot = Option('/') config_file_path = Option('/etc/yum/yum.conf') plugins = BoolOption(False) -@@ -625,13 +731,13 @@ class StartupConf(BaseConfig): +@@ -625,15 +731,16 @@ class StartupConf(BaseConfig): persistdir = Option('/var/lib/yum') class YumConf(StartupConf): @@ -197277,8 +197387,11 @@ index d09511f..8eab5bc 100644 + reset_nice = BoolOption(True) cachedir = Option('/var/cache/yum') ++ cashedir = Option('/var/cache/CAShe') -@@ -641,29 +747,33 @@ class YumConf(StartupConf): + keepcache = BoolOption(True) + logfile = Option('/var/log/yum.log') +@@ -641,29 +748,33 @@ class YumConf(StartupConf): commands = ListOption() exclude = ListOption() @@ -197322,7 +197435,7 @@ index d09511f..8eab5bc 100644 alwaysprompt = BoolOption(True) exactarch = BoolOption(True) tolerant = BoolOption(True) -@@ -677,18 +787,35 @@ class YumConf(StartupConf): +@@ -677,33 +788,53 @@ class YumConf(StartupConf): obsoletes = BoolOption(True) showdupesfromrepos = BoolOption(False) enabled = BoolOption(True) @@ -197358,7 +197471,9 @@ index d09511f..8eab5bc 100644 # Time in seconds (1 day). NOTE: This isn't used when using metalinks mirrorlist_expire = SecondsOption(60 * 60 * 24) # XXX rpm_check_debug is unused, left around for API compatibility for now -@@ -697,13 +824,15 @@ class YumConf(StartupConf): + rpm_check_debug = BoolOption(True) + disable_excludes = ListOption() ++ query_install_excludes = BoolOption(True) skip_broken = BoolOption(False) # Note that "instant" is the old behaviour, but group:primary is very # similar but better :). @@ -197377,7 +197492,7 @@ index d09511f..8eab5bc 100644 color = SelectionOption('auto', ('auto', 'never', 'always'), mapper={'on' : 'always', 'yes' : 'always', -@@ -715,22 +844,27 @@ class YumConf(StartupConf): +@@ -715,22 +846,27 @@ class YumConf(StartupConf): color_list_installed_newer = Option('bold,yellow') color_list_installed_reinstall = Option('normal') color_list_installed_extra = Option('bold,red') @@ -197405,7 +197520,7 @@ index d09511f..8eab5bc 100644 history_record = BoolOption(True) history_record_packages = ListOption(['yum', 'rpm']) -@@ -744,18 +878,45 @@ class YumConf(StartupConf): +@@ -744,18 +880,46 @@ class YumConf(StartupConf): loadts_ignoremissing = BoolOption(False) loadts_ignorerpm = BoolOption(False) @@ -197430,6 +197545,7 @@ index d09511f..8eab5bc 100644 + fssnap_devices = ListOption("!*/swap !*/lv_swap " + "glob:/etc/yum/fssnap.d/*.conf", + parse_default=True) ++ fssnap_abort_on_errors = SelectionOption('any', ('broken-setup', 'snapshot-failure', 'any', 'none')) + + depsolve_loop_limit = PositiveIntOption(100, names_of_0=[""]) + @@ -197451,7 +197567,7 @@ index d09511f..8eab5bc 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 +939,12 @@ class YumConf(StartupConf): +@@ -778,14 +942,12 @@ class YumConf(StartupConf): return output class RepoConf(BaseConfig): @@ -197469,7 +197585,7 @@ index d09511f..8eab5bc 100644 ck = self.__cached_keys if not isinstance(self, RepoConf): ck = set() -@@ -797,6 +956,7 @@ class RepoConf(BaseConfig): +@@ -797,6 +959,7 @@ class RepoConf(BaseConfig): name = Option() enabled = Inherit(YumConf.enabled) @@ -197477,7 +197593,7 @@ index d09511f..8eab5bc 100644 baseurl = UrlListOption() mirrorlist = UrlOption() metalink = UrlOption() -@@ -820,42 +980,77 @@ class RepoConf(BaseConfig): +@@ -820,42 +983,77 @@ class RepoConf(BaseConfig): keepalive = Inherit(YumConf.keepalive) enablegroups = Inherit(YumConf.enablegroups) @@ -197566,7 +197682,7 @@ index d09511f..8eab5bc 100644 # ' xemacs syntax hack -@@ -864,6 +1059,12 @@ def readStartupConfig(configfile, root): +@@ -864,6 +1062,12 @@ def readStartupConfig(configfile, root): startupconf.config_file_path = configfile parser = ConfigParser() confpp_obj = ConfigPreProcessor(configfile) @@ -197579,7 +197695,7 @@ index d09511f..8eab5bc 100644 try: parser.readfp(confpp_obj) except ParsingError, e: -@@ -876,25 +1077,29 @@ def readStartupConfig(configfile, root): +@@ -876,25 +1080,29 @@ 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 @@ -197617,7 +197733,7 @@ index d09511f..8eab5bc 100644 yumvars['basearch'] = startupconf.basearch yumvars['arch'] = startupconf.arch yumvars['releasever'] = startupconf.releasever -@@ -915,22 +1120,12 @@ def readMainConfig(startupconf): +@@ -915,22 +1123,12 @@ def readMainConfig(startupconf): ir_path = varReplace(ir_path, yumvars) setattr(yumconf, option, ir_path) @@ -197646,7 +197762,7 @@ index d09511f..8eab5bc 100644 # These can use the above FS yumvars for option in ('cachedir', 'logfile', 'persistdir'): -@@ -956,6 +1151,12 @@ def readMainConfig(startupconf): +@@ -956,6 +1154,12 @@ def readMainConfig(startupconf): return yumconf def readVersionGroupsConfig(configfile="/etc/yum/version-groups.conf"): @@ -197659,7 +197775,7 @@ index d09511f..8eab5bc 100644 parser = ConfigParser() confpp_obj = ConfigPreProcessor(configfile) try: -@@ -970,17 +1171,16 @@ def readVersionGroupsConfig(configfile="/etc/yum/version-groups.conf"): +@@ -970,17 +1174,16 @@ def readVersionGroupsConfig(configfile="/etc/yum/version-groups.conf"): def getOption(conf, section, name, option): @@ -197687,7 +197803,7 @@ index d09511f..8eab5bc 100644 try: val = conf.get(section, name) except (NoSectionError, NoOptionError): -@@ -1010,7 +1210,10 @@ def _getsysver(installroot, distroverpkg): +@@ -1010,7 +1213,10 @@ def _getsysver(installroot, distroverpkg): ts = rpmUtils.transaction.initReadOnlyTransaction(root=installroot) ts.pushVSFlags(~(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)) try: @@ -197699,7 +197815,7 @@ index d09511f..8eab5bc 100644 except TypeError, e: # This is code for "cannot open rpmdb" # this is for pep 352 compliance on python 2.6 and above :( -@@ -1028,25 +1231,44 @@ def _getsysver(installroot, distroverpkg): +@@ -1028,25 +1234,44 @@ def _getsysver(installroot, distroverpkg): if idx.count() == 0: releasever = '$releasever' else: @@ -197755,7 +197871,7 @@ index d09511f..8eab5bc 100644 # b/c repoids can have $values in them we need to map both ways to figure # out which one is which section_id = repo.id -@@ -1054,6 +1276,22 @@ def writeRawRepoFile(repo,only=None): +@@ -1054,6 +1279,22 @@ def writeRawRepoFile(repo,only=None): for sect in ini._sections.keys(): if varReplace(sect, repo.yumvar) == repo.id: section_id = sect @@ -197778,7 +197894,7 @@ index d09511f..8eab5bc 100644 # Updated the ConfigParser with the changed values cfgOptions = repo.cfg.options(repo.id) -@@ -1069,7 +1307,7 @@ def writeRawRepoFile(repo,only=None): +@@ -1069,7 +1310,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 @@ -197787,7 +197903,7 @@ index d09511f..8eab5bc 100644 ovalue = ini[section_id][name] if name not in cfgOptions and option.default == value: -@@ -1080,6 +1318,48 @@ def writeRawRepoFile(repo,only=None): +@@ -1080,6 +1321,48 @@ def writeRawRepoFile(repo,only=None): fp.write(str(ini)) fp.close() @@ -198997,10 +199113,10 @@ index bca9651..00c17ad 100644 else: diff --git a/yum/fssnapshots.py b/yum/fssnapshots.py new file mode 100755 -index 0000000..e912ea1 +index 0000000..9af252d --- /dev/null +++ b/yum/fssnapshots.py -@@ -0,0 +1,347 @@ +@@ -0,0 +1,345 @@ + + +import os @@ -199058,9 +199174,6 @@ index 0000000..e912ea1 + names = lvm.listVgNames() + + if not names: # Could be just broken... -+ if not os.path.exists("/sbin/lvm"): -+ return [] # Minimal install etc. -+ + p = subprocess.Popen(["/sbin/lvm", "vgs", "-o", "vg_name"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + err = p.wait() @@ -199149,7 +199262,8 @@ index 0000000..e912ea1 + devices = [] + + self.version = _ver -+ self.available = bool(lvm) ++ # Parts of the API seem to work even when lvm is not actually installed, hence the path test ++ self.available = bool(lvm and os.path.exists("/sbin/lvm")) + self.postfix_static = "_yum_" + self._postfix = None + self._root = root @@ -199349,7 +199463,7 @@ index 0000000..e912ea1 + + return ret diff --git a/yum/history.py b/yum/history.py -index 5385bd1..fd80191 100644 +index 5385bd1..d08837c 100644 --- a/yum/history.py +++ b/yum/history.py @@ -20,6 +20,7 @@ @@ -199544,7 +199658,18 @@ index 5385bd1..fd80191 100644 # make an addon path for where we're going to stick # random additional history info - probably from plugins and what-not -@@ -638,13 +741,15 @@ class YumHistory: +@@ -635,16 +738,26 @@ class YumHistory: + # it's deep yum stuff and there should only be one yum. + executeSQL(self._conn.cursor(), "PRAGMA locking_mode = EXCLUSIVE") + ++ # See: http://sqlite.org/pragma.html#pragma_synchronous ++ # It's far from the end of the world if the history DB dies, and ++ # NORMAL is very safe already. FULL means that verifyTransaction() ++ # does an fsync() for each package, which sucks. ++ executeSQL(self._conn.cursor(), "PRAGMA synchronous = NORMAL") ++ # Could/should do this when installroot'ing? ++ # executeSQL(self._conn.cursor(), "PRAGMA synchronous = OFF") ++ return self._conn.cursor() def _commit(self): return self._conn.commit() @@ -199561,7 +199686,7 @@ index 5385bd1..fd80191 100644 cur = self._get_cursor() executeSQL(cur, """SELECT pkgtupid, checksum FROM pkgtups WHERE name=? AND arch=? AND -@@ -659,6 +764,9 @@ class YumHistory: +@@ -659,6 +772,9 @@ class YumHistory: if checksum == sql_checksum: return sql_pkgtupid @@ -199571,7 +199696,7 @@ index 5385bd1..fd80191 100644 (n,a,e,v,r) = pkgtup (n,a,e,v,r) = (to_unicode(n),to_unicode(a), to_unicode(e),to_unicode(v),to_unicode(r)) -@@ -674,23 +782,28 @@ class YumHistory: +@@ -674,23 +790,28 @@ class YumHistory: (name, arch, epoch, version, release) VALUES (?, ?, ?, ?, ?)""", (n,a,e,v,r)) return cur.lastrowid @@ -199608,7 +199733,7 @@ index 5385bd1..fd80191 100644 @staticmethod def txmbr2state(txmbr): -@@ -984,7 +1097,8 @@ class YumHistory: +@@ -984,7 +1105,8 @@ class YumHistory: ORDER BY name ASC, epoch ASC""", (tid,)) ret = [] for row in cur: @@ -199618,7 +199743,7 @@ index 5385bd1..fd80191 100644 ret.append(obj) return ret def _old_data_pkgs(self, tid): -@@ -998,7 +1112,7 @@ class YumHistory: +@@ -998,7 +1120,7 @@ class YumHistory: ret = [] for row in cur: obj = YumHistoryPackageState(row[0],row[1],row[2],row[3],row[4], @@ -199627,7 +199752,7 @@ index 5385bd1..fd80191 100644 obj.done = row[6] == 'TRUE' obj.state_installed = None if _sttxt2stcode[obj.state] in TS_INSTALL_STATES: -@@ -1018,7 +1132,8 @@ class YumHistory: +@@ -1018,7 +1140,8 @@ class YumHistory: ORDER BY name ASC, epoch ASC""", (tid,)) ret = [] for row in cur: @@ -199637,7 +199762,7 @@ index 5385bd1..fd80191 100644 ret.append(obj) return ret def _old_prob_pkgs(self, rpid): -@@ -1032,7 +1147,8 @@ class YumHistory: +@@ -1032,7 +1155,8 @@ class YumHistory: ORDER BY name ASC, epoch ASC""", (rpid,)) ret = [] for row in cur: @@ -199647,7 +199772,7 @@ index 5385bd1..fd80191 100644 obj.main = row[6] == 'TRUE' ret.append(obj) return ret -@@ -1091,7 +1207,11 @@ class YumHistory: +@@ -1091,7 +1215,11 @@ class YumHistory: if tids and len(tids) <= yum.constants.PATTERNS_INDEXED_MAX: params = tids = list(set(tids)) sql += " WHERE tid IN (%s)" % ", ".join(['?'] * len(tids)) @@ -199660,7 +199785,7 @@ index 5385bd1..fd80191 100644 if limit is not None: sql += " LIMIT " + str(limit) executeSQL(cur, sql, params) -@@ -1151,6 +1271,127 @@ class YumHistory: +@@ -1151,6 +1279,127 @@ class YumHistory: assert len(ret) == 1 return ret[0] @@ -199788,7 +199913,7 @@ index 5385bd1..fd80191 100644 def _yieldSQLDataList(self, patterns, fields, ignore_case): """Yields all the package data for the given params. """ -@@ -1182,6 +1423,17 @@ class YumHistory: +@@ -1182,6 +1431,17 @@ class YumHistory: if cur is None: return set() @@ -199806,7 +199931,7 @@ index 5385bd1..fd80191 100644 data = _setupHistorySearchSQL(patterns, ignore_case) (need_full, npatterns, fields, names) = data -@@ -1220,6 +1472,48 @@ class YumHistory: +@@ -1220,6 +1480,48 @@ class YumHistory: tids.add(row[0]) return tids @@ -199855,7 +199980,7 @@ index 5385bd1..fd80191 100644 _update_ops_2 = ['''\ \ CREATE TABLE trans_skip_pkgs ( -@@ -1307,6 +1601,8 @@ class YumHistory: +@@ -1307,6 +1609,8 @@ class YumHistory: self._cached_updated_2 = True return True @@ -199864,7 +199989,7 @@ index 5385bd1..fd80191 100644 def _create_db_file(self): """ Create a new history DB file, populating tables etc. """ -@@ -1321,8 +1617,10 @@ class YumHistory: +@@ -1321,8 +1625,10 @@ class YumHistory: if os.path.exists(_db_file + '-journal'): os.rename(_db_file + '-journal', _db_file + '-journal.old') self._db_file = _db_file @@ -199876,7 +200001,7 @@ index 5385bd1..fd80191 100644 # make them default to 0600 - sysadmin can change it later # if they want fo = os.open(self._db_file, os.O_CREAT, 0600) -@@ -1374,7 +1672,10 @@ class YumHistory: +@@ -1374,7 +1680,10 @@ class YumHistory: cur.execute(op) for op in self._update_ops_2: cur.execute(op) @@ -200801,7 +200926,7 @@ index 4af563a..a702ac1 100644 self.obsoletes = {} #obs[obsoletename] = [pkg1, pkg2, pkg3] #the package lists are packages that obsolete the key name diff --git a/yum/packages.py b/yum/packages.py -index 5ef9951..b219ada 100644 +index 5ef9951..8365f16 100644 --- a/yum/packages.py +++ b/yum/packages.py @@ -38,6 +38,7 @@ import struct @@ -201073,7 +201198,25 @@ index 5ef9951..b219ada 100644 # Hacky way to get rid of version numbers... ix = val.find('> ') if ix != -1: -@@ -859,7 +921,8 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -843,6 +905,17 @@ class YumAvailablePackage(PackageObject, RpmBase): + return self.checksums[0][1] + checksum = property(_checksum) + ++ ++ def _get_cashe(self): ++ if not hasattr(self, '_cashe_obj'): ++ if hasattr(self.repo, '_cashe') and self.repo._cashe is not None: ++ (csum_type, csum) = self.returnIdSum() ++ self._cashe_obj = self.repo._cashe.get(csum_type, csum) ++ else: ++ self._cashe_obj = None ++ return self._cashe_obj ++ _cashe = property(_get_cashe) ++ + def getDiscNum(self): + if self.basepath is None: + return None +@@ -859,7 +932,8 @@ class YumAvailablePackage(PackageObject, RpmBase): try: hdr = rpmUtils.miscutils.hdrFromPackage(ts, rpmfile) except rpmUtils.RpmUtilsError: @@ -201083,7 +201226,7 @@ index 5ef9951..b219ada 100644 return hdr def returnLocalHeader(self): -@@ -871,9 +934,11 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -871,9 +945,11 @@ class YumAvailablePackage(PackageObject, RpmBase): hlist = rpm.readHeaderListFromFile(self.localHdr()) hdr = hlist[0] except (rpm.error, IndexError): @@ -201097,7 +201240,50 @@ index 5ef9951..b219ada 100644 return hdr -@@ -1063,10 +1128,10 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -896,7 +972,7 @@ class YumAvailablePackage(PackageObject, RpmBase): + + return self.hdrpath + +- def verifyLocalPkg(self): ++ def verifyLocalPkg(self, from_cashe=False): + """check the package checksum vs the localPkg + return True if pkg is good, False if not""" + +@@ -905,7 +981,10 @@ class YumAvailablePackage(PackageObject, RpmBase): + try: + nst = os.stat(self.localPkg()) + except OSError, e: ++ if self._cashe and self._cashe.load(self.localPkg()): ++ return self.verifyLocalPkg(from_cashe=True) + return False ++ + if (hasattr(self, '_verify_local_pkg_cache') and + self._verify_local_pkg_cache): + ost = self._verify_local_pkg_cache +@@ -921,12 +1000,22 @@ class YumAvailablePackage(PackageObject, RpmBase): + filesum = misc.checksum(csum_type, self.localPkg(), + datasize=self.packagesize) + except Errors.MiscError: ++ if from_cashe: ++ self._cashe.unlink() ++ elif nst.st_size >= self.packagesize: ++ return self.verifyLocalPkg() # Try: cashe + return False + + if filesum != csum: ++ if from_cashe: ++ self._cashe.unlink() ++ elif nst.st_size >= self.packagesize: ++ return self.verifyLocalPkg() # Try: cashe + return False + + self._verify_local_pkg_cache = nst ++ if not from_cashe and self._cashe and not self._cashe.exists: ++ self._cashe.save(self.localPkg()) + + return True + +@@ -1063,10 +1152,10 @@ class YumAvailablePackage(PackageObject, RpmBase): packager = url = '' if self.packager: @@ -201110,7 +201296,7 @@ index 5ef9951..b219ada 100644 (csum_type, csum, csumid) = self.checksums[0] msg = """ %s -@@ -1080,10 +1145,10 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1080,10 +1169,10 @@ class YumAvailablePackage(PackageObject, RpmBase):