From d24df21f1603734e81348a20cf2bf9f8c32a2fe5 Mon Sep 17 00:00:00 2001 From: James Antill Date: Thu, 30 Aug 2012 10:33:18 -0400 Subject: [PATCH 001/174] update to latest HEAD. - Fix rel-eng problems when repo.repofile is None. --- yum-HEAD.patch | 155 ++++++++++++++++++++++++++++++------------------- yum.spec | 6 +- 2 files changed, 99 insertions(+), 62 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index 05b65b1..4026087 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -2553,7 +2553,7 @@ index 1a8202a..15a8345 100644 .IP "\fB\-\-setopt=option=value\fP" Set any config option in yum config or repo files. For options in the global diff --git a/docs/yum.conf.5 b/docs/yum.conf.5 -index 515aa73..b456074 100644 +index 515aa73..01facf8 100644 --- a/docs/yum.conf.5 +++ b/docs/yum.conf.5 @@ -114,15 +114,27 @@ are causing problems from the transaction. @@ -2665,7 +2665,27 @@ index 515aa73..b456074 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 -@@ -593,8 +654,50 @@ See color_list_installed_older for possible values. +@@ -480,6 +541,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 ++\fBmddownloadpolicy \fR ++You can select which kinds of repodata you would prefer yum to download: ++ ++`sqlite' - Download the .sqlite files, if available. This is currently slightly ++faster, once they are downloaded. However these files tend to be bigger, and ++thus. take longer to download. ++ ++`sqlite' - Download the .XML files, which yum will do anyway as a fallback on ++the other options. These files tend to be smaller, but they require ++parsing/converting locally after download and some aditional checks are ++performed on them each time they are used. ++ ++.IP + \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, +@@ -593,8 +667,50 @@ See color_list_installed_older for possible values. When removing packages (by removal, update or obsoletion) go through each package's dependencies. If any of them are no longer required by any other package then also mark them to be removed. @@ -2716,7 +2736,7 @@ index 515aa73..b456074 100644 .SH "[repository] OPTIONS" -@@ -755,6 +858,11 @@ repository. +@@ -755,6 +871,11 @@ repository. Overrides the \fBbandwidth\fR option from the [main] section for this repository. @@ -2728,7 +2748,7 @@ index 515aa73..b456074 100644 .IP \fBsslcacert \fR -@@ -776,6 +884,10 @@ repository. +@@ -776,6 +897,10 @@ repository. Overrides the \fBsslclientkey\fR option from the [main] section for this repository. @@ -2739,7 +2759,7 @@ index 515aa73..b456074 100644 .IP \fBmetadata_expire \fR -@@ -824,7 +936,11 @@ as greater/less than any other. defaults to 1000 +@@ -824,7 +949,11 @@ 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. @@ -155222,7 +155242,7 @@ index 65f6d5e..08e66b9 100755 print category.name for group in category.groups: diff --git a/yum/config.py b/yum/config.py -index d09511f..b81020f 100644 +index d09511f..74be397 100644 --- a/yum/config.py +++ b/yum/config.py @@ -45,15 +45,18 @@ from misc import get_uuid, read_in_items_from_dot_dir @@ -155493,12 +155513,12 @@ index d09511f..b81020f 100644 class PositiveIntOption(IntOption): - +- """ +- An option representing a positive integer value, where 0 can have a special +- represention. + """An option representing a positive integer value, where 0 can + have a special representation. """ -- An option representing a positive integer value, where 0 can have a special -- represention. -- """ - def __init__(self, default=None, range_min=0, range_max=None, names_of_0=None): @@ -155689,11 +155709,11 @@ index d09511f..b81020f 100644 - Invalid inputs: -10, -0.1, 45.6L, 123Mb - - Return value will always be an integer +- +- 1k = 1024 bytes. + Valid inputs: 100, 123M, 45.6k, 12.4G, 100K, 786.3, 0. + Invalid inputs: -10, -0.1, 45.6L, 123Mb. -- 1k = 1024 bytes. -- - ValueError will be raised if the option couldn't be parsed. + :param s: the string to parse + :return: the number of bytes represented by *s* @@ -156185,7 +156205,7 @@ index d09511f..b81020f 100644 try: val = conf.get(section, name) except (NoSectionError, NoOptionError): -@@ -1028,23 +1159,19 @@ def _getsysver(installroot, distroverpkg): +@@ -1028,25 +1159,28 @@ def _getsysver(installroot, distroverpkg): if idx.count() == 0: releasever = '$releasever' else: @@ -156212,10 +156232,20 @@ index d09511f..b81020f 100644 if not _use_iniparse: - return + return None ++ ++ if not hasattr(repo, 'repofile') or not repo.repofile: ++ return None ++ ++ try: ++ ini = INIConfig(open(repo.repofile)) ++ except: ++ return None - ini = INIConfig(open(repo.repofile)) +- ini = INIConfig(open(repo.repofile)) # b/c repoids can have $values in them we need to map both ways to figure -@@ -1054,6 +1181,19 @@ def writeRawRepoFile(repo,only=None): + # out which one is which + section_id = repo.id +@@ -1054,6 +1188,19 @@ def writeRawRepoFile(repo,only=None): for sect in ini._sections.keys(): if varReplace(sect, repo.yumvar) == repo.id: section_id = sect @@ -156235,7 +156265,7 @@ index d09511f..b81020f 100644 # Updated the ConfigParser with the changed values cfgOptions = repo.cfg.options(repo.id) -@@ -1069,7 +1209,7 @@ def writeRawRepoFile(repo,only=None): +@@ -1069,7 +1216,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 @@ -157642,7 +157672,7 @@ index 0000000..6a04f3a + + return returns.values() diff --git a/yum/metalink.py b/yum/metalink.py -index aaa4f25..51895fd 100755 +index aaa4f25..61aa586 100755 --- a/yum/metalink.py +++ b/yum/metalink.py @@ -180,6 +180,7 @@ class MetaLinkRepoMD: @@ -157670,12 +157700,12 @@ index aaa4f25..51895fd 100755 + if host in self._host2mc: continue - hosts.add(host) -+ self._host2mc[host] = mirror.max_connections ++ self._host2mc[host] = mirror else: continue diff --git a/yum/misc.py b/yum/misc.py -index 2f6ddfe..4cae42b 100644 +index 2f6ddfe..a39a222 100644 --- a/yum/misc.py +++ b/yum/misc.py @@ -8,6 +8,7 @@ import os @@ -157721,16 +157751,19 @@ index 2f6ddfe..4cae42b 100644 except KeyError: return None # if it returns None then, well, it's bollocksed -@@ -746,6 +761,8 @@ def _decompress_chunked(source, dest, ztype): +@@ -744,8 +759,9 @@ def _decompress_chunked(source, dest, ztype): + while True: + try: data = s_fn.read(1024000) - except IOError: - break -+ except EOFError: -+ break +- except IOError: +- break ++ except (OSError, IOError, EOFError), e: ++ msg = "Error reading from file %s: %s" % (source, str(e)) ++ raise Errors.MiscError, msg if not data: break -@@ -940,14 +957,16 @@ def unlink_f(filename): +@@ -940,14 +956,16 @@ def unlink_f(filename): if e.errno != errno.ENOENT: raise @@ -157751,7 +157784,7 @@ index 2f6ddfe..4cae42b 100644 def _getloginuid(): """ Get the audit-uid/login-uid, if available. None is returned if there -@@ -992,9 +1011,17 @@ def setup_locale(override_codecs=True, override_time=False): +@@ -992,9 +1010,17 @@ def setup_locale(override_codecs=True, override_time=False): locale.setlocale(locale.LC_ALL, 'C') if override_codecs: @@ -157772,7 +157805,7 @@ index 2f6ddfe..4cae42b 100644 def get_my_lang_code(): -@@ -1105,17 +1132,28 @@ def decompress(filename, dest=None, fn_only=False, check_timestamps=False): +@@ -1105,17 +1131,28 @@ def decompress(filename, dest=None, fn_only=False, check_timestamps=False): out = filename.replace('.xz', '') else: @@ -159301,7 +159334,7 @@ index 2cb1acb..0586c1c 100644 for pkg in un['pkglist']: for filedata in pkg['packages']: diff --git a/yum/yumRepo.py b/yum/yumRepo.py -index e5e9ece..fc2614e 100644 +index e5e9ece..bbcb2b8 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -20,10 +20,12 @@ import time @@ -159554,7 +159587,7 @@ index e5e9ece..fc2614e 100644 if proxy_string is not None: self._proxy_dict['http'] = proxy_string -@@ -483,13 +560,26 @@ class YumRepository(Repository, config.RepoConf): +@@ -483,13 +560,30 @@ class YumRepository(Repository, config.RepoConf): ugopts = self._default_grabopts() self._grabfunc = URLGrabber(progress_obj=self.callback, @@ -159565,12 +159598,16 @@ index e5e9ece..fc2614e 100644 reget='simple', **ugopts) + def add_mc(url): -+ host = urlparse.urlsplit(url).netloc ++ host = urlparse.urlsplit(url).netloc.split('@')[-1] + mc = self.metalink_data._host2mc.get(host) -+ if mc > 0: ++ if mc: + url = { + 'mirror': misc.to_utf8(url), -+ 'kwargs': { 'max_connections': mc }, ++ 'kwargs': { ++ 'max_connections': mc.max_connections, ++ 'preference': mc.preference, ++ 'private': mc.private, ++ }, + } + return url + urls = self.urls @@ -159582,7 +159619,7 @@ index e5e9ece..fc2614e 100644 failure_callback=self.mirror_failure_obj) def _default_grabopts(self, cache=True): -@@ -499,6 +589,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -499,6 +593,7 @@ class YumRepository(Repository, config.RepoConf): 'throttle': self.throttle, 'proxies': self.proxy_dict, 'timeout': self.timeout, @@ -159590,7 +159627,7 @@ index e5e9ece..fc2614e 100644 'http_headers': tuple(self.__headersListFromDict(cache=cache)), 'ssl_verify_peer': self.sslverify, 'ssl_verify_host': self.sslverify, -@@ -714,10 +805,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -714,10 +809,10 @@ class YumRepository(Repository, config.RepoConf): local = self.metalink_filename + '.tmp' if not self._metalinkCurrent(): url = misc.to_utf8(self.metalink) @@ -159599,11 +159636,11 @@ index e5e9ece..fc2614e 100644 try: ug = URLGrabber(progress_obj = self.callback, **ugopts) - result = ug.urlgrab(url, local, text=self.id + "/metalink") -+ result = ug.urlgrab(url, local, text=str(self) +"/metalink") ++ result = ug.urlgrab(url, local, text="%s/metalink" % self) except urlgrabber.grabber.URLGrabError, e: if not os.path.exists(self.metalink_filename): -@@ -751,7 +842,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -751,7 +846,7 @@ class YumRepository(Repository, config.RepoConf): def _getFile(self, url=None, relative=None, local=None, start=None, end=None, copy_local=None, checkfunc=None, text=None, reget='simple', @@ -159612,7 +159649,7 @@ index e5e9ece..fc2614e 100644 """retrieve file from the mirrorgroup for the repo relative to local, optionally get range from start to end, also optionally retrieve from a specific baseurl""" -@@ -768,7 +859,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -768,7 +863,7 @@ class YumRepository(Repository, config.RepoConf): if local is None or relative is None: raise Errors.RepoError, \ @@ -159621,7 +159658,7 @@ index e5e9ece..fc2614e 100644 if self.cache == 1: if os.path.exists(local): # FIXME - we should figure out a way -@@ -796,6 +887,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -796,6 +891,16 @@ class YumRepository(Repository, config.RepoConf): except Errors.MediaError, e: verbose_logger.log(logginglevels.DEBUG_2, "Error getting package from media; falling back to url %s" %(e,)) @@ -159638,7 +159675,7 @@ index e5e9ece..fc2614e 100644 if url and scheme != "media": ugopts = self._default_grabopts(cache=cache) ug = URLGrabber(progress_obj = self.callback, -@@ -815,14 +916,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -815,14 +920,11 @@ class YumRepository(Repository, config.RepoConf): range=(start, end), ) except URLGrabError, e: @@ -159655,7 +159692,7 @@ index e5e9ece..fc2614e 100644 else: -@@ -835,19 +933,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -835,19 +937,18 @@ class YumRepository(Repository, config.RepoConf): reget = reget, checkfunc=checkfunc, http_headers=headers, @@ -159681,7 +159718,7 @@ index e5e9ece..fc2614e 100644 remote = package.relativepath local = package.localPkg() basepath = package.basepath -@@ -857,15 +954,26 @@ class YumRepository(Repository, config.RepoConf): +@@ -857,15 +958,26 @@ class YumRepository(Repository, config.RepoConf): return local misc.unlink_f(local) @@ -159709,7 +159746,7 @@ index e5e9ece..fc2614e 100644 def getHeader(self, package, checkfunc = None, reget = 'simple', cache = True): -@@ -1020,7 +1128,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1020,7 +1132,7 @@ class YumRepository(Repository, config.RepoConf): if grab_can_fail: return None raise Errors.RepoError, 'Error downloading file %s: %s' % (local, e) @@ -159718,7 +159755,7 @@ index e5e9ece..fc2614e 100644 misc.unlink_f(tfname) if grab_can_fail: return None -@@ -1260,6 +1368,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1260,6 +1372,9 @@ class YumRepository(Repository, config.RepoConf): return True def _check_db_version(self, mdtype, repoXML=None): @@ -159728,7 +159765,7 @@ index e5e9ece..fc2614e 100644 if repoXML is None: repoXML = self.repoXML if mdtype in repoXML.repoData: -@@ -1277,11 +1388,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -1277,11 +1392,11 @@ class YumRepository(Repository, config.RepoConf): return None if not file_check: @@ -159743,7 +159780,7 @@ index e5e9ece..fc2614e 100644 if not os.path.exists(local): local = misc.decompress(local, fn_only=True) compressed = True -@@ -1302,6 +1413,17 @@ class YumRepository(Repository, config.RepoConf): +@@ -1302,6 +1417,17 @@ class YumRepository(Repository, config.RepoConf): into the delete list, this means metadata can change filename without us leaking it. """ @@ -159761,7 +159798,7 @@ index e5e9ece..fc2614e 100644 def _mdtype_eq(omdtype, odata, nmdtype, ndata): """ Check if two returns from _get_mdtype_data() are equal. """ if ndata is None: -@@ -1321,6 +1443,14 @@ class YumRepository(Repository, config.RepoConf): +@@ -1321,6 +1447,14 @@ class YumRepository(Repository, config.RepoConf): return True all_mdtypes = self.retrieved.keys() @@ -159776,7 +159813,7 @@ index e5e9ece..fc2614e 100644 if mdtypes is None: mdtypes = all_mdtypes -@@ -1333,8 +1463,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1333,8 +1467,7 @@ class YumRepository(Repository, config.RepoConf): # Inited twice atm. ... sue me self._oldRepoMDData['new_MD_files'] = [] @@ -159786,7 +159823,7 @@ index e5e9ece..fc2614e 100644 for mdtype in all_mdtypes: (nmdtype, ndata) = self._get_mdtype_data(mdtype) -@@ -1371,43 +1500,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -1371,43 +1504,16 @@ class YumRepository(Repository, config.RepoConf): # No old repomd data, but we might still have uncompressed MD if self._groupCheckDataMDValid(ndata, nmdtype, mdtype): continue @@ -159835,7 +159872,7 @@ index e5e9ece..fc2614e 100644 def _groupLoadRepoXML(self, text=None, mdtypes=None): """ Retrieve the new repomd.xml from the repository, then check it -@@ -1421,7 +1523,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1421,7 +1527,7 @@ class YumRepository(Repository, config.RepoConf): self._commonRetrieveDataMD(mdtypes) def _mdpolicy2mdtypes(self): @@ -159844,7 +159881,7 @@ index e5e9ece..fc2614e 100644 'group:primary' : ['primary'], 'group:small' : ["primary", "updateinfo"], 'group:main' : ["primary", "group", "filelists", -@@ -1436,6 +1538,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1436,6 +1542,7 @@ class YumRepository(Repository, config.RepoConf): if not mdtypes or 'group:all' in mdtypes: mdtypes = None else: @@ -159852,7 +159889,7 @@ index e5e9ece..fc2614e 100644 mdtypes = sorted(list(mdtypes)) return mdtypes -@@ -1451,12 +1554,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1451,12 +1558,7 @@ class YumRepository(Repository, config.RepoConf): def _getRepoXML(self): if self._repoXML: return self._repoXML @@ -159866,7 +159903,7 @@ index e5e9ece..fc2614e 100644 return self._repoXML -@@ -1480,7 +1578,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1480,7 +1582,7 @@ class YumRepository(Repository, config.RepoConf): result = self._getFile(relative='repodata/repomd.xml.asc', copy_local=1, local = sigfile, @@ -159875,7 +159912,7 @@ index e5e9ece..fc2614e 100644 reget=None, checkfunc=None, cache=self.http_caching == 'all', -@@ -1514,7 +1612,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1514,7 +1616,7 @@ class YumRepository(Repository, config.RepoConf): return self._checkMD(fn, mdtype, openchecksum) def _checkMD(self, fn, mdtype, openchecksum=False, @@ -159884,7 +159921,7 @@ index e5e9ece..fc2614e 100644 """ Internal function, use .checkMD() from outside yum. """ thisdata = data # So the argument name is nicer -@@ -1537,6 +1635,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -1537,6 +1639,18 @@ class YumRepository(Repository, config.RepoConf): if size is not None: size = int(size) @@ -159903,7 +159940,7 @@ index e5e9ece..fc2614e 100644 try: # get the local checksum l_csum = self._checksum(r_ctype, file, datasize=size) except Errors.RepoError, e: -@@ -1551,15 +1661,13 @@ class YumRepository(Repository, config.RepoConf): +@@ -1551,15 +1665,13 @@ class YumRepository(Repository, config.RepoConf): return None raise URLGrabError(-1, 'Metadata file does not match checksum') @@ -159920,7 +159957,7 @@ index e5e9ece..fc2614e 100644 """ Internal function, use .retrieveMD() from outside yum. """ # Note that this can raise Errors.RepoMDError if mdtype doesn't exist # for this repo. -@@ -1597,8 +1705,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -1597,8 +1709,10 @@ class YumRepository(Repository, config.RepoConf): return local # it's the same return the local one try: @@ -159933,7 +159970,7 @@ index e5e9ece..fc2614e 100644 if thisdata.size is None: reget = None else: -@@ -1613,8 +1723,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1613,8 +1727,9 @@ class YumRepository(Repository, config.RepoConf): checkfunc=checkfunc, text=text, cache=self.http_caching == 'all', @@ -159945,7 +159982,7 @@ index e5e9ece..fc2614e 100644 if retrieve_can_fail: return None raise -@@ -1624,7 +1735,6 @@ class YumRepository(Repository, config.RepoConf): +@@ -1624,7 +1739,6 @@ class YumRepository(Repository, config.RepoConf): raise Errors.RepoError, \ "Could not retrieve %s matching remote checksum from %s" % (local, self) else: @@ -159953,7 +159990,7 @@ index e5e9ece..fc2614e 100644 return local -@@ -1646,13 +1756,21 @@ class YumRepository(Repository, config.RepoConf): +@@ -1646,13 +1760,21 @@ class YumRepository(Repository, config.RepoConf): def getGroups(self): """gets groups and returns group file path for the repository, if there @@ -159978,7 +160015,7 @@ index e5e9ece..fc2614e 100644 self._callbacks_changed = True def setFailureObj(self, failure_obj): -@@ -1681,7 +1799,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1681,7 +1803,7 @@ class YumRepository(Repository, config.RepoConf): print "Could not read mirrorlist %s, error was \n%s" %(url, e) content = [] for line in content: diff --git a/yum.spec b/yum.spec index fa49208..48d9bf8 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 37%{?dist} +Release: 38%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -315,9 +315,9 @@ exit 0 %endif %changelog -* Wed Aug 29 2012 James Antill - 3.4.3-37 +* Thu Aug 30 2012 James Antill - 3.4.3-38 - update to latest HEAD. -- Fix problem on metalink downloads due to weird python issue. +- Fix rel-eng problems when repo.repofile is None. * Tue Aug 28 2012 James Antill - 3.4.3-36 - update to latest HEAD. From 83a026313fbd26cefdce88d52631bb31898d1e8c Mon Sep 17 00:00:00 2001 From: James Antill Date: Thu, 30 Aug 2012 16:31:59 -0400 Subject: [PATCH 002/174] update to latest HEAD. - Fix rel-eng problems when repo.repofile is None. - Don't statvfs when we aren't going to copy. --- yum-HEAD.patch | 65 +++++++++++++++++++++++++++++--------------------- yum.spec | 5 ++-- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index 4026087..39fe263 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -96,7 +96,7 @@ index 2f6154e..2e5a052 100644 diff --git a/cli.py b/cli.py old mode 100644 new mode 100755 -index 6056d38..c7d89a1 +index 6056d38..adc3516 --- a/cli.py +++ b/cli.py @@ -25,7 +25,7 @@ import sys @@ -1577,7 +1577,17 @@ index 6056d38..c7d89a1 self._checkAbsInstallRoot(opts) # If the conf file is inside the installroot - use that. # otherwise look for it in the normal root -@@ -1713,6 +2264,10 @@ class YumOptionParser(OptionParser): +@@ -1701,6 +2252,9 @@ class YumOptionParser(OptionParser): + group.add_option("--showduplicates", dest="showdupesfromrepos", + action="store_true", + help=_("show duplicates, in repos, in list/search commands")) ++ group.add_option("--show-duplicates", dest="showdupesfromrepos", ++ action="store_true", ++ help=SUPPRESS_HELP) + group.add_option("-e", "--errorlevel", dest="errorlevel", default=None, + help=_("error output level"), type='int', + metavar='[error level]') +@@ -1713,6 +2267,10 @@ class YumOptionParser(OptionParser): help=_("verbose operation")) group.add_option("-y", "--assumeyes", dest="assumeyes", action="store_true", help=_("answer yes for all questions")) @@ -159334,7 +159344,7 @@ index 2cb1acb..0586c1c 100644 for pkg in un['pkglist']: for filedata in pkg['packages']: diff --git a/yum/yumRepo.py b/yum/yumRepo.py -index e5e9ece..bbcb2b8 100644 +index e5e9ece..f834aec 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -20,10 +20,12 @@ import time @@ -159658,11 +159668,12 @@ index e5e9ece..bbcb2b8 100644 if self.cache == 1: if os.path.exists(local): # FIXME - we should figure out a way -@@ -796,6 +891,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -796,6 +891,17 @@ class YumRepository(Repository, config.RepoConf): except Errors.MediaError, e: verbose_logger.log(logginglevels.DEBUG_2, "Error getting package from media; falling back to url %s" %(e,)) -+ if size: ++ if size and (self.copy_local or not url or ++ not (url.startswith("/") or url.startswith("file:"))): + dirstat = os.statvfs(os.path.dirname(local)) + avail = dirstat.f_bavail * dirstat.f_bsize + if avail < long(size): @@ -159675,7 +159686,7 @@ index e5e9ece..bbcb2b8 100644 if url and scheme != "media": ugopts = self._default_grabopts(cache=cache) ug = URLGrabber(progress_obj = self.callback, -@@ -815,14 +920,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -815,14 +921,11 @@ class YumRepository(Repository, config.RepoConf): range=(start, end), ) except URLGrabError, e: @@ -159692,7 +159703,7 @@ index e5e9ece..bbcb2b8 100644 else: -@@ -835,19 +937,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -835,19 +938,18 @@ class YumRepository(Repository, config.RepoConf): reget = reget, checkfunc=checkfunc, http_headers=headers, @@ -159718,7 +159729,7 @@ index e5e9ece..bbcb2b8 100644 remote = package.relativepath local = package.localPkg() basepath = package.basepath -@@ -857,15 +958,26 @@ class YumRepository(Repository, config.RepoConf): +@@ -857,15 +959,26 @@ class YumRepository(Repository, config.RepoConf): return local misc.unlink_f(local) @@ -159746,7 +159757,7 @@ index e5e9ece..bbcb2b8 100644 def getHeader(self, package, checkfunc = None, reget = 'simple', cache = True): -@@ -1020,7 +1132,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1020,7 +1133,7 @@ class YumRepository(Repository, config.RepoConf): if grab_can_fail: return None raise Errors.RepoError, 'Error downloading file %s: %s' % (local, e) @@ -159755,7 +159766,7 @@ index e5e9ece..bbcb2b8 100644 misc.unlink_f(tfname) if grab_can_fail: return None -@@ -1260,6 +1372,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1260,6 +1373,9 @@ class YumRepository(Repository, config.RepoConf): return True def _check_db_version(self, mdtype, repoXML=None): @@ -159765,7 +159776,7 @@ index e5e9ece..bbcb2b8 100644 if repoXML is None: repoXML = self.repoXML if mdtype in repoXML.repoData: -@@ -1277,11 +1392,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -1277,11 +1393,11 @@ class YumRepository(Repository, config.RepoConf): return None if not file_check: @@ -159780,7 +159791,7 @@ index e5e9ece..bbcb2b8 100644 if not os.path.exists(local): local = misc.decompress(local, fn_only=True) compressed = True -@@ -1302,6 +1417,17 @@ class YumRepository(Repository, config.RepoConf): +@@ -1302,6 +1418,17 @@ class YumRepository(Repository, config.RepoConf): into the delete list, this means metadata can change filename without us leaking it. """ @@ -159798,7 +159809,7 @@ index e5e9ece..bbcb2b8 100644 def _mdtype_eq(omdtype, odata, nmdtype, ndata): """ Check if two returns from _get_mdtype_data() are equal. """ if ndata is None: -@@ -1321,6 +1447,14 @@ class YumRepository(Repository, config.RepoConf): +@@ -1321,6 +1448,14 @@ class YumRepository(Repository, config.RepoConf): return True all_mdtypes = self.retrieved.keys() @@ -159813,7 +159824,7 @@ index e5e9ece..bbcb2b8 100644 if mdtypes is None: mdtypes = all_mdtypes -@@ -1333,8 +1467,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1333,8 +1468,7 @@ class YumRepository(Repository, config.RepoConf): # Inited twice atm. ... sue me self._oldRepoMDData['new_MD_files'] = [] @@ -159823,7 +159834,7 @@ index e5e9ece..bbcb2b8 100644 for mdtype in all_mdtypes: (nmdtype, ndata) = self._get_mdtype_data(mdtype) -@@ -1371,43 +1504,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -1371,43 +1505,16 @@ class YumRepository(Repository, config.RepoConf): # No old repomd data, but we might still have uncompressed MD if self._groupCheckDataMDValid(ndata, nmdtype, mdtype): continue @@ -159872,7 +159883,7 @@ index e5e9ece..bbcb2b8 100644 def _groupLoadRepoXML(self, text=None, mdtypes=None): """ Retrieve the new repomd.xml from the repository, then check it -@@ -1421,7 +1527,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1421,7 +1528,7 @@ class YumRepository(Repository, config.RepoConf): self._commonRetrieveDataMD(mdtypes) def _mdpolicy2mdtypes(self): @@ -159881,7 +159892,7 @@ index e5e9ece..bbcb2b8 100644 'group:primary' : ['primary'], 'group:small' : ["primary", "updateinfo"], 'group:main' : ["primary", "group", "filelists", -@@ -1436,6 +1542,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1436,6 +1543,7 @@ class YumRepository(Repository, config.RepoConf): if not mdtypes or 'group:all' in mdtypes: mdtypes = None else: @@ -159889,7 +159900,7 @@ index e5e9ece..bbcb2b8 100644 mdtypes = sorted(list(mdtypes)) return mdtypes -@@ -1451,12 +1558,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1451,12 +1559,7 @@ class YumRepository(Repository, config.RepoConf): def _getRepoXML(self): if self._repoXML: return self._repoXML @@ -159903,7 +159914,7 @@ index e5e9ece..bbcb2b8 100644 return self._repoXML -@@ -1480,7 +1582,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1480,7 +1583,7 @@ class YumRepository(Repository, config.RepoConf): result = self._getFile(relative='repodata/repomd.xml.asc', copy_local=1, local = sigfile, @@ -159912,7 +159923,7 @@ index e5e9ece..bbcb2b8 100644 reget=None, checkfunc=None, cache=self.http_caching == 'all', -@@ -1514,7 +1616,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1514,7 +1617,7 @@ class YumRepository(Repository, config.RepoConf): return self._checkMD(fn, mdtype, openchecksum) def _checkMD(self, fn, mdtype, openchecksum=False, @@ -159921,7 +159932,7 @@ index e5e9ece..bbcb2b8 100644 """ Internal function, use .checkMD() from outside yum. """ thisdata = data # So the argument name is nicer -@@ -1537,6 +1639,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -1537,6 +1640,18 @@ class YumRepository(Repository, config.RepoConf): if size is not None: size = int(size) @@ -159940,7 +159951,7 @@ index e5e9ece..bbcb2b8 100644 try: # get the local checksum l_csum = self._checksum(r_ctype, file, datasize=size) except Errors.RepoError, e: -@@ -1551,15 +1665,13 @@ class YumRepository(Repository, config.RepoConf): +@@ -1551,15 +1666,13 @@ class YumRepository(Repository, config.RepoConf): return None raise URLGrabError(-1, 'Metadata file does not match checksum') @@ -159957,7 +159968,7 @@ index e5e9ece..bbcb2b8 100644 """ Internal function, use .retrieveMD() from outside yum. """ # Note that this can raise Errors.RepoMDError if mdtype doesn't exist # for this repo. -@@ -1597,8 +1709,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -1597,8 +1710,10 @@ class YumRepository(Repository, config.RepoConf): return local # it's the same return the local one try: @@ -159970,7 +159981,7 @@ index e5e9ece..bbcb2b8 100644 if thisdata.size is None: reget = None else: -@@ -1613,8 +1727,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1613,8 +1728,9 @@ class YumRepository(Repository, config.RepoConf): checkfunc=checkfunc, text=text, cache=self.http_caching == 'all', @@ -159982,7 +159993,7 @@ index e5e9ece..bbcb2b8 100644 if retrieve_can_fail: return None raise -@@ -1624,7 +1739,6 @@ class YumRepository(Repository, config.RepoConf): +@@ -1624,7 +1740,6 @@ class YumRepository(Repository, config.RepoConf): raise Errors.RepoError, \ "Could not retrieve %s matching remote checksum from %s" % (local, self) else: @@ -159990,7 +160001,7 @@ index e5e9ece..bbcb2b8 100644 return local -@@ -1646,13 +1760,21 @@ class YumRepository(Repository, config.RepoConf): +@@ -1646,13 +1761,21 @@ class YumRepository(Repository, config.RepoConf): def getGroups(self): """gets groups and returns group file path for the repository, if there @@ -160015,7 +160026,7 @@ index e5e9ece..bbcb2b8 100644 self._callbacks_changed = True def setFailureObj(self, failure_obj): -@@ -1681,7 +1803,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1681,7 +1804,7 @@ class YumRepository(Repository, config.RepoConf): print "Could not read mirrorlist %s, error was \n%s" %(url, e) content = [] for line in content: diff --git a/yum.spec b/yum.spec index 48d9bf8..178e346 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 38%{?dist} +Release: 40%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -315,9 +315,10 @@ exit 0 %endif %changelog -* Thu Aug 30 2012 James Antill - 3.4.3-38 +* Thu Aug 30 2012 James Antill - 3.4.3-40 - update to latest HEAD. - Fix rel-eng problems when repo.repofile is None. +- Don't statvfs when we aren't going to copy. * Tue Aug 28 2012 James Antill - 3.4.3-36 - update to latest HEAD. From 32e1511d4eee458825765d65c094745da87f9818 Mon Sep 17 00:00:00 2001 From: James Antill Date: Fri, 31 Aug 2012 17:08:23 -0400 Subject: [PATCH 003/174] update to latest HEAD. - Don't statvfs when we aren't going to copy, and using relative. --- yum-HEAD.patch | 70 ++++++++++++++++++++++++++++++-------------------- yum.spec | 6 ++++- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index 39fe263..e3296f4 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -159344,7 +159344,7 @@ index 2cb1acb..0586c1c 100644 for pkg in un['pkglist']: for filedata in pkg['packages']: diff --git a/yum/yumRepo.py b/yum/yumRepo.py -index e5e9ece..f834aec 100644 +index e5e9ece..7c55353 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -20,10 +20,12 @@ import time @@ -159650,8 +159650,23 @@ index e5e9ece..f834aec 100644 except urlgrabber.grabber.URLGrabError, e: if not os.path.exists(self.metalink_filename): -@@ -751,7 +846,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -749,9 +844,22 @@ class YumRepository(Repository, config.RepoConf): + value), + fdel=lambda self: setattr(self, "_metalink", None)) ++ def _all_urls_are_files(self, url): ++ if url: ++ return url.startswith("/") or url.startswith("file:") ++ ++ if not self.urls: # WTF ... but whatever. ++ return False ++ ++ # Not an explicit url ... so make sure all mirrors/etc. are file:// ++ for url in self.urls: ++ if not self._all_urls_are_files(url): ++ return False ++ return True ++ def _getFile(self, url=None, relative=None, local=None, start=None, end=None, copy_local=None, checkfunc=None, text=None, reget='simple', - cache=True, size=None): @@ -159659,7 +159674,7 @@ index e5e9ece..f834aec 100644 """retrieve file from the mirrorgroup for the repo relative to local, optionally get range from start to end, also optionally retrieve from a specific baseurl""" -@@ -768,7 +863,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -768,7 +876,7 @@ class YumRepository(Repository, config.RepoConf): if local is None or relative is None: raise Errors.RepoError, \ @@ -159668,12 +159683,11 @@ index e5e9ece..f834aec 100644 if self.cache == 1: if os.path.exists(local): # FIXME - we should figure out a way -@@ -796,6 +891,17 @@ class YumRepository(Repository, config.RepoConf): +@@ -796,6 +904,16 @@ class YumRepository(Repository, config.RepoConf): except Errors.MediaError, e: verbose_logger.log(logginglevels.DEBUG_2, "Error getting package from media; falling back to url %s" %(e,)) -+ if size and (self.copy_local or not url or -+ not (url.startswith("/") or url.startswith("file:"))): ++ if size and (copy_local or not _all_urls_are_files(url)): + dirstat = os.statvfs(os.path.dirname(local)) + avail = dirstat.f_bavail * dirstat.f_bsize + if avail < long(size): @@ -159686,7 +159700,7 @@ index e5e9ece..f834aec 100644 if url and scheme != "media": ugopts = self._default_grabopts(cache=cache) ug = URLGrabber(progress_obj = self.callback, -@@ -815,14 +921,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -815,14 +933,11 @@ class YumRepository(Repository, config.RepoConf): range=(start, end), ) except URLGrabError, e: @@ -159703,7 +159717,7 @@ index e5e9ece..f834aec 100644 else: -@@ -835,19 +938,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -835,19 +950,18 @@ class YumRepository(Repository, config.RepoConf): reget = reget, checkfunc=checkfunc, http_headers=headers, @@ -159729,7 +159743,7 @@ index e5e9ece..f834aec 100644 remote = package.relativepath local = package.localPkg() basepath = package.basepath -@@ -857,15 +959,26 @@ class YumRepository(Repository, config.RepoConf): +@@ -857,15 +971,26 @@ class YumRepository(Repository, config.RepoConf): return local misc.unlink_f(local) @@ -159757,7 +159771,7 @@ index e5e9ece..f834aec 100644 def getHeader(self, package, checkfunc = None, reget = 'simple', cache = True): -@@ -1020,7 +1133,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1020,7 +1145,7 @@ class YumRepository(Repository, config.RepoConf): if grab_can_fail: return None raise Errors.RepoError, 'Error downloading file %s: %s' % (local, e) @@ -159766,7 +159780,7 @@ index e5e9ece..f834aec 100644 misc.unlink_f(tfname) if grab_can_fail: return None -@@ -1260,6 +1373,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1260,6 +1385,9 @@ class YumRepository(Repository, config.RepoConf): return True def _check_db_version(self, mdtype, repoXML=None): @@ -159776,7 +159790,7 @@ index e5e9ece..f834aec 100644 if repoXML is None: repoXML = self.repoXML if mdtype in repoXML.repoData: -@@ -1277,11 +1393,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -1277,11 +1405,11 @@ class YumRepository(Repository, config.RepoConf): return None if not file_check: @@ -159791,7 +159805,7 @@ index e5e9ece..f834aec 100644 if not os.path.exists(local): local = misc.decompress(local, fn_only=True) compressed = True -@@ -1302,6 +1418,17 @@ class YumRepository(Repository, config.RepoConf): +@@ -1302,6 +1430,17 @@ class YumRepository(Repository, config.RepoConf): into the delete list, this means metadata can change filename without us leaking it. """ @@ -159809,7 +159823,7 @@ index e5e9ece..f834aec 100644 def _mdtype_eq(omdtype, odata, nmdtype, ndata): """ Check if two returns from _get_mdtype_data() are equal. """ if ndata is None: -@@ -1321,6 +1448,14 @@ class YumRepository(Repository, config.RepoConf): +@@ -1321,6 +1460,14 @@ class YumRepository(Repository, config.RepoConf): return True all_mdtypes = self.retrieved.keys() @@ -159824,7 +159838,7 @@ index e5e9ece..f834aec 100644 if mdtypes is None: mdtypes = all_mdtypes -@@ -1333,8 +1468,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1333,8 +1480,7 @@ class YumRepository(Repository, config.RepoConf): # Inited twice atm. ... sue me self._oldRepoMDData['new_MD_files'] = [] @@ -159834,7 +159848,7 @@ index e5e9ece..f834aec 100644 for mdtype in all_mdtypes: (nmdtype, ndata) = self._get_mdtype_data(mdtype) -@@ -1371,43 +1505,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -1371,43 +1517,16 @@ class YumRepository(Repository, config.RepoConf): # No old repomd data, but we might still have uncompressed MD if self._groupCheckDataMDValid(ndata, nmdtype, mdtype): continue @@ -159883,7 +159897,7 @@ index e5e9ece..f834aec 100644 def _groupLoadRepoXML(self, text=None, mdtypes=None): """ Retrieve the new repomd.xml from the repository, then check it -@@ -1421,7 +1528,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1421,7 +1540,7 @@ class YumRepository(Repository, config.RepoConf): self._commonRetrieveDataMD(mdtypes) def _mdpolicy2mdtypes(self): @@ -159892,7 +159906,7 @@ index e5e9ece..f834aec 100644 'group:primary' : ['primary'], 'group:small' : ["primary", "updateinfo"], 'group:main' : ["primary", "group", "filelists", -@@ -1436,6 +1543,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1436,6 +1555,7 @@ class YumRepository(Repository, config.RepoConf): if not mdtypes or 'group:all' in mdtypes: mdtypes = None else: @@ -159900,7 +159914,7 @@ index e5e9ece..f834aec 100644 mdtypes = sorted(list(mdtypes)) return mdtypes -@@ -1451,12 +1559,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1451,12 +1571,7 @@ class YumRepository(Repository, config.RepoConf): def _getRepoXML(self): if self._repoXML: return self._repoXML @@ -159914,7 +159928,7 @@ index e5e9ece..f834aec 100644 return self._repoXML -@@ -1480,7 +1583,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1480,7 +1595,7 @@ class YumRepository(Repository, config.RepoConf): result = self._getFile(relative='repodata/repomd.xml.asc', copy_local=1, local = sigfile, @@ -159923,7 +159937,7 @@ index e5e9ece..f834aec 100644 reget=None, checkfunc=None, cache=self.http_caching == 'all', -@@ -1514,7 +1617,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1514,7 +1629,7 @@ class YumRepository(Repository, config.RepoConf): return self._checkMD(fn, mdtype, openchecksum) def _checkMD(self, fn, mdtype, openchecksum=False, @@ -159932,7 +159946,7 @@ index e5e9ece..f834aec 100644 """ Internal function, use .checkMD() from outside yum. """ thisdata = data # So the argument name is nicer -@@ -1537,6 +1640,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -1537,6 +1652,18 @@ class YumRepository(Repository, config.RepoConf): if size is not None: size = int(size) @@ -159951,7 +159965,7 @@ index e5e9ece..f834aec 100644 try: # get the local checksum l_csum = self._checksum(r_ctype, file, datasize=size) except Errors.RepoError, e: -@@ -1551,15 +1666,13 @@ class YumRepository(Repository, config.RepoConf): +@@ -1551,15 +1678,13 @@ class YumRepository(Repository, config.RepoConf): return None raise URLGrabError(-1, 'Metadata file does not match checksum') @@ -159968,7 +159982,7 @@ index e5e9ece..f834aec 100644 """ Internal function, use .retrieveMD() from outside yum. """ # Note that this can raise Errors.RepoMDError if mdtype doesn't exist # for this repo. -@@ -1597,8 +1710,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -1597,8 +1722,10 @@ class YumRepository(Repository, config.RepoConf): return local # it's the same return the local one try: @@ -159981,7 +159995,7 @@ index e5e9ece..f834aec 100644 if thisdata.size is None: reget = None else: -@@ -1613,8 +1728,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1613,8 +1740,9 @@ class YumRepository(Repository, config.RepoConf): checkfunc=checkfunc, text=text, cache=self.http_caching == 'all', @@ -159993,7 +160007,7 @@ index e5e9ece..f834aec 100644 if retrieve_can_fail: return None raise -@@ -1624,7 +1740,6 @@ class YumRepository(Repository, config.RepoConf): +@@ -1624,7 +1752,6 @@ class YumRepository(Repository, config.RepoConf): raise Errors.RepoError, \ "Could not retrieve %s matching remote checksum from %s" % (local, self) else: @@ -160001,7 +160015,7 @@ index e5e9ece..f834aec 100644 return local -@@ -1646,13 +1761,21 @@ class YumRepository(Repository, config.RepoConf): +@@ -1646,13 +1773,21 @@ class YumRepository(Repository, config.RepoConf): def getGroups(self): """gets groups and returns group file path for the repository, if there @@ -160026,7 +160040,7 @@ index e5e9ece..f834aec 100644 self._callbacks_changed = True def setFailureObj(self, failure_obj): -@@ -1681,7 +1804,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1681,7 +1816,7 @@ class YumRepository(Repository, config.RepoConf): print "Could not read mirrorlist %s, error was \n%s" %(url, e) content = [] for line in content: diff --git a/yum.spec b/yum.spec index 178e346..b64281c 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 40%{?dist} +Release: 41%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -315,6 +315,10 @@ exit 0 %endif %changelog +* Fri Aug 31 2012 James Antill - 3.4.3-41 +- update to latest HEAD. +- Don't statvfs when we aren't going to copy, and using relative. + * Thu Aug 30 2012 James Antill - 3.4.3-40 - update to latest HEAD. - Fix rel-eng problems when repo.repofile is None. From 82619862242247ec5d6890a338fecc76af7bcc55 Mon Sep 17 00:00:00 2001 From: James Antill Date: Sat, 1 Sep 2012 11:14:42 -0400 Subject: [PATCH 004/174] update to latest HEAD. - Fix missing self. on last patch. --- yum-HEAD.patch | 4 ++-- yum.spec | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index e3296f4..96760d5 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -159344,7 +159344,7 @@ index 2cb1acb..0586c1c 100644 for pkg in un['pkglist']: for filedata in pkg['packages']: diff --git a/yum/yumRepo.py b/yum/yumRepo.py -index e5e9ece..7c55353 100644 +index e5e9ece..876dc12 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -20,10 +20,12 @@ import time @@ -159687,7 +159687,7 @@ index e5e9ece..7c55353 100644 except Errors.MediaError, e: verbose_logger.log(logginglevels.DEBUG_2, "Error getting package from media; falling back to url %s" %(e,)) -+ if size and (copy_local or not _all_urls_are_files(url)): ++ if size and (copy_local or not self._all_urls_are_files(url)): + dirstat = os.statvfs(os.path.dirname(local)) + avail = dirstat.f_bavail * dirstat.f_bsize + if avail < long(size): diff --git a/yum.spec b/yum.spec index b64281c..ecbe5eb 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 41%{?dist} +Release: 42%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -315,6 +315,10 @@ exit 0 %endif %changelog +* Sat Sep 1 2012 James Antill - 3.4.3-42 +- update to latest HEAD. +- Fix missing self. on last patch. + * Fri Aug 31 2012 James Antill - 3.4.3-41 - update to latest HEAD. - Don't statvfs when we aren't going to copy, and using relative. From cc5b95c12fd10d3e79e0cabc74d3347cfc81e897 Mon Sep 17 00:00:00 2001 From: James Antill Date: Fri, 7 Sep 2012 15:46:01 -0400 Subject: [PATCH 005/174] update to latest HEAD. - Use .ui_id explicitly for backcompat. on strings, *sigh*. --- yum-HEAD.patch | 328 +++++++++++++++++++++++++++++++++++-------------- yum.spec | 6 +- 2 files changed, 240 insertions(+), 94 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index 96760d5..e4c51b8 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -2293,7 +2293,7 @@ index 0000000..d2a0ed1 +if __name__ == "__main__": + generateAll(os.getcwd(), os.getcwd()) diff --git a/docs/yum.8 b/docs/yum.8 -index 1a8202a..15a8345 100644 +index 1a8202a..dab01f6 100644 --- a/docs/yum.8 +++ b/docs/yum.8 @@ -52,6 +52,7 @@ gnome\-packagekit application\&. @@ -2304,8 +2304,12 @@ index 1a8202a..15a8345 100644 .br .I \fR * localinstall rpmfile1 [rpmfile2] [\&.\&.\&.] (maintained for legacy reasons only - use install) -@@ -69,7 +70,9 @@ gnome\-packagekit application\&. +@@ -67,9 +68,13 @@ gnome\-packagekit application\&. .br + .I \fR * repolist [all|enabled|disabled] + .br ++.I \fR * repoinfo [all|enabled|disabled] ++.br .I \fR * version [ all | installed | available | group-* | nogroups* | grouplist | groupinfo ] .br -.I \fR * history [info|list|packages-list|summary|addon-info|redo|undo|rollback|new] @@ -2315,7 +2319,7 @@ index 1a8202a..15a8345 100644 .br .I \fR * check .br -@@ -86,14 +89,20 @@ Is used to install the latest version of a package or +@@ -86,14 +91,20 @@ Is used to install the latest version of a package or group of packages while ensuring that all dependencies are satisfied\&. (See \fBSpecifying package names\fP for more information) If no package matches the given package name(s), they are assumed to be a shell @@ -2340,7 +2344,7 @@ index 1a8202a..15a8345 100644 .IP .IP "\fBupdate\fP" If run without any packages, update will update every currently -@@ -111,7 +120,7 @@ changes, for example: upgrading from somelinux 8.0 to somelinux 9. +@@ -111,7 +122,7 @@ changes, for example: upgrading from somelinux 8.0 to somelinux 9. Note that "\fBupdate\fP" works on installed packages first, and only if there are no matches does it look for available packages. The difference is most @@ -2349,7 +2353,7 @@ index 1a8202a..15a8345 100644 "\fBupdate\fP foo" if foo-1-2 is installed. You can use the "\fBupdate-to\fP" if you'd prefer that nothing happen in the above case. .IP -@@ -158,6 +167,11 @@ the "install" command\&.(See \fBSpecifying package names\fP for more information +@@ -158,6 +169,11 @@ the "install" command\&.(See \fBSpecifying package names\fP for more information Note that "yum" is included in the protected_packages configuration, by default. So you can't accidentally remove yum itself. @@ -2361,7 +2365,7 @@ index 1a8202a..15a8345 100644 .IP .IP "\fBlist\fP" Is used to list various information about available -@@ -209,10 +223,12 @@ installed. +@@ -209,10 +225,12 @@ installed. "\fBgroup list\fP" is used to list the available groups from all \fByum\fP repos. Groups are marked as "installed" if all mandatory packages are installed, or if a group doesn't have any mandatory packages then it is installed if any of the optional or @@ -2378,7 +2382,7 @@ index 1a8202a..15a8345 100644 "\fBgroup remove\fP" is used to remove all of the packages in a group, unlike "groupinstall" this will remove everything regardless of group_package_types. It is worth pointing -@@ -224,10 +240,37 @@ to only remove packages which aren't required by something else. +@@ -224,10 +242,37 @@ to only remove packages which aren't required by something else. "\fBgroup info\fP" is used to give the description and package list of a group (and which type those packages are marked as). Note that you can use the yum-filter-data and @@ -2417,7 +2421,7 @@ index 1a8202a..15a8345 100644 .IP .IP "\fBshell\fP" Is used to enter the 'yum shell', when a filename is specified the contents of -@@ -235,12 +278,13 @@ that file is executed in yum shell mode. See \fIyum-shell(8)\fP for more info +@@ -235,12 +280,13 @@ that file is executed in yum shell mode. See \fIyum-shell(8)\fP for more info .IP .IP "\fBresolvedep\fP" Is used to list packages providing the specified dependencies, at most one @@ -2433,7 +2437,7 @@ index 1a8202a..15a8345 100644 reasons only. .IP .IP "\fBlocalupdate\fP" -@@ -248,7 +292,7 @@ Is used to update the system by specifying local rpm files. Only the specified +@@ -248,7 +294,7 @@ Is used to update the system by specifying local rpm files. Only the specified rpm files of which an older version is already installed will be installed, the remaining specified packages will be ignored. If required the enabled repositories will be used to resolve dependencies. Note @@ -2442,7 +2446,7 @@ index 1a8202a..15a8345 100644 legacy reasons only. .IP .IP "\fBreinstall\fP" -@@ -260,7 +304,7 @@ on groups, files, provides and filelists just like the "install" command\&. +@@ -260,7 +306,7 @@ on groups, files, provides and filelists just like the "install" command\&. Will try and downgrade a package from the version currently installed to the previously highest version (or the specified version). The depsolver will not necessarily work, but if you specify all the packages it @@ -2451,7 +2455,14 @@ index 1a8202a..15a8345 100644 work for "installonly" packages, like Kernels. downgrade operates on groups, files, provides, filelists and rpm files just like the "install" command\&. .IP -@@ -294,8 +338,8 @@ package counts/etc. will be zeroed out). +@@ -291,11 +337,15 @@ then yum will ignore any repo errors and output the information it can get + (Eg. "yum clean all; yum -C repolist" will output something, although the + package counts/etc. will be zeroed out). + .IP ++.IP "\fBrepoinfo\fP" ++.IP ++This ocmmand works exactly like repolist -v. ++.IP .IP "\fBversion\fP" Produces a "version" of the rpmdb, and of the enabled repositories if "all" is given as the first argument. You can also specify version groups in the @@ -2462,7 +2473,7 @@ index 1a8202a..15a8345 100644 packages (in sorted order), and the checksum_type/checksum_data entries from the yumdb. Note that this rpmdb version is now also used significantly within yum (esp. in yum history). -@@ -321,26 +365,33 @@ and so takes sub-commands: +@@ -321,26 +371,33 @@ and so takes sub-commands: .IP "\fBhistory\fP" The history command allows the user to view what has happened in past transactions (assuming the history_record config. option is set). You can use @@ -2502,7 +2513,7 @@ index 1a8202a..15a8345 100644 A (if it is not still installed), and "rollback 1" will try to remove packages B and C. Note that after a "rollback 1" you will have a fourth transaction, although the ending rpmdb version (see: yum version) should be the same in -@@ -349,6 +400,12 @@ transactions 1 and 4. +@@ -349,6 +406,12 @@ transactions 1 and 4. The addon-info command takes a transaction ID, and the packages-list command takes a package (with wildcards). @@ -2515,7 +2526,7 @@ index 1a8202a..15a8345 100644 In "history list" you can change the behaviour of the 2nd column via. the configuration option history_list_view. -@@ -371,6 +428,15 @@ end of the package column in the packages-list command). +@@ -371,6 +434,15 @@ end of the package column in the packages-list command). .I \fBs\fR - The transaction completed fine, but --skip-broken was enabled and had to skip some packages. .br @@ -2531,7 +2542,7 @@ index 1a8202a..15a8345 100644 .IP .IP "\fBcheck\fP" Checks the local rpmdb and produces information on any problems it finds. You -@@ -401,6 +467,11 @@ Assume yes; assume that the answer to any question which would be asked +@@ -401,6 +473,11 @@ Assume yes; assume that the answer to any question which would be asked is yes\&. .br Configuration Option: \fBassumeyes\fP @@ -2543,7 +2554,7 @@ index 1a8202a..15a8345 100644 .IP "\fB\-c, \-\-config=[config file]\fP" Specifies the config file location - can take HTTP and FTP URLs and local file paths\&. -@@ -420,7 +491,7 @@ Sets the error level to [number] Practical range 0 \- 10. 0 means print only cri +@@ -420,7 +497,7 @@ Sets the error level to [number] Practical range 0 \- 10. 0 means print only cri .br Configuration Option: \fBerrorlevel\fP .IP "\fB\-\-rpmverbosity=[name]\fP" @@ -2552,7 +2563,7 @@ index 1a8202a..15a8345 100644 options are: 'critical', 'emergency', 'error', 'warn' and 'debug'. .br Configuration Option: \fBrpmverbosity\fP -@@ -506,7 +577,8 @@ option will corrupt your cache (and you can use $releasever in your cachedir +@@ -506,7 +583,8 @@ option will corrupt your cache (and you can use $releasever in your cachedir configuration to stop this). .PP .IP "\fB\-t, \-\-tolerant\fP" @@ -3471,7 +3482,7 @@ index f1e06e8..b21c594 100644 complete -F _yum -o filenames yum yummain.py diff --git a/output.py b/output.py -index b6aa277..caac21a 100755 +index b6aa277..05b255e 100755 --- a/output.py +++ b/output.py @@ -1,6 +1,6 @@ @@ -3901,6 +3912,15 @@ index b6aa277..caac21a 100755 (hibeg, hiend) = self._highlight(highlight) print _("Name : %s%s%s") % (hibeg, to_unicode(pkg.name), hiend) print _("Arch : %s") % to_unicode(pkg.arch) +@@ -585,7 +820,7 @@ class YumOutput: + print _("Version : %s") % to_unicode(pkg.version) + print _("Release : %s") % to_unicode(pkg.release) + print _("Size : %s") % self.format_number(float(pkg.size)) +- print _("Repo : %s") % to_unicode(pkg.repoid) ++ print _("Repo : %s") % to_unicode(pkg.repo.ui_id) + if pkg.repoid == 'installed' and 'from_repo' in pkg.yumdb_info: + print _("From repo : %s") % to_unicode(pkg.yumdb_info.from_repo) + if self.verbose_logger.isEnabledFor(logginglevels.DEBUG_3): @@ -617,9 +852,22 @@ class YumOutput: print "" @@ -157874,7 +157894,7 @@ index 4af563a..47832fc 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..f67169f 100644 +index 5ef9951..07c555c 100644 --- a/yum/packages.py +++ b/yum/packages.py @@ -106,14 +106,16 @@ def buildPkgRefDict(pkgs, casematch=True): @@ -157896,7 +157916,18 @@ index 5ef9951..f67169f 100644 exactmatch = [] matched = [] unmatched = [] -@@ -243,34 +245,87 @@ class PackageObject(object): +@@ -223,6 +225,10 @@ class FakeRepository: + def __str__(self): + return self.id + ++ def _ui_id(self): ++ return self.id ++ ui_id = property(fget=lambda self: self._ui_id()) ++ + + # Goal for the below is to have a packageobject that can be used by generic + # functions independent of the type of package - ie: installed or available +@@ -243,34 +249,87 @@ class PackageObject(object): def _ui_envra(self): if self.epoch == '0': @@ -158004,7 +158035,7 @@ index 5ef9951..f67169f 100644 def __str__(self): return self.ui_envra -@@ -481,15 +536,14 @@ class RpmBase(object): +@@ -481,15 +540,14 @@ class RpmBase(object): if prcotuple in self._prco_lookup[prcotype]: return 1 @@ -158028,7 +158059,7 @@ index 5ef9951..f67169f 100644 return 0 -@@ -611,15 +665,18 @@ class RpmBase(object): +@@ -611,15 +669,18 @@ class RpmBase(object): dirlist = property(fget=lambda self: self.returnFileEntries(ftype='dir')) ghostlist = property(fget=lambda self: self.returnFileEntries(ftype='ghost')) requires = property(fget=lambda self: self.returnPrco('requires')) @@ -158047,7 +158078,7 @@ index 5ef9951..f67169f 100644 conflicts_print = property(fget=lambda self: self.returnPrco('conflicts', True)) obsoletes_print = property(fget=lambda self: self.returnPrco('obsoletes', True)) changelog = property(fget=lambda self: self.returnChangelog()) -@@ -1083,7 +1140,7 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1083,7 +1144,7 @@ class YumAvailablePackage(PackageObject, RpmBase): misc.to_unicode(misc.to_xml(self.summary)), misc.to_unicode(misc.to_xml(self.description)), packager, url, self.filetime, @@ -158056,7 +158087,7 @@ index 5ef9951..f67169f 100644 msg += self._return_remote_location() return msg -@@ -1133,7 +1190,7 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1133,7 +1194,7 @@ class YumAvailablePackage(PackageObject, RpmBase): msg = "" mylist = getattr(self, pcotype) if mylist: msg = "\n \n" % pcotype @@ -158065,7 +158096,7 @@ index 5ef9951..f67169f 100644 pcostring = ''' %s\n""" % misc.to_xml(fn) return msg -@@ -1194,8 +1251,8 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1194,8 +1255,8 @@ class YumAvailablePackage(PackageObject, RpmBase): continue newlist.append(i) mylist = newlist @@ -158091,7 +158122,7 @@ index 5ef9951..f67169f 100644 if name.startswith('rpmlib('): continue # this drops out requires that the pkg provides for itself. -@@ -1217,13 +1274,16 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1217,13 +1278,16 @@ class YumAvailablePackage(PackageObject, RpmBase): prcostring += ''' ver="%s"''' % misc.to_xml(v, attrib=True) if r: prcostring += ''' rel="%s"''' % misc.to_xml(r, attrib=True) @@ -158110,7 +158141,7 @@ index 5ef9951..f67169f 100644 return msg def _dump_changelog(self, clog_limit): -@@ -1272,6 +1332,13 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1272,6 +1336,13 @@ class YumAvailablePackage(PackageObject, RpmBase): return misc.to_utf8(msg) @@ -158124,7 +158155,7 @@ index 5ef9951..f67169f 100644 # This is a tweak on YumAvailablePackage() and is a base class for packages # which are actual rpms. -@@ -1299,7 +1366,8 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1299,7 +1370,8 @@ class YumHeaderPackage(YumAvailablePackage): self.pkgid = self.hdr[rpm.RPMTAG_SHA1HEADER] if not self.pkgid: self.pkgid = "%s.%s" %(self.hdr['name'], self.hdr['buildtime']) @@ -158134,7 +158165,7 @@ index 5ef9951..f67169f 100644 self.__mode_cache = {} self.__prcoPopulated = False -@@ -1353,6 +1421,12 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1353,6 +1425,12 @@ class YumHeaderPackage(YumAvailablePackage): continue lst = hdr[getattr(rpm, 'RPMTAG_%sFLAGS' % tag)] @@ -158147,7 +158178,7 @@ index 5ef9951..f67169f 100644 flag = map(rpmUtils.miscutils.flagToString, lst) flag = map(misc.share_data, flag) -@@ -1363,6 +1437,10 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1363,6 +1441,10 @@ class YumHeaderPackage(YumAvailablePackage): prcotype = tag2prco[tag] self.prco[prcotype] = map(misc.share_data, zip(name,flag,vers)) @@ -158158,7 +158189,7 @@ index 5ef9951..f67169f 100644 def tagByName(self, tag): warnings.warn("tagByName() will go away in a furture version of Yum.\n", -@@ -1447,7 +1525,7 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1447,7 +1529,7 @@ class YumHeaderPackage(YumAvailablePackage): raise NotImplementedError() def _size(self): @@ -159078,9 +159109,27 @@ index 9b265f9..61c9a0e 100644 + + self.display.verify_txmbr(self.base, txmbr, count) diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py -index 8a6f6f3..ba929de 100644 +index 8a6f6f3..ed57408 100644 --- a/yum/sqlitesack.py +++ b/yum/sqlitesack.py +@@ -69,7 +69,7 @@ def _parse_pkg_n(match, regexp_match, n): + if not regexp_match: + return False + +- if (match and n and match[0] not in ('?', '*') and match[0] != n[0]): ++ if (match and n and match[0] not in ('?', '*', '[') and match[0] != n[0]): + return False + if regexp_match(n): + return True +@@ -82,7 +82,7 @@ def _parse_pkg(match, regexp_match, data, e,v,r,a): + # Worthless speed hacks? + if match == n: + return True +- if (match and n and match[0] not in ('?', '*') and ++ if (match and n and match[0] not in ('?', '*', '[') and + match[0] != n[0] and match[0] != e[0]): + return False + @@ -382,6 +382,10 @@ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase): def returnPrco(self, prcotype, printable=False): @@ -159344,7 +159393,7 @@ index 2cb1acb..0586c1c 100644 for pkg in un['pkglist']: for filedata in pkg['packages']: diff --git a/yum/yumRepo.py b/yum/yumRepo.py -index e5e9ece..876dc12 100644 +index e5e9ece..21f65f7 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -20,10 +20,12 @@ import time @@ -159368,6 +159417,15 @@ index e5e9ece..876dc12 100644 from constants import * import metalink +@@ -104,7 +107,7 @@ class YumPackageSack(packageSack.PackageSack): + if repo in self.added: + if 'metadata' not in self.added[repo]: + raise Errors.RepoError, '%s md for %s imported before primary' \ +- % (datatype, repo.id) ++ % (datatype, repo.ui_id) + current = 0 + for pkgid in dataobj: + current += 1 @@ -121,6 +124,25 @@ class YumPackageSack(packageSack.PackageSack): # umm, wtf? pass @@ -159545,16 +159603,18 @@ index e5e9ece..876dc12 100644 def close(self): if self._sack is not None: self.sack.close() -@@ -350,7 +434,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -350,6 +434,10 @@ class YumRepository(Repository, config.RepoConf): return thisdata.location def __str__(self): -- return self.id -+ return self.ui_id ++ # Note: You might expect this to be .ui_id, except people got used to ++ # the fact that str(repo) == repo.id and used the former instead of ++ # the later when they wanted just the .id. So we have to live with it ++ # and use .ui_id explicitly. + return self.id def _checksum(self, sumtype, file, CHUNK=2**16, checksum_can_fail=False, - datasize=None): -@@ -378,7 +462,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -378,7 +466,7 @@ class YumRepository(Repository, config.RepoConf): 'basecachedir', 'http_headers', 'metadata_cookie', 'metadata_cookie_fn', 'quick_enable_disable', 'repoMDFile', 'timestamp_check', 'urls', 'mirrorurls', @@ -159563,7 +159623,16 @@ index e5e9ece..876dc12 100644 for attr in dir(self): if attr.startswith('_'): continue -@@ -431,25 +515,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -422,7 +510,7 @@ class YumRepository(Repository, config.RepoConf): + on then raise a repo error""" + if len(self._urls) < 1 and not self.mediaid: + raise Errors.RepoError, \ +- 'Cannot find a valid baseurl for repo: %s' % self.id ++ 'Cannot find a valid baseurl for repo: %s' % self.ui_id + + def doProxyDict(self): + if self._proxy_dict: +@@ -431,25 +519,18 @@ class YumRepository(Repository, config.RepoConf): self._proxy_dict = {} # zap it proxy_string = None empty = (None, '_none_', '') @@ -159597,7 +159666,7 @@ index e5e9ece..876dc12 100644 if proxy_string is not None: self._proxy_dict['http'] = proxy_string -@@ -483,13 +560,30 @@ class YumRepository(Repository, config.RepoConf): +@@ -483,13 +564,30 @@ class YumRepository(Repository, config.RepoConf): ugopts = self._default_grabopts() self._grabfunc = URLGrabber(progress_obj=self.callback, @@ -159629,7 +159698,7 @@ index e5e9ece..876dc12 100644 failure_callback=self.mirror_failure_obj) def _default_grabopts(self, cache=True): -@@ -499,6 +593,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -499,6 +597,7 @@ class YumRepository(Repository, config.RepoConf): 'throttle': self.throttle, 'proxies': self.proxy_dict, 'timeout': self.timeout, @@ -159637,7 +159706,7 @@ index e5e9ece..876dc12 100644 'http_headers': tuple(self.__headersListFromDict(cache=cache)), 'ssl_verify_peer': self.sslverify, 'ssl_verify_host': self.sslverify, -@@ -714,10 +809,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -714,15 +813,15 @@ class YumRepository(Repository, config.RepoConf): local = self.metalink_filename + '.tmp' if not self._metalinkCurrent(): url = misc.to_utf8(self.metalink) @@ -159646,11 +159715,17 @@ index e5e9ece..876dc12 100644 try: ug = URLGrabber(progress_obj = self.callback, **ugopts) - result = ug.urlgrab(url, local, text=self.id + "/metalink") -+ result = ug.urlgrab(url, local, text="%s/metalink" % self) ++ result = ug.urlgrab(url, local, text="%s/metalink" % self.ui_id) except urlgrabber.grabber.URLGrabError, e: if not os.path.exists(self.metalink_filename): -@@ -749,9 +844,22 @@ class YumRepository(Repository, config.RepoConf): + msg = ("Cannot retrieve metalink for repository: %s. " +- "Please verify its path and try again" % self ) ++ "Please verify its path and try again" % self.ui_id ) + raise Errors.RepoError, msg + # Now, we have an old usable metalink, so we can't move to + # a newer repomd.xml ... or checksums won't match. +@@ -749,9 +848,22 @@ class YumRepository(Repository, config.RepoConf): value), fdel=lambda self: setattr(self, "_metalink", None)) @@ -159674,16 +159749,25 @@ index e5e9ece..876dc12 100644 """retrieve file from the mirrorgroup for the repo relative to local, optionally get range from start to end, also optionally retrieve from a specific baseurl""" -@@ -768,7 +876,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -768,7 +880,7 @@ class YumRepository(Repository, config.RepoConf): if local is None or relative is None: raise Errors.RepoError, \ - "get request for Repo %s, gave no source or dest" % self.id -+ "get request for Repo %s, gave no source or dest" % self ++ "get request for Repo %s, gave no source or dest" % self.ui_id if self.cache == 1: if os.path.exists(local): # FIXME - we should figure out a way -@@ -796,6 +904,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -778,7 +890,7 @@ class YumRepository(Repository, config.RepoConf): + raise Errors.RepoError, \ + "Caching enabled but no local cache of %s from %s" % (local, + +- self) ++ self.ui_id) + + if url: + (scheme, netloc, path, query, fragid) = urlparse.urlsplit(url) +@@ -796,6 +908,16 @@ class YumRepository(Repository, config.RepoConf): except Errors.MediaError, e: verbose_logger.log(logginglevels.DEBUG_2, "Error getting package from media; falling back to url %s" %(e,)) @@ -159700,7 +159784,7 @@ index e5e9ece..876dc12 100644 if url and scheme != "media": ugopts = self._default_grabopts(cache=cache) ug = URLGrabber(progress_obj = self.callback, -@@ -815,14 +933,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -815,14 +937,11 @@ class YumRepository(Repository, config.RepoConf): range=(start, end), ) except URLGrabError, e: @@ -159717,7 +159801,7 @@ index e5e9ece..876dc12 100644 else: -@@ -835,19 +950,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -835,19 +954,18 @@ class YumRepository(Repository, config.RepoConf): reget = reget, checkfunc=checkfunc, http_headers=headers, @@ -159743,7 +159827,7 @@ index e5e9ece..876dc12 100644 remote = package.relativepath local = package.localPkg() basepath = package.basepath -@@ -857,15 +971,26 @@ class YumRepository(Repository, config.RepoConf): +@@ -857,15 +975,26 @@ class YumRepository(Repository, config.RepoConf): return local misc.unlink_f(local) @@ -159771,7 +159855,16 @@ index e5e9ece..876dc12 100644 def getHeader(self, package, checkfunc = None, reget = 'simple', cache = True): -@@ -1020,7 +1145,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -991,7 +1120,7 @@ class YumRepository(Repository, config.RepoConf): + def _cachingRepoXML(self, local): + """ Should we cache the current repomd.xml """ + if self.cache and not os.path.exists(local): +- raise Errors.RepoError, 'Cannot find repomd.xml file for %s' % self ++ raise Errors.RepoError, 'Cannot find repomd.xml file for %s' % self.ui_id + if self.cache or self.metadataCurrent(): + return True + return False +@@ -1020,7 +1149,7 @@ class YumRepository(Repository, config.RepoConf): if grab_can_fail: return None raise Errors.RepoError, 'Error downloading file %s: %s' % (local, e) @@ -159780,7 +159873,25 @@ index e5e9ece..876dc12 100644 misc.unlink_f(tfname) if grab_can_fail: return None -@@ -1260,6 +1385,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1047,7 +1176,7 @@ class YumRepository(Repository, config.RepoConf): + parse_can_fail = 'old_repo_XML' in self._oldRepoMDData + if parse_can_fail: + return None +- raise Errors.RepoError, 'Error importing repomd.xml from %s: %s' % (self, e) ++ raise Errors.RepoError, 'Error importing repomd.xml from %s: %s' % (self.ui_id, e) + + def _saveOldRepoXML(self, local): + """ If we have an older repomd.xml file available, save it out. """ +@@ -1074,7 +1203,7 @@ class YumRepository(Repository, config.RepoConf): + # We still want the old data, so we don't download twice. So we + # pretend everything is good until the revert. + if not self.timestamp_check: +- raise Errors.RepoError, "Can't download or revert repomd.xml" ++ raise Errors.RepoError, "Can't download or revert repomd.xml for:" % self.ui_id + + if 'old_repo_XML' not in self._oldRepoMDData: + self._oldRepoMDData = {} +@@ -1260,6 +1389,9 @@ class YumRepository(Repository, config.RepoConf): return True def _check_db_version(self, mdtype, repoXML=None): @@ -159790,7 +159901,7 @@ index e5e9ece..876dc12 100644 if repoXML is None: repoXML = self.repoXML if mdtype in repoXML.repoData: -@@ -1277,11 +1405,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -1277,11 +1409,11 @@ class YumRepository(Repository, config.RepoConf): return None if not file_check: @@ -159805,7 +159916,7 @@ index e5e9ece..876dc12 100644 if not os.path.exists(local): local = misc.decompress(local, fn_only=True) compressed = True -@@ -1302,6 +1430,17 @@ class YumRepository(Repository, config.RepoConf): +@@ -1302,6 +1434,17 @@ class YumRepository(Repository, config.RepoConf): into the delete list, this means metadata can change filename without us leaking it. """ @@ -159823,7 +159934,7 @@ index e5e9ece..876dc12 100644 def _mdtype_eq(omdtype, odata, nmdtype, ndata): """ Check if two returns from _get_mdtype_data() are equal. """ if ndata is None: -@@ -1321,6 +1460,14 @@ class YumRepository(Repository, config.RepoConf): +@@ -1321,6 +1464,14 @@ class YumRepository(Repository, config.RepoConf): return True all_mdtypes = self.retrieved.keys() @@ -159838,7 +159949,7 @@ index e5e9ece..876dc12 100644 if mdtypes is None: mdtypes = all_mdtypes -@@ -1333,8 +1480,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1333,8 +1484,7 @@ class YumRepository(Repository, config.RepoConf): # Inited twice atm. ... sue me self._oldRepoMDData['new_MD_files'] = [] @@ -159848,7 +159959,7 @@ index e5e9ece..876dc12 100644 for mdtype in all_mdtypes: (nmdtype, ndata) = self._get_mdtype_data(mdtype) -@@ -1371,43 +1517,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -1371,43 +1521,16 @@ class YumRepository(Repository, config.RepoConf): # No old repomd data, but we might still have uncompressed MD if self._groupCheckDataMDValid(ndata, nmdtype, mdtype): continue @@ -159897,7 +160008,7 @@ index e5e9ece..876dc12 100644 def _groupLoadRepoXML(self, text=None, mdtypes=None): """ Retrieve the new repomd.xml from the repository, then check it -@@ -1421,7 +1540,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1421,7 +1544,7 @@ class YumRepository(Repository, config.RepoConf): self._commonRetrieveDataMD(mdtypes) def _mdpolicy2mdtypes(self): @@ -159906,7 +160017,7 @@ index e5e9ece..876dc12 100644 'group:primary' : ['primary'], 'group:small' : ["primary", "updateinfo"], 'group:main' : ["primary", "group", "filelists", -@@ -1436,6 +1555,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1436,6 +1559,7 @@ class YumRepository(Repository, config.RepoConf): if not mdtypes or 'group:all' in mdtypes: mdtypes = None else: @@ -159914,7 +160025,13 @@ index e5e9ece..876dc12 100644 mdtypes = sorted(list(mdtypes)) return mdtypes -@@ -1451,12 +1571,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1446,17 +1570,12 @@ class YumRepository(Repository, config.RepoConf): + except KeyboardInterrupt: + self._revertOldRepoXML() # Undo metadata cookie? + raise +- raise Errors.RepoError, 'Bad loadRepoXML policy: %s' % (self.mdpolicy) ++ raise Errors.RepoError, 'Bad loadRepoXML policy (for %s): %s' % (self.ui_id, self.mdpolicy) + def _getRepoXML(self): if self._repoXML: return self._repoXML @@ -159924,20 +160041,20 @@ index e5e9ece..876dc12 100644 - msg = ("Cannot retrieve repository metadata (repomd.xml) for repository: %s. " - "Please verify its path and try again" % self ) - raise Errors.RepoError, msg -+ self._loadRepoXML(text=self) ++ self._loadRepoXML(text=self.ui_id) return self._repoXML -@@ -1480,7 +1595,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1480,7 +1599,7 @@ class YumRepository(Repository, config.RepoConf): result = self._getFile(relative='repodata/repomd.xml.asc', copy_local=1, local = sigfile, - text='%s/signature' % self.id, -+ text='%s/signature' % self, ++ text='%s/signature' % self.ui_id, reget=None, checkfunc=None, cache=self.http_caching == 'all', -@@ -1514,7 +1629,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1514,7 +1633,7 @@ class YumRepository(Repository, config.RepoConf): return self._checkMD(fn, mdtype, openchecksum) def _checkMD(self, fn, mdtype, openchecksum=False, @@ -159946,7 +160063,7 @@ index e5e9ece..876dc12 100644 """ Internal function, use .checkMD() from outside yum. """ thisdata = data # So the argument name is nicer -@@ -1537,6 +1652,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -1537,6 +1656,18 @@ class YumRepository(Repository, config.RepoConf): if size is not None: size = int(size) @@ -159965,7 +160082,7 @@ index e5e9ece..876dc12 100644 try: # get the local checksum l_csum = self._checksum(r_ctype, file, datasize=size) except Errors.RepoError, e: -@@ -1551,15 +1678,13 @@ class YumRepository(Repository, config.RepoConf): +@@ -1551,15 +1682,13 @@ class YumRepository(Repository, config.RepoConf): return None raise URLGrabError(-1, 'Metadata file does not match checksum') @@ -159982,7 +160099,16 @@ index e5e9ece..876dc12 100644 """ Internal function, use .retrieveMD() from outside yum. """ # Note that this can raise Errors.RepoMDError if mdtype doesn't exist # for this repo. -@@ -1597,8 +1722,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -1588,7 +1717,7 @@ class YumRepository(Repository, config.RepoConf): + else: # ain't there - raise + raise Errors.RepoError, \ + "Caching enabled but no local cache of %s from %s" % (local, +- self) ++ self.ui_id) + + if (os.path.exists(local) or + self._preload_md_from_system_cache(os.path.basename(local))): +@@ -1597,8 +1726,10 @@ class YumRepository(Repository, config.RepoConf): return local # it's the same return the local one try: @@ -159995,7 +160121,7 @@ index e5e9ece..876dc12 100644 if thisdata.size is None: reget = None else: -@@ -1613,8 +1740,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1613,8 +1744,9 @@ class YumRepository(Repository, config.RepoConf): checkfunc=checkfunc, text=text, cache=self.http_caching == 'all', @@ -160007,15 +160133,18 @@ index e5e9ece..876dc12 100644 if retrieve_can_fail: return None raise -@@ -1624,7 +1752,6 @@ class YumRepository(Repository, config.RepoConf): +@@ -1622,9 +1754,8 @@ class YumRepository(Repository, config.RepoConf): + if retrieve_can_fail: + return None raise Errors.RepoError, \ - "Could not retrieve %s matching remote checksum from %s" % (local, self) +- "Could not retrieve %s matching remote checksum from %s" % (local, self) ++ "Could not retrieve %s matching remote checksum from %s" % (local, self.ui_id) else: - self.retrieved[mdtype] = 1 return local -@@ -1646,13 +1773,21 @@ class YumRepository(Repository, config.RepoConf): +@@ -1646,13 +1777,21 @@ class YumRepository(Repository, config.RepoConf): def getGroups(self): """gets groups and returns group file path for the repository, if there @@ -160040,7 +160169,7 @@ index e5e9ece..876dc12 100644 self._callbacks_changed = True def setFailureObj(self, failure_obj): -@@ -1681,7 +1816,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1681,7 +1820,7 @@ class YumRepository(Repository, config.RepoConf): print "Could not read mirrorlist %s, error was \n%s" %(url, e) content = [] for line in content: @@ -160050,7 +160179,7 @@ index e5e9ece..876dc12 100644 mirror = line.rstrip() # no more trailing \n's mirror = mirror.replace('$ARCH', '$BASEARCH') diff --git a/yumcommands.py b/yumcommands.py -index 4dcbea7..52c3127 100644 +index 4dcbea7..a2e0b1b 100644 --- a/yumcommands.py +++ b/yumcommands.py @@ -29,7 +29,7 @@ import operator @@ -161742,12 +161871,13 @@ index 4dcbea7..52c3127 100644 + """ def getNames(self): +- return ('repolist',) + """Return a list containing the names of this command. This + command can be called from the command line by using any of these names. + + :return: a list containing the names of this command + """ - return ('repolist',) ++ return ('repolist', 'repoinfo') def getUsage(self): + """Return a usage string for this command. @@ -161780,7 +161910,19 @@ index 4dcbea7..52c3127 100644 def _repo_size(repo): ret = 0 for pkg in repo.sack.returnPackages(): -@@ -866,6 +1902,13 @@ class RepoListCommand(YumCommand): +@@ -857,7 +1893,10 @@ class RepoListCommand(YumCommand): + arg = 'enabled' + extcmds = map(lambda x: x.lower(), extcmds) + +- verbose = base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3) ++ if basecmd == 'repoinfo': ++ verbose = True ++ else: ++ verbose = base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3) + if arg != 'disabled' or extcmds: + try: + # Setup so len(repo.sack) is correct +@@ -866,6 +1905,13 @@ class RepoListCommand(YumCommand): except yum.Errors.RepoError: if verbose: raise @@ -161794,7 +161936,7 @@ index 4dcbea7..52c3127 100644 repos = base.repos.repos.values() repos.sort() -@@ -924,111 +1967,108 @@ class RepoListCommand(YumCommand): +@@ -924,111 +1970,108 @@ class RepoListCommand(YumCommand): ui_enabled = dhibeg + _('disabled') + hiend ui_endis_wid = utf8_width(_('disabled')) @@ -161808,7 +161950,7 @@ index 4dcbea7..52c3127 100644 - cols.append((rid, repo.name, - (ui_enabled, ui_endis_wid), ui_num)) + if not verbose: -+ rid = str(repo) ++ rid = repo.ui_id # can't use str() + if enabled and repo.metalink: + mdts = repo.metalink_data.repomd.timestamp + if mdts > repo.repoXML.timestamp: @@ -161820,7 +161962,7 @@ index 4dcbea7..52c3127 100644 + md = repo.repoXML else: + md = None -+ out = [base.fmtKeyValFill(_("Repo-id : "), repo), ++ out = [base.fmtKeyValFill(_("Repo-id : "), repo.ui_id), + base.fmtKeyValFill(_("Repo-name : "), repo.name)] + + if force_show or extcmds: @@ -161994,12 +162136,12 @@ index 4dcbea7..52c3127 100644 - base.verbose_logger.log(logginglevels.DEBUG_3, - "%s\n", - "\n".join(map(misc.to_unicode, out))) -+ base.verbose_logger.log(logginglevels.DEBUG_3, "%s\n", ++ base.verbose_logger.info("%s\n", + "\n".join(map(misc.to_unicode, out))) if not verbose and cols: # Work out the first (id) and last (enabled/disalbed/count), -@@ -1088,21 +2128,54 @@ class RepoListCommand(YumCommand): +@@ -1088,21 +2131,54 @@ class RepoListCommand(YumCommand): return 0, ['repolist: ' +to_unicode(locale.format("%d", tot_num, True))] def needTs(self, base, basecmd, extcmds): @@ -162054,7 +162196,7 @@ index 4dcbea7..52c3127 100644 if len(extcmds) == 0: base.usage() raise cli.CliError -@@ -1147,28 +2220,85 @@ class HelpCommand(YumCommand): +@@ -1147,28 +2223,85 @@ class HelpCommand(YumCommand): return help_output def doCommand(self, base, basecmd, extcmds): @@ -162140,7 +162282,7 @@ index 4dcbea7..52c3127 100644 self.doneCommand(base, _("Setting up Reinstall Process")) try: return base.reinstallPkgs(extcmds) -@@ -1177,49 +2307,139 @@ class ReInstallCommand(YumCommand): +@@ -1177,49 +2310,139 @@ class ReInstallCommand(YumCommand): return 1, [to_unicode(e)] def getSummary(self): @@ -162281,7 +162423,7 @@ index 4dcbea7..52c3127 100644 vcmd = 'installed' if extcmds: vcmd = extcmds[0] -@@ -1308,7 +2528,7 @@ class VersionCommand(YumCommand): +@@ -1308,7 +2531,7 @@ class VersionCommand(YumCommand): str(data[2][grp]))) _append_repos(cols, data[3][grp]) except yum.Errors.YumBaseError, e: @@ -162290,7 +162432,7 @@ index 4dcbea7..52c3127 100644 if vcmd in ('available', 'all', 'group-available', 'group-all'): try: data = base.pkgSack.simpleVersion(not verbose, groups=groups) -@@ -1327,7 +2547,7 @@ class VersionCommand(YumCommand): +@@ -1327,7 +2550,7 @@ class VersionCommand(YumCommand): if verbose: _append_repos(cols, data[3][grp]) except yum.Errors.YumBaseError, e: @@ -162299,7 +162441,7 @@ index 4dcbea7..52c3127 100644 data = {'rid' : {}, 'ver' : {}} for (rid, ver) in cols: -@@ -1344,6 +2564,14 @@ class VersionCommand(YumCommand): +@@ -1344,6 +2567,14 @@ class VersionCommand(YumCommand): return 0, ['version'] def needTs(self, base, basecmd, extcmds): @@ -162314,7 +162456,7 @@ index 4dcbea7..52c3127 100644 vcmd = 'installed' if extcmds: vcmd = extcmds[0] -@@ -1354,23 +2582,62 @@ class VersionCommand(YumCommand): +@@ -1354,23 +2585,62 @@ class VersionCommand(YumCommand): class HistoryCommand(YumCommand): @@ -162378,7 +162520,7 @@ index 4dcbea7..52c3127 100644 return 2, ["Repeating transaction %u" % (old.tid,)] def _hcmd_undo(self, base, extcmds): -@@ -1426,12 +2693,57 @@ class HistoryCommand(YumCommand): +@@ -1426,12 +2696,57 @@ class HistoryCommand(YumCommand): def _hcmd_new(self, base, extcmds): base.history._create_db_file() @@ -162437,7 +162579,7 @@ index 4dcbea7..52c3127 100644 if extcmds and extcmds[0] not in cmds: base.logger.critical(_('Invalid history sub-command, use: %s.'), ", ".join(cmds)) -@@ -1444,6 +2756,19 @@ class HistoryCommand(YumCommand): +@@ -1444,6 +2759,19 @@ class HistoryCommand(YumCommand): raise cli.CliError def doCommand(self, base, basecmd, extcmds): @@ -162457,7 +162599,7 @@ index 4dcbea7..52c3127 100644 vcmd = 'list' if extcmds: vcmd = extcmds[0] -@@ -1468,12 +2793,26 @@ class HistoryCommand(YumCommand): +@@ -1468,12 +2796,26 @@ class HistoryCommand(YumCommand): ret = self._hcmd_rollback(base, extcmds) elif vcmd == 'new': ret = self._hcmd_new(base, extcmds) @@ -162484,7 +162626,7 @@ index 4dcbea7..52c3127 100644 vcmd = 'list' if extcmds: vcmd = extcmds[0] -@@ -1481,16 +2820,46 @@ class HistoryCommand(YumCommand): +@@ -1481,16 +2823,46 @@ class HistoryCommand(YumCommand): class CheckRpmdbCommand(YumCommand): @@ -162531,7 +162673,7 @@ index 4dcbea7..52c3127 100644 chkcmd = 'all' if extcmds: chkcmd = extcmds -@@ -1505,19 +2874,57 @@ class CheckRpmdbCommand(YumCommand): +@@ -1505,19 +2877,57 @@ class CheckRpmdbCommand(YumCommand): return rc, ['%s %s' % (basecmd, chkcmd)] def needTs(self, base, basecmd, extcmds): @@ -162589,7 +162731,7 @@ index 4dcbea7..52c3127 100644 if not extcmds: base.logger.critical(_("No saved transaction file specified.")) raise cli.CliError -@@ -1533,5 +2940,13 @@ class LoadTransactionCommand(YumCommand): +@@ -1533,5 +2943,13 @@ class LoadTransactionCommand(YumCommand): def needTs(self, base, basecmd, extcmds): diff --git a/yum.spec b/yum.spec index ecbe5eb..2d4321e 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 42%{?dist} +Release: 43%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -315,6 +315,10 @@ exit 0 %endif %changelog +* Fri Sep 7 2012 James Antill - 3.4.3-43 +- update to latest HEAD. +- Use .ui_id explicitly for backcompat. on strings, *sigh*. + * Sat Sep 1 2012 James Antill - 3.4.3-42 - update to latest HEAD. - Fix missing self. on last patch. From 9cc696d4caad604bc9df2306a6f1f205e1051306 Mon Sep 17 00:00:00 2001 From: James Antill Date: Wed, 17 Oct 2012 15:49:36 -0400 Subject: [PATCH 006/174] update to latest HEAD. - Add downloadonly into core, and enable background downloads. - Lots of minor fixes. --- commit-build.sh | 6 + diff-specs.sh | 7 + yum-HEAD.patch | 967 +++++++++++++++++++++++++++++++++--------------- yum.spec | 14 +- 4 files changed, 698 insertions(+), 296 deletions(-) create mode 100755 commit-build.sh create mode 100755 diff-specs.sh diff --git a/commit-build.sh b/commit-build.sh new file mode 100755 index 0000000..7094099 --- /dev/null +++ b/commit-build.sh @@ -0,0 +1,6 @@ +#! /bin/sh -e + +fedpkg clog +git commit -a -F clog +git push +fedpkg build diff --git a/diff-specs.sh b/diff-specs.sh new file mode 100755 index 0000000..e5b0ee2 --- /dev/null +++ b/diff-specs.sh @@ -0,0 +1,7 @@ +#! /bin/sh -e + +# yum-3.4.3-44.fc19 +ver=$(/usr/bin/fedpkg verrel | perl -lpe 's/-[^-]+$//') + +fedpkg prep > /dev/null +diff -u yum.spec $ver/yum.spec diff --git a/yum-HEAD.patch b/yum-HEAD.patch index e4c51b8..6aba05e 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -96,7 +96,7 @@ index 2f6154e..2e5a052 100644 diff --git a/cli.py b/cli.py old mode 100644 new mode 100755 -index 6056d38..adc3516 +index 6056d38..4122d5d --- a/cli.py +++ b/cli.py @@ -25,7 +25,7 @@ import sys @@ -384,13 +384,12 @@ index 6056d38..adc3516 stuff_to_download = True po = txmbr.po if po: -@@ -489,9 +536,21 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -489,9 +536,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput): else: self.reportDownloadSize(downloadpkgs, install_only) + cfr = self.tsInfo._check_future_rpmdbv + if (cfr is not None and -+ cfr[0] == self.tsInfo.state_counter and + self.tsInfo.futureRpmDBVersion() != cfr[1]): + msg = _("future rpmdb ver mismatched saved transaction version,") + if cfr[2]: @@ -407,7 +406,7 @@ index 6056d38..adc3516 self.verbose_logger.info(_('Exiting on user Command')) return -1 -@@ -609,12 +668,14 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -609,12 +667,14 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return resultobject.return_code def gpgsigcheck(self, pkgs): @@ -427,7 +426,7 @@ index 6056d38..adc3516 for po in pkgs: result, errmsg = self.sigCheckPkg(po) -@@ -623,7 +684,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -623,7 +683,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): continue elif result == 1: @@ -437,7 +436,7 @@ index 6056d38..adc3516 raise yum.Errors.YumBaseError, \ _('Refusing to automatically import keys when running ' \ 'unattended.\nUse "-y" to override.') -@@ -691,12 +753,62 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -691,12 +752,62 @@ class YumBaseCli(yum.YumBase, output.YumOutput): ", ".join(matches)) self.verbose_logger.log(yum.logginglevels.INFO_2, msg) @@ -506,7 +505,7 @@ index 6056d38..adc3516 # get the list of available packages # iterate over the user's list # add packages to Transaction holding class if they match. -@@ -710,11 +822,36 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -710,11 +821,36 @@ 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))): @@ -545,7 +544,7 @@ index 6056d38..adc3516 except yum.Errors.InstallError: self.verbose_logger.log(yum.logginglevels.INFO_2, _('No package %s%s%s available.'), -@@ -723,6 +860,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -723,6 +859,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): self._maybeYouMeant(arg) else: done = True @@ -553,7 +552,7 @@ index 6056d38..adc3516 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 +870,27 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -732,9 +869,27 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [_('Nothing to do')] def updatePkgs(self, userlist, quiet=0, update_to=False): @@ -584,7 +583,7 @@ index 6056d38..adc3516 # 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,21 +901,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -745,21 +900,18 @@ class YumBaseCli(yum.YumBase, output.YumOutput): else: # go through the userlist - look for items that are local rpms. If we find them @@ -615,7 +614,7 @@ index 6056d38..adc3516 if len(self.tsInfo) > oldcount: change = len(self.tsInfo) - oldcount -@@ -770,9 +923,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -770,9 +922,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): # Note that we aren't in __init__ yet for a couple of reasons, but we # probably will get there for 3.2.28. def distroSyncPkgs(self, userlist): @@ -643,7 +642,7 @@ index 6056d38..adc3516 level = 'diff' if userlist and userlist[0] in ('full', 'diff', 'different'): -@@ -831,6 +999,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -831,6 +998,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): continue nayi = napkg.yumdb_info @@ -651,7 +650,7 @@ index 6056d38..adc3516 for apkg in self.pkgSack.searchPkgTuple(napkg.pkgtup): if ('checksum_type' in nayi and 'checksum_data' in nayi and -@@ -865,15 +1034,54 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -865,15 +1033,54 @@ class YumBaseCli(yum.YumBase, output.YumOutput): else: return 0, [_('No Packages marked for Distribution Synchronization')] @@ -712,7 +711,7 @@ index 6056d38..adc3516 if not rms: self._checkMaybeYouMeant(arg, always_output=False, rpmdb_only=True) all_rms.extend(rms) -@@ -884,12 +1092,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -884,12 +1091,24 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [_('No Packages marked for removal')] def downgradePkgs(self, userlist): @@ -740,7 +739,7 @@ index 6056d38..adc3516 for arg in userlist: if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or os.path.exists(arg))): -@@ -905,26 +1125,44 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -905,26 +1124,44 @@ class YumBaseCli(yum.YumBase, output.YumOutput): self.term.MODE['bold'], arg, self.term.MODE['normal']) self._maybeYouMeant(arg) @@ -789,7 +788,7 @@ index 6056d38..adc3516 except yum.Errors.ReinstallRemoveError: self._checkMaybeYouMeant(arg, always_output=False) except yum.Errors.ReinstallInstallError, e: -@@ -940,15 +1178,31 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -940,15 +1177,31 @@ 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) @@ -824,7 +823,7 @@ index 6056d38..adc3516 # read in each package into a YumLocalPackage Object # append it to self.localPackages # check if it can be installed or updated based on nevra versus rpmdb -@@ -972,20 +1226,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -972,20 +1225,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [_('Nothing to do')] def returnPkgLists(self, extcmds, installed_available=False): @@ -864,7 +863,7 @@ index 6056d38..adc3516 special = ['available', 'installed', 'all', 'extras', 'updates', 'recent', 'obsoletes'] -@@ -1017,8 +1276,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1017,8 +1275,25 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return ypl def search(self, args): @@ -892,7 +891,7 @@ index 6056d38..adc3516 # call the yum module search function with lists of tags to search # and what to search for -@@ -1108,9 +1384,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1108,9 +1383,20 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, matching def deplist(self, args): @@ -915,7 +914,7 @@ index 6056d38..adc3516 pkgs = [] for arg in args: if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or -@@ -1131,10 +1418,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1131,10 +1417,19 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [] def provides(self, args): @@ -939,7 +938,7 @@ index 6056d38..adc3516 old_sdup = self.conf.showdupesfromrepos # For output, as searchPackageProvides() is always in showdups mode self.conf.showdupesfromrepos = True -@@ -1147,6 +1443,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1147,6 +1442,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput): paths = set(sys.path + os.environ['PATH'].split(':')) nargs = [] for arg in args: @@ -948,7 +947,7 @@ index 6056d38..adc3516 if yum.misc.re_filename(arg) or yum.misc.re_glob(arg): continue for path in paths: -@@ -1163,20 +1461,77 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1163,20 +1460,77 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 0, [] def resolveDepCli(self, args): @@ -1031,7 +1030,7 @@ index 6056d38..adc3516 hdrcode = pkgcode = xmlcode = dbcode = expccode = 0 pkgresults = hdrresults = xmlresults = dbresults = expcresults = [] msg = self.fmtKeyValFill(_('Cleaning repos: '), -@@ -1228,130 +1583,257 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1228,130 +1582,257 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return code, [] def returnGroupLists(self, userlist): @@ -1369,7 +1368,7 @@ index 6056d38..adc3516 except yum.Errors.GroupsError: self.logger.critical(_('Warning: Group %s does not exist.'), group_string) continue -@@ -1368,17 +1850,61 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1368,17 +1849,61 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return 2, [P_('%d package to Install', '%d packages to Install', len(pkgs_used)) % len(pkgs_used)] def removeGroups(self, grouplist): @@ -1439,7 +1438,7 @@ index 6056d38..adc3516 if not pkgs_used: return 0, [_('No packages to remove from groups')] -@@ -1389,7 +1915,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1389,7 +1914,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput): def _promptWanted(self): # shortcut for the always-off/always-on options @@ -1448,7 +1447,7 @@ index 6056d38..adc3516 return False if self.conf.alwaysprompt: return True -@@ -1400,7 +1926,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1400,7 +1925,6 @@ class YumBaseCli(yum.YumBase, output.YumOutput): # package wasn't explictly given on the command line for txmbr in self.tsInfo.getMembers(): if txmbr.isDep or \ @@ -1456,7 +1455,7 @@ index 6056d38..adc3516 txmbr.name not in self.extcmds: return True -@@ -1408,11 +1933,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1408,11 +1932,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return False def usage(self): @@ -1470,7 +1469,7 @@ index 6056d38..adc3516 sys.stdout.write(self.optparser.get_usage()) def _installable(self, pkg, ematch=False): -@@ -1468,9 +1993,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): +@@ -1468,9 +1992,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput): return False class YumOptionParser(OptionParser): @@ -1482,7 +1481,7 @@ index 6056d38..adc3516 def __init__(self,base, **kwargs): # check if this is called with a utils=True/False parameter -@@ -1488,13 +2013,23 @@ class YumOptionParser(OptionParser): +@@ -1488,13 +2012,23 @@ class YumOptionParser(OptionParser): self._addYumBasicOptions() def error(self, msg): @@ -1508,7 +1507,7 @@ index 6056d38..adc3516 try: args = _filtercmdline( ('--noplugins','--version','-q', '-v', "--quiet", "--verbose"), -@@ -1521,7 +2056,15 @@ class YumOptionParser(OptionParser): +@@ -1521,7 +2055,15 @@ class YumOptionParser(OptionParser): return ret def setupYumConfig(self, args=None): @@ -1525,7 +1524,7 @@ index 6056d38..adc3516 if not args: (opts, cmds) = self.parse_args() else: -@@ -1533,16 +2076,20 @@ class YumOptionParser(OptionParser): +@@ -1533,16 +2075,22 @@ class YumOptionParser(OptionParser): try: # config file is parsed and moving us forward # set some things in it. @@ -1536,13 +1535,16 @@ index 6056d38..adc3516 # Handle remaining options if opts.assumeyes: - self.base.conf.assumeyes =1 -+ self.base.conf.assumeyes = 1 -+ if opts.assumeno: -+ self.base.conf.assumeno = 1 - +- - # Instead of going cache-only for a non-root user, try to use a - # user writable cachedir. If that fails fall back to cache-only. - if opts.cacheonly: ++ self.base.conf.assumeyes = 1 ++ if opts.assumeno: ++ self.base.conf.assumeno = 1 ++ self.base.conf.downloadonly = opts.dlonly ++ self.base.conf.downloaddir = opts.dldir ++ + # Treat users like root as much as possible: + if not self.base.setCacheDir(): self.base.conf.cache = 1 @@ -1551,7 +1553,7 @@ index 6056d38..adc3516 self.base.conf.cache = 1 if opts.obsoletes: -@@ -1610,10 +2157,6 @@ class YumOptionParser(OptionParser): +@@ -1610,10 +2158,6 @@ class YumOptionParser(OptionParser): self.base.usage() sys.exit(1) @@ -1562,7 +1564,7 @@ index 6056d38..adc3516 # Disable all gpg key checking, if requested. if opts.nogpgcheck: # Altering the normal configs. doesn't work too well, esp. with -@@ -1640,6 +2183,14 @@ class YumOptionParser(OptionParser): +@@ -1640,10 +2184,18 @@ class YumOptionParser(OptionParser): sys.exit(1) def getRoot(self,opts): @@ -1577,7 +1579,12 @@ index 6056d38..adc3516 self._checkAbsInstallRoot(opts) # If the conf file is inside the installroot - use that. # otherwise look for it in the normal root -@@ -1701,6 +2252,9 @@ class YumOptionParser(OptionParser): +- if opts.installroot: ++ if opts.installroot and opts.installroot.lstrip('/'): + 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 +2253,9 @@ class YumOptionParser(OptionParser): group.add_option("--showduplicates", dest="showdupesfromrepos", action="store_true", help=_("show duplicates, in repos, in list/search commands")) @@ -1587,7 +1594,7 @@ index 6056d38..adc3516 group.add_option("-e", "--errorlevel", dest="errorlevel", default=None, help=_("error output level"), type='int', metavar='[error level]') -@@ -1713,6 +2267,10 @@ class YumOptionParser(OptionParser): +@@ -1713,6 +2268,10 @@ class YumOptionParser(OptionParser): help=_("verbose operation")) group.add_option("-y", "--assumeyes", dest="assumeyes", action="store_true", help=_("answer yes for all questions")) @@ -1598,9 +1605,20 @@ index 6056d38..adc3516 group.add_option("--version", action="store_true", help=_("show Yum version and exit")) group.add_option("--installroot", help=_("set install root"), +@@ -1748,6 +2307,10 @@ 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")) ++ group.add_option("--downloadonly", dest="dlonly", action="store_true", ++ help=_("don't update, just download")) ++ group.add_option("--downloaddir", dest="dldir", default=None, ++ help=_("specifies an alternate directory to store packages")) + group.add_option("", "--setopt", dest="setopts", default=[], + action="append", help=_("set arbitrary config and repo options")) + diff --git a/completion-helper.py b/completion-helper.py new file mode 100755 -index 0000000..0e4b96b +index 0000000..05801d1 --- /dev/null +++ b/completion-helper.py @@ -0,0 +1,90 @@ @@ -1629,7 +1647,7 @@ index 0000000..0e4b96b + +import cli +import yumcommands -+from yum.Errors import GroupsError ++from yum.Errors import GroupsError, ConfigError + + +class GroupsCompletionCommand(yumcommands.GroupsCommand): @@ -1682,11 +1700,11 @@ index 0000000..0e4b96b + base.registerCommand(RepoListCompletionCommand()) + base.getOptionsConfig(args) + base.parseCommands() -+ for repo in base.repos.listEnabled(): -+ repo.skip_if_unavailable = True + try: ++ for repo in base.repos.listEnabled(): ++ repo.skip_if_unavailable = True + base.doCommands() -+ except GroupsError, e: ++ except (GroupsError, ConfigError), e: + base.logger.error(e) + +if __name__ == "__main__": @@ -2293,7 +2311,7 @@ index 0000000..d2a0ed1 +if __name__ == "__main__": + generateAll(os.getcwd(), os.getcwd()) diff --git a/docs/yum.8 b/docs/yum.8 -index 1a8202a..dab01f6 100644 +index 1a8202a..65ff448 100644 --- a/docs/yum.8 +++ b/docs/yum.8 @@ -52,6 +52,7 @@ gnome\-packagekit application\&. @@ -2563,18 +2581,24 @@ index 1a8202a..dab01f6 100644 options are: 'critical', 'emergency', 'error', 'warn' and 'debug'. .br Configuration Option: \fBrpmverbosity\fP -@@ -506,7 +583,8 @@ option will corrupt your cache (and you can use $releasever in your cachedir +@@ -506,7 +583,14 @@ option will corrupt your cache (and you can use $releasever in your cachedir configuration to stop this). .PP .IP "\fB\-t, \-\-tolerant\fP" -This option currently does nothing. +This option makes yum go slower, checking for things that shouldn't be possible +making it more tolerant of external errors. ++.br ++.IP "\fB\-\-downloadonly\fP" ++Don't update, just download. ++.br ++.IP "\fB\-\-downloaddir=directory\fP" ++Specifies an alternate directory to store packages. .br .IP "\fB\-\-setopt=option=value\fP" Set any config option in yum config or repo files. For options in the global diff --git a/docs/yum.conf.5 b/docs/yum.conf.5 -index 515aa73..01facf8 100644 +index 515aa73..029fa75 100644 --- a/docs/yum.conf.5 +++ b/docs/yum.conf.5 @@ -114,15 +114,27 @@ are causing problems from the transaction. @@ -2706,7 +2730,7 @@ index 515aa73..01facf8 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, -@@ -593,8 +667,50 @@ See color_list_installed_older for possible values. +@@ -593,8 +667,53 @@ See color_list_installed_older for possible values. When removing packages (by removal, update or obsoletion) go through each package's dependencies. If any of them are no longer required by any other package then also mark them to be removed. @@ -2739,12 +2763,15 @@ index 515aa73..01facf8 100644 +Should the load-ts command ignore packages that are missing. This includes +packages in the TS to be removed, which aren't installed, and packages in the +TS to be added, which aren't available. ++If this is set to true, and an rpm is missing then loadts_ignorenewrpm is ++automatically set to true. +Boolean (1, 0, True, False, yes, no) Defaults to False + +.IP +\fBloadts_ignorerpm\fR +Should the load-ts command ignore the rpmdb version (yum version nogroups) or +abort if there is a mismatch between the TS file and the current machine. ++If this is set to true, then loadts_ignorenewrpm is automatically set to true. +Boolean (1, 0, True, False, yes, no) Defaults to False + +.IP @@ -2757,7 +2784,7 @@ index 515aa73..01facf8 100644 .SH "[repository] OPTIONS" -@@ -755,6 +871,11 @@ repository. +@@ -755,6 +874,11 @@ repository. Overrides the \fBbandwidth\fR option from the [main] section for this repository. @@ -2769,7 +2796,7 @@ index 515aa73..01facf8 100644 .IP \fBsslcacert \fR -@@ -776,6 +897,10 @@ repository. +@@ -776,6 +900,10 @@ repository. Overrides the \fBsslclientkey\fR option from the [main] section for this repository. @@ -2780,7 +2807,7 @@ index 515aa73..01facf8 100644 .IP \fBmetadata_expire \fR -@@ -824,7 +949,11 @@ as greater/less than any other. defaults to 1000 +@@ -824,7 +952,11 @@ 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. @@ -3146,7 +3173,7 @@ index c60fa08..0000000 -ts run -exit diff --git a/etc/yum.bash b/etc/yum.bash -index f1e06e8..b21c594 100644 +index f1e06e8..d484f8d 100644 --- a/etc/yum.bash +++ b/etc/yum.bash @@ -1,53 +1,17 @@ @@ -3220,16 +3247,20 @@ index f1e06e8..b21c594 100644 COMPREPLY+=( $( compgen -W '$( command grep -il "^\s*enabled\s*=\s*$val" \ /etc/yum/pluginconf.d/*.conf 2>/dev/null \ | sed -ne "s|^.*/\([^/]\{1,\}\)\.conf$|\1|p" )' -- "$2" ) ) -@@ -75,7 +39,7 @@ _yum_baseopts() +@@ -75,9 +39,10 @@ _yum_baseopts() { local opts='--help --tolerant --cacheonly --config --randomwait --debuglevel --showduplicates --errorlevel --rpmverbosity --quiet - --verbose --assumeyes --version --installroot --enablerepo + --verbose --assumeyes --assumeno --version --installroot --enablerepo --disablerepo --exclude --disableexcludes --obsoletes --noplugins - --nogpgcheck --skip-broken --color --releasever --setopt' +- --nogpgcheck --skip-broken --color --releasever --setopt' ++ --nogpgcheck --skip-broken --color --releasever --setopt --downloadonly ++ --downloaddir' [[ $COMP_LINE == *--noplugins* ]] || \ -@@ -89,6 +53,16 @@ _yum_transactions() + opts+=" --disableplugin --enableplugin" + printf %s "$opts" +@@ -89,6 +54,16 @@ _yum_transactions() sed -ne 's/^[[:space:]]*\([0-9]\{1,\}\).*/\1/p' )" -- "$cur" ) ) } @@ -3246,7 +3277,7 @@ index f1e06e8..b21c594 100644 # arguments: # 1 = current word to be completed # 2 = previous word -@@ -119,17 +93,17 @@ _yum_complete_baseopts() +@@ -119,17 +94,17 @@ _yum_complete_baseopts() ;; --enablerepo) @@ -3267,7 +3298,7 @@ index f1e06e8..b21c594 100644 COMPREPLY=( $( compgen -W '${COMPREPLY[@]} all main' -- "$1" ) ) return 0 ;; -@@ -183,16 +157,16 @@ _yum() +@@ -183,16 +158,16 @@ _yum() # Commands offered as completions local cmds=( check check-update clean deplist distro-sync downgrade @@ -3288,7 +3319,7 @@ index f1e06e8..b21c594 100644 [[ ${words[i]} == $c ]] && cmd=$c && break done done -@@ -205,13 +179,12 @@ _yum() +@@ -205,13 +180,12 @@ _yum() return 0 ;; @@ -3304,7 +3335,7 @@ index f1e06e8..b21c594 100644 COMPREPLY=( $( compgen -W 'expire-cache packages headers metadata cache dbcache all' -- "$cur" ) ) return 0 -@@ -224,59 +197,83 @@ _yum() +@@ -224,59 +198,83 @@ _yum() ;; distro-sync|distribution-synchronization) @@ -3404,7 +3435,7 @@ index f1e06e8..b21c594 100644 ;; esac return 0 -@@ -288,42 +285,56 @@ _yum() +@@ -288,42 +286,56 @@ _yum() ;; install) @@ -3468,7 +3499,7 @@ index f1e06e8..b21c594 100644 COMPREPLY=( $( compgen -W 'all installed available nogroups grouplist groupinfo' -- "$cur" ) ) return 0 -@@ -337,7 +348,11 @@ _yum() +@@ -337,7 +349,11 @@ _yum() $split && return 0 @@ -151098,10 +151129,10 @@ index 1ce4720..25e3022 gobject.threads_init() dbus.glib.threads_init() diff --git a/yum.spec b/yum.spec -index abd203f..65c62a9 100644 +index abd203f..4ad6804 100644 --- a/yum.spec +++ b/yum.spec -@@ -1,24 +1,51 @@ +@@ -1,24 +1,53 @@ -Summary: RPM installer/updater +%define move_yum_conf_back 1 +%define auto_sitelib 1 @@ -151155,11 +151186,13 @@ index abd203f..65c62a9 100644 Requires: yum-metadata-parser >= 1.1.0 -Requires: python-iniparse Requires: pygpgme ++# rawhide is >= 0.5.3-7.fc18 ... as this is added. ++Requires: pyliblzma + Conflicts: rpm >= 5-0 # Zif is a re-implementation of yum in C, however: # -@@ -34,18 +61,26 @@ Conflicts: rpm >= 5-0 +@@ -34,18 +63,28 @@ Conflicts: rpm >= 5-0 # zif experts). # # ...so we have two sane choices: i) Conflict with it. 2) Stop developing yum. @@ -151188,12 +151221,14 @@ index abd203f..65c62a9 100644 +Provides: yum-protect-packages = 1.1.27-0.yum +Provides: yum-plugin-protect-packages = 1.1.27-0.yum +Obsoletes: yum-plugin-download-order <= 0.2-2 ++Obsoletes: yum-plugin-downloadonly <= 1.1.31-6.fc19 ++Provides: yum-plugin-downloadonly = 3.4.3-44.yum +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + %description Yum is a utility that can check for and automatically download and -@@ -58,9 +93,11 @@ Group: Applications/System +@@ -58,9 +97,11 @@ Group: Applications/System Requires: yum = %{version}-%{release} Requires: dbus-python Requires: pygobject2 @@ -151207,7 +151242,7 @@ index abd203f..65c62a9 100644 Requires(postun): /sbin/service -@@ -83,18 +120,46 @@ Requires(postun): /sbin/service +@@ -83,18 +124,46 @@ Requires(postun): /sbin/service These are the files needed to run yum updates as a cron job. Install this package if you want auto yum updates nightly via cron. @@ -151256,7 +151291,7 @@ index abd203f..65c62a9 100644 # Ghost files: mkdir -p $RPM_BUILD_ROOT/var/lib/yum/history -@@ -102,12 +167,18 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/yum/plugins +@@ -102,12 +171,18 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/yum/plugins mkdir -p $RPM_BUILD_ROOT/var/lib/yum/yumdb touch $RPM_BUILD_ROOT/var/lib/yum/uuid @@ -151275,7 +151310,7 @@ index abd203f..65c62a9 100644 %post updatesd /sbin/chkconfig --add yum-updatesd /sbin/service yum-updatesd condrestart >/dev/null 2>&1 -@@ -119,6 +190,7 @@ if [ $1 = 0 ]; then +@@ -119,6 +194,7 @@ if [ $1 = 0 ]; then /sbin/service yum-updatesd stop >/dev/null 2>&1 fi exit 0 @@ -151283,7 +151318,7 @@ index abd203f..65c62a9 100644 %post cron -@@ -165,21 +237,30 @@ exit 0 +@@ -165,21 +241,30 @@ exit 0 %files -f %{name}.lang @@ -151319,7 +151354,7 @@ index abd203f..65c62a9 100644 %dir /var/cache/yum %dir /var/lib/yum %ghost /var/lib/yum/uuid -@@ -188,20 +269,24 @@ exit 0 +@@ -188,20 +273,24 @@ exit 0 %ghost /var/lib/yum/yumdb %{_mandir}/man*/yum.* %{_mandir}/man*/yum-shell* @@ -151351,7 +151386,7 @@ index abd203f..65c62a9 100644 %files updatesd %defattr(-, root, root) %config(noreplace) %{_sysconfdir}/yum/yum-updatesd.conf -@@ -210,8 +295,12 @@ exit 0 +@@ -210,8 +299,12 @@ exit 0 %{_datadir}/yum-cli/yumupd.py* %{_sbindir}/yum-updatesd %{_mandir}/man*/yum-updatesd* @@ -151392,10 +151427,18 @@ index c1af4ad..e3e3956 100644 pass diff --git a/yum/__init__.py b/yum/__init__.py -index 99039e0..198dc6d 100644 +index 99039e0..604ccce 100644 --- a/yum/__init__.py +++ b/yum/__init__.py -@@ -46,8 +46,13 @@ import operator +@@ -21,6 +21,7 @@ The Yum RPM software updater. + import os + import os.path + import rpm ++import sys + + def _rpm_ver_atleast(vertup): + """ Check if rpm is at least the current vertup. Can return False/True/None +@@ -46,8 +47,13 @@ import operator import tempfile import yum.i18n @@ -151411,7 +151454,7 @@ index 99039e0..198dc6d 100644 import config from config import ParsingError, ConfigParser -@@ -73,6 +78,7 @@ import logginglevels +@@ -73,6 +79,7 @@ import logginglevels import yumRepo import callbacks import yum.history @@ -151419,7 +151462,7 @@ index 99039e0..198dc6d 100644 import warnings warnings.simplefilter("ignore", Errors.YumFutureDeprecationWarning) -@@ -82,7 +88,7 @@ from packages import YumAvailablePackage, YumLocalPackage, YumInstalledPackage +@@ -82,7 +89,7 @@ from packages import YumAvailablePackage, YumLocalPackage, YumInstalledPackage from packages import YumUrlPackage, YumNotFoundPackage from constants import * from yum.rpmtrans import RPMTransaction,SimpleCliCallBack @@ -151428,7 +151471,7 @@ index 99039e0..198dc6d 100644 import string import StringIO -@@ -102,10 +108,12 @@ default_grabber.opts.user_agent += " yum/" + __version__ +@@ -102,10 +109,12 @@ default_grabber.opts.user_agent += " yum/" + __version__ class _YumPreBaseConf: @@ -151445,7 +151488,7 @@ index 99039e0..198dc6d 100644 def __init__(self): self.fn = '/etc/yum/yum.conf' self.root = '/' -@@ -125,12 +133,15 @@ class _YumPreBaseConf: +@@ -125,12 +134,15 @@ class _YumPreBaseConf: class _YumPreRepoConf: @@ -151465,7 +151508,7 @@ index 99039e0..198dc6d 100644 self.callback = None self.failure_callback = None self.interrupt_callback = None -@@ -164,11 +175,11 @@ class _YumCostExclude: +@@ -164,11 +176,11 @@ class _YumCostExclude: return False class YumBase(depsolve.Depsolve): @@ -151482,7 +151525,7 @@ index 99039e0..198dc6d 100644 def __init__(self): depsolve.Depsolve.__init__(self) self._conf = None -@@ -177,6 +188,7 @@ class YumBase(depsolve.Depsolve): +@@ -177,6 +189,7 @@ class YumBase(depsolve.Depsolve): self._up = None self._comps = None self._history = None @@ -151490,7 +151533,7 @@ index 99039e0..198dc6d 100644 self._pkgSack = None self._lockfile = None self._tags = None -@@ -204,6 +216,7 @@ class YumBase(depsolve.Depsolve): +@@ -204,6 +217,7 @@ class YumBase(depsolve.Depsolve): self.run_with_package_names = set() self._cleanup = [] @@ -151498,7 +151541,7 @@ index 99039e0..198dc6d 100644 def __del__(self): self.close() -@@ -213,10 +226,15 @@ class YumBase(depsolve.Depsolve): +@@ -213,10 +227,15 @@ class YumBase(depsolve.Depsolve): for cb in self._cleanup: cb() def close(self): @@ -151514,7 +151557,7 @@ index 99039e0..198dc6d 100644 if self._repos: self._repos.close() -@@ -225,15 +243,33 @@ class YumBase(depsolve.Depsolve): +@@ -225,15 +244,33 @@ class YumBase(depsolve.Depsolve): return transactioninfo.TransactionData() def doGenericSetup(self, cache=0): @@ -151550,7 +151593,7 @@ index 99039e0..198dc6d 100644 warnings.warn(_('doConfigSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -297,15 +333,17 @@ class YumBase(depsolve.Depsolve): +@@ -297,15 +334,17 @@ class YumBase(depsolve.Depsolve): # Try the old default fn = '/etc/yum.conf' @@ -151571,7 +151614,7 @@ index 99039e0..198dc6d 100644 if debuglevel != None: startupconf.debuglevel = debuglevel -@@ -336,6 +374,12 @@ class YumBase(depsolve.Depsolve): +@@ -336,6 +375,12 @@ class YumBase(depsolve.Depsolve): self._conf = config.readMainConfig(startupconf) @@ -151584,7 +151627,7 @@ index 99039e0..198dc6d 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 +411,36 @@ class YumBase(depsolve.Depsolve): +@@ -367,22 +412,36 @@ class YumBase(depsolve.Depsolve): def doLoggingSetup(self, debuglevel, errorlevel, syslog_ident=None, syslog_facility=None, syslog_device='/dev/log'): @@ -151628,7 +151671,7 @@ index 99039e0..198dc6d 100644 if repo_age is None: repo_age = os.stat(repofn)[8] -@@ -391,8 +449,7 @@ class YumBase(depsolve.Depsolve): +@@ -391,8 +450,7 @@ class YumBase(depsolve.Depsolve): try: parser.readfp(confpp_obj) except ParsingError, e: @@ -151638,7 +151681,7 @@ index 99039e0..198dc6d 100644 # Check sections in the .repo file that was just slurped up for section in parser.sections(): -@@ -429,7 +486,15 @@ class YumBase(depsolve.Depsolve): +@@ -429,7 +487,15 @@ class YumBase(depsolve.Depsolve): thisrepo.base_persistdir = self.conf._repos_persistdir @@ -151655,7 +151698,7 @@ index 99039e0..198dc6d 100644 if thisrepo.id in self.repo_setopts: for opt in self.repo_setopts[thisrepo.id].items: if not hasattr(thisrepo, opt): -@@ -440,6 +505,20 @@ class YumBase(depsolve.Depsolve): +@@ -440,6 +506,20 @@ class YumBase(depsolve.Depsolve): if validate and not validate(thisrepo): continue @@ -151676,7 +151719,7 @@ index 99039e0..198dc6d 100644 # Got our list of repo objects, add them to the repos # collection try: -@@ -448,8 +527,11 @@ class YumBase(depsolve.Depsolve): +@@ -448,8 +528,11 @@ class YumBase(depsolve.Depsolve): self.logger.warning(e) def getReposFromConfig(self): @@ -151690,7 +151733,7 @@ index 99039e0..198dc6d 100644 # Read .repo files from directories specified by the reposdir option # (typically /etc/yum/repos.d) repo_config_age = self.conf.config_file_age -@@ -466,18 +548,22 @@ class YumBase(depsolve.Depsolve): +@@ -466,18 +549,22 @@ class YumBase(depsolve.Depsolve): if os.path.isdir(reposdir): for repofn in sorted(glob.glob('%s/*.repo' % reposdir)): @@ -151718,7 +151761,7 @@ index 99039e0..198dc6d 100644 repo = yumRepo.YumRepository(section) try: repo.populate(parser, section, self.conf) -@@ -493,38 +579,40 @@ class YumBase(depsolve.Depsolve): +@@ -493,38 +580,40 @@ class YumBase(depsolve.Depsolve): repo.name = to_unicode(repo.name) # Set attributes not from the config file @@ -151781,7 +151824,7 @@ index 99039e0..198dc6d 100644 if isinstance(self.plugins, plugins.YumPlugins): raise RuntimeError(_("plugins already initialised")) -@@ -533,6 +621,8 @@ class YumBase(depsolve.Depsolve): +@@ -533,6 +622,8 @@ class YumBase(depsolve.Depsolve): def doRpmDBSetup(self): @@ -151790,7 +151833,7 @@ index 99039e0..198dc6d 100644 warnings.warn(_('doRpmDBSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -552,7 +642,8 @@ class YumBase(depsolve.Depsolve): +@@ -552,7 +643,8 @@ class YumBase(depsolve.Depsolve): return self._rpmdb def closeRpmDB(self): @@ -151800,7 +151843,7 @@ index 99039e0..198dc6d 100644 if self._rpmdb is not None: self._rpmdb.ts = None self._rpmdb.dropCachedData() -@@ -567,6 +658,12 @@ class YumBase(depsolve.Depsolve): +@@ -567,6 +659,12 @@ class YumBase(depsolve.Depsolve): self._ts = None def doRepoSetup(self, thisrepo=None): @@ -151813,7 +151856,7 @@ index 99039e0..198dc6d 100644 warnings.warn(_('doRepoSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -588,7 +685,8 @@ class YumBase(depsolve.Depsolve): +@@ -588,7 +686,8 @@ class YumBase(depsolve.Depsolve): prerepoconf = self.prerepoconf del self.prerepoconf @@ -151823,7 +151866,7 @@ index 99039e0..198dc6d 100644 self.repos.callback = prerepoconf.callback self.repos.setFailureCallback(prerepoconf.failure_callback) self.repos.setInterruptCallback(prerepoconf.interrupt_callback) -@@ -630,6 +728,14 @@ class YumBase(depsolve.Depsolve): +@@ -630,6 +729,14 @@ class YumBase(depsolve.Depsolve): self._repos = RepoStorage(self) def doSackSetup(self, archlist=None, thisrepo=None): @@ -151838,7 +151881,7 @@ index 99039e0..198dc6d 100644 warnings.warn(_('doSackSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -711,6 +817,9 @@ class YumBase(depsolve.Depsolve): +@@ -711,6 +818,9 @@ class YumBase(depsolve.Depsolve): def doUpdateSetup(self): @@ -151848,7 +151891,7 @@ index 99039e0..198dc6d 100644 warnings.warn(_('doUpdateSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -765,6 +874,8 @@ class YumBase(depsolve.Depsolve): +@@ -765,6 +875,8 @@ class YumBase(depsolve.Depsolve): return self._up def doGroupSetup(self): @@ -151857,7 +151900,20 @@ index 99039e0..198dc6d 100644 warnings.warn(_('doGroupSetup() will go away in a future version of Yum.\n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -829,7 +940,7 @@ class YumBase(depsolve.Depsolve): +@@ -820,16 +932,14 @@ class YumBase(depsolve.Depsolve): + self.verbose_logger.log(logginglevels.DEBUG_4, + _('Adding group file from repository: %s'), repo) + groupfile = repo.getGroups() +- # open it up as a file object so iterparse can cope with our compressed file +- if groupfile: +- groupfile = misc.repo_gen_decompress(groupfile, 'groups.xml', +- cached=repo.cache) +- # Do we want a RepoError here? +- ++ if not groupfile: ++ msg = _('Failed to retrieve group file for repository: %s') % repo ++ self.logger.critical(msg) ++ continue try: self._comps.add(groupfile) except (Errors.GroupsError,Errors.CompsException), e: @@ -151866,7 +151922,7 @@ index 99039e0..198dc6d 100644 self.logger.critical(msg) else: repo.groups_added = True -@@ -837,7 +948,10 @@ class YumBase(depsolve.Depsolve): +@@ -837,7 +947,10 @@ class YumBase(depsolve.Depsolve): if self._comps.compscount == 0: raise Errors.GroupsError, _('No Groups Available in any repository') @@ -151878,7 +151934,7 @@ index 99039e0..198dc6d 100644 self.verbose_logger.debug('group time: %0.3f' % (time.time() - group_st)) return self._comps -@@ -868,7 +982,7 @@ class YumBase(depsolve.Depsolve): +@@ -868,7 +981,7 @@ class YumBase(depsolve.Depsolve): # feed it into _tags.add() self._tags.add(repo.id, tag_sqlite) except (Errors.RepoError, Errors.PkgTagsError), e: @@ -151887,7 +151943,7 @@ index 99039e0..198dc6d 100644 self.logger.critical(msg) -@@ -881,9 +995,18 @@ class YumBase(depsolve.Depsolve): +@@ -881,9 +994,18 @@ class YumBase(depsolve.Depsolve): if self._history is None: pdb_path = self.conf.persistdir + "/history" self._history = yum.history.YumHistory(root=self.conf.installroot, @@ -151907,7 +151963,7 @@ index 99039e0..198dc6d 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,6 +1044,11 @@ class YumBase(depsolve.Depsolve): +@@ -921,6 +1043,11 @@ class YumBase(depsolve.Depsolve): fdel=lambda self: setattr(self, "_history", None), doc="Yum History Object") @@ -151919,7 +151975,7 @@ index 99039e0..198dc6d 100644 pkgtags = property(fget=lambda self: self._getTags(), fset=lambda self, value: setattr(self, "_tags",value), fdel=lambda self: setattr(self, "_tags", None), -@@ -928,9 +1056,10 @@ class YumBase(depsolve.Depsolve): +@@ -928,9 +1055,10 @@ class YumBase(depsolve.Depsolve): def doSackFilelistPopulate(self): @@ -151933,7 +151989,7 @@ index 99039e0..198dc6d 100644 necessary = False # I can't think of a nice way of doing this, we have to have the sack here -@@ -951,8 +1080,12 @@ class YumBase(depsolve.Depsolve): +@@ -951,8 +1079,12 @@ class YumBase(depsolve.Depsolve): self.repos.populateSack(mdtype='filelists') def yumUtilsMsg(self, func, prog): @@ -151948,7 +152004,7 @@ index 99039e0..198dc6d 100644 if self.rpmdb.contains(name="yum-utils"): return -@@ -964,8 +1097,17 @@ class YumBase(depsolve.Depsolve): +@@ -964,8 +1096,17 @@ class YumBase(depsolve.Depsolve): (hibeg, prog, hiend)) def buildTransaction(self, unfinished_transactions_check=True): @@ -151968,7 +152024,7 @@ index 99039e0..198dc6d 100644 if (unfinished_transactions_check and misc.find_unfinished_transactions(yumlibpath=self.conf.persistdir)): msg = _('There are unfinished transactions remaining. You might ' \ -@@ -1004,7 +1146,7 @@ class YumBase(depsolve.Depsolve): +@@ -1004,7 +1145,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 ) @@ -151977,7 +152033,7 @@ index 99039e0..198dc6d 100644 self.tsInfo.pkgSack.dropCachedData() # FIXME: This is horrible, see below and yummain. Maybe create a real -@@ -1044,6 +1186,37 @@ class YumBase(depsolve.Depsolve): +@@ -1044,6 +1185,39 @@ class YumBase(depsolve.Depsolve): if first.verEQ(other): continue msg = _('Protected multilib versions: %s != %s') @@ -151987,14 +152043,16 @@ index 99039e0..198dc6d 100644 + bigmsg = _("""\ + Multilib version problems found. This often means that the root +cause is something else and multilib version checking is just -+pointing it that there is a problem. Eg.: ++pointing out that there is a problem. Eg.: + + 1. You have an upgrade for %(name)s which is missing some + dependency that another package requires. Yum is trying to + solve this by installing an older version of %(name)s of the + different architecture. If you exclude the bad architecture + yum will tell you what the root cause is (which package -+ requires what). ++ requires what). You can try redoing the upgrade with ++ --exclude %(name)s.otherarch ... this should give you an error ++ message showing the root cause of the problem. + + 2. You have multiple architectures of %(name)s installed, but + yum can only see an upgrade for one of those arcitectures. @@ -152015,7 +152073,7 @@ index 99039e0..198dc6d 100644 xrestring.append(msg % (first, other)) if xrestring: rescode = 1 -@@ -1242,13 +1415,15 @@ class YumBase(depsolve.Depsolve): +@@ -1242,13 +1416,15 @@ class YumBase(depsolve.Depsolve): if None in pkgtup: return None return pkgtup @@ -152035,7 +152093,7 @@ index 99039e0..198dc6d 100644 if pkgtup is None: return self._not_found_i[pkgtup] = YumNotFoundPackage(pkgtup) -@@ -1454,8 +1629,14 @@ class YumBase(depsolve.Depsolve): +@@ -1454,8 +1630,14 @@ class YumBase(depsolve.Depsolve): return probs def runTransaction(self, cb): @@ -152051,7 +152109,7 @@ index 99039e0..198dc6d 100644 self.plugins.run('pretrans') # We may want to put this other places, eventually, but for now it's -@@ -1516,10 +1697,23 @@ class YumBase(depsolve.Depsolve): +@@ -1516,10 +1698,23 @@ class YumBase(depsolve.Depsolve): pass self._ts_save_file = None @@ -152075,7 +152133,7 @@ index 99039e0..198dc6d 100644 # make resultobject - just a plain yumgenericholder object resultobject = misc.GenericHolder() -@@ -1567,13 +1761,24 @@ class YumBase(depsolve.Depsolve): +@@ -1567,13 +1762,24 @@ 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): @@ -152105,7 +152163,7 @@ index 99039e0..198dc6d 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,9 +1789,16 @@ class YumBase(depsolve.Depsolve): +@@ -1584,9 +1790,16 @@ 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 @@ -152122,7 +152180,7 @@ index 99039e0..198dc6d 100644 for txmbr in self.tsInfo: if txmbr.output_state in TS_INSTALL_STATES: if not self.rpmdb.contains(po=txmbr.po): -@@ -1596,7 +1808,9 @@ class YumBase(depsolve.Depsolve): +@@ -1596,7 +1809,9 @@ 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 @@ -152132,7 +152190,7 @@ index 99039e0..198dc6d 100644 po = self.getInstalledPackageObject(txmbr.pkgtup) rpo = txmbr.po po.yumdb_info.from_repo = rpo.repoid -@@ -1630,6 +1844,10 @@ class YumBase(depsolve.Depsolve): +@@ -1630,6 +1845,10 @@ class YumBase(depsolve.Depsolve): if md: po.yumdb_info.from_repo_timestamp = str(md.timestamp) @@ -152143,7 +152201,7 @@ index 99039e0..198dc6d 100644 loginuid = misc.getloginuid() if txmbr.updates or txmbr.downgrades or txmbr.reinstall: if txmbr.updates: -@@ -1640,11 +1858,16 @@ class YumBase(depsolve.Depsolve): +@@ -1640,11 +1859,16 @@ class YumBase(depsolve.Depsolve): opo = po if 'installed_by' in opo.yumdb_info: po.yumdb_info.installed_by = opo.yumdb_info.installed_by @@ -152160,7 +152218,7 @@ index 99039e0..198dc6d 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 +1885,13 @@ class YumBase(depsolve.Depsolve): +@@ -1662,10 +1886,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 @@ -152174,7 +152232,7 @@ index 99039e0..198dc6d 100644 self.verbose_logger.log(logginglevels.DEBUG_2, 'What is this? %s' % txmbr.po) self.plugins.run('postverifytrans') -@@ -1680,10 +1906,11 @@ class YumBase(depsolve.Depsolve): +@@ -1680,10 +1907,11 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.debug('VerifyTransaction time: %0.3f' % (time.time() - vt_st)) def costExcludePackages(self): @@ -152190,7 +152248,7 @@ index 99039e0..198dc6d 100644 # if all the repo.costs are equal then don't bother running things costs = {} for r in self.repos.listEnabled(): -@@ -1705,10 +1932,12 @@ class YumBase(depsolve.Depsolve): +@@ -1705,10 +1933,12 @@ class YumBase(depsolve.Depsolve): done = True def excludePackages(self, repo=None): @@ -152206,7 +152264,7 @@ index 99039e0..198dc6d 100644 if "all" in self.conf.disable_excludes: return -@@ -1735,9 +1964,11 @@ class YumBase(depsolve.Depsolve): +@@ -1735,9 +1965,11 @@ class YumBase(depsolve.Depsolve): self.pkgSack.addPackageExcluder(repoid, exid,'exclude.match', match) def includePackages(self, repo): @@ -152221,7 +152279,7 @@ index 99039e0..198dc6d 100644 includelist = repo.getIncludePkgList() if len(includelist) == 0: -@@ -1757,8 +1988,11 @@ class YumBase(depsolve.Depsolve): +@@ -1757,8 +1989,11 @@ class YumBase(depsolve.Depsolve): self.pkgSack.addPackageExcluder(repo.id, exid, 'exclude.marked') def doLock(self, lockfile = YUM_PID_FILE): @@ -152235,7 +152293,7 @@ index 99039e0..198dc6d 100644 if self.conf.uid != 0: # If we are a user, assume we are using the root cache ... so don't # bother locking. -@@ -1774,38 +2008,26 @@ class YumBase(depsolve.Depsolve): +@@ -1774,38 +2009,26 @@ class YumBase(depsolve.Depsolve): mypid=str(os.getpid()) while not self._lock(lockfile, mypid, 0644): @@ -152289,7 +152347,7 @@ index 99039e0..198dc6d 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 +2052,69 @@ class YumBase(depsolve.Depsolve): +@@ -1830,31 +2053,69 @@ class YumBase(depsolve.Depsolve): self._unlock(lockfile) self._lockfile = None @@ -152369,7 +152427,7 @@ index 99039e0..198dc6d 100644 failed = False if type(fo) is types.InstanceType: -@@ -1894,9 +2154,16 @@ class YumBase(depsolve.Depsolve): +@@ -1894,9 +2155,16 @@ class YumBase(depsolve.Depsolve): def verifyChecksum(self, fo, checksumType, csum): @@ -152389,7 +152447,7 @@ index 99039e0..198dc6d 100644 try: filesum = misc.checksum(checksumType, fo) except Errors.MiscError, e: -@@ -1908,6 +2175,17 @@ class YumBase(depsolve.Depsolve): +@@ -1908,6 +2176,17 @@ class YumBase(depsolve.Depsolve): return 0 def downloadPkgs(self, pkglist, callback=None, callback_total=None): @@ -152407,7 +152465,43 @@ index 99039e0..198dc6d 100644 def mediasort(apo, bpo): # FIXME: we should probably also use the mediaid; else we # could conceivably ping-pong between different disc1's -@@ -1979,8 +2257,9 @@ class YumBase(depsolve.Depsolve): +@@ -1943,6 +2222,7 @@ class YumBase(depsolve.Depsolve): + self.history.close() + + self.plugins.run('predownload', pkglist=pkglist) ++ downloadonly = getattr(self.conf, 'downloadonly', False) + repo_cached = False + remote_pkgs = [] + remote_size = 0 +@@ -1961,6 +2241,14 @@ class YumBase(depsolve.Depsolve): + self.verbose_logger.debug(_("using local copy of %s") %(po,)) + continue + ++ if downloadonly: ++ # download to temp file ++ rpmfile = po.localpath ++ po.localpath += '.%d.tmp' % os.getpid() ++ try: os.rename(rpmfile, po.localpath) ++ except OSError: pass ++ po.basepath # prefetch now; fails when repos are closed ++ + remote_pkgs.append(po) + remote_size += po.size + +@@ -1969,7 +2257,11 @@ class YumBase(depsolve.Depsolve): + # way to save this, report the error and return + if (self.conf.cache or repo_cached) and errors: + return errors +- ++ if downloadonly: ++ # close DBs, unlock ++ self.repos.close() ++ self.closeRpmDB() ++ self.doUnlock() + + remote_pkgs.sort(mediasort) + # This is kind of a hack and does nothing in non-Fedora versions, +@@ -1979,8 +2271,9 @@ class YumBase(depsolve.Depsolve): urlgrabber.progress.text_meter_total_size(remote_size) beg_download = time.time() i = 0 @@ -152418,7 +152512,7 @@ index 99039e0..198dc6d 100644 for po in remote_pkgs: # Recheck if the file is there, works around a couple of weird # edge cases. -@@ -1992,52 +2271,47 @@ class YumBase(depsolve.Depsolve): +@@ -1992,67 +2285,94 @@ class YumBase(depsolve.Depsolve): remote_size -= po.size if hasattr(urlgrabber.progress, 'text_meter_total_size'): urlgrabber.progress.text_meter_total_size(remote_size, @@ -152497,7 +152591,32 @@ index 99039e0..198dc6d 100644 if hasattr(urlgrabber.progress, 'text_meter_total_size'): urlgrabber.progress.text_meter_total_size(0) if callback_total is not None and not errors: -@@ -2052,7 +2326,22 @@ class YumBase(depsolve.Depsolve): + callback_total(remote_pkgs, remote_size, beg_download) + +- self.plugins.run('postdownload', pkglist=pkglist, errors=errors) ++ if downloadonly: ++ for po in remote_pkgs: ++ rpmfile = po.localpath.rsplit('.', 2)[0] ++ if po in errors: ++ # we may throw away partial file here- but we don't lock, ++ # so can't rename tempfile to rpmfile safely ++ misc.unlink_f(po.localpath) ++ if po not in errors: ++ # verifyPkg() didn't complain, so (potentially) ++ # overwriting another copy should not be a problem ++ os.rename(po.localpath, rpmfile) ++ po.localpath = rpmfile ++ else: ++ # XXX: Run unlocked? Skip this for now.. ++ self.plugins.run('postdownload', pkglist=pkglist, errors=errors) + + # Close curl object after we've downloaded everything. + if hasattr(urlgrabber.grabber, 'reset_curl_obj'): + urlgrabber.grabber.reset_curl_obj() + ++ if downloadonly and not errors: # caller handles errors ++ self.verbose_logger.info(_('exiting because --downloadonly specified')) ++ sys.exit(self.exit_code) return errors def verifyHeader(self, fo, po, raiseError): @@ -152521,7 +152640,7 @@ index 99039e0..198dc6d 100644 if type(fo) is types.InstanceType: fo = fo.filename -@@ -2076,9 +2365,12 @@ class YumBase(depsolve.Depsolve): +@@ -2076,9 +2396,12 @@ class YumBase(depsolve.Depsolve): return 1 def downloadHeader(self, po): @@ -152536,7 +152655,7 @@ index 99039e0..198dc6d 100644 if hasattr(po, 'pkgtype') and po.pkgtype == 'local': return -@@ -2122,15 +2414,17 @@ class YumBase(depsolve.Depsolve): +@@ -2122,15 +2445,17 @@ class YumBase(depsolve.Depsolve): return def sigCheckPkg(self, po): @@ -152562,7 +152681,7 @@ index 99039e0..198dc6d 100644 if self._override_sigchecks: check = False hasgpgkey = 0 -@@ -2181,6 +2475,9 @@ class YumBase(depsolve.Depsolve): +@@ -2181,6 +2506,9 @@ class YumBase(depsolve.Depsolve): return result, msg def cleanUsedHeadersPackages(self): @@ -152572,7 +152691,7 @@ index 99039e0..198dc6d 100644 filelist = [] for txmbr in self.tsInfo: if txmbr.po.state not in TS_INSTALL_STATES: -@@ -2218,27 +2515,42 @@ class YumBase(depsolve.Depsolve): +@@ -2218,27 +2546,42 @@ class YumBase(depsolve.Depsolve): _('%s removed'), fn) def cleanHeaders(self): @@ -152617,7 +152736,7 @@ index 99039e0..198dc6d 100644 cachedir = self.conf.persistdir + "/rpmdb-indexes/" if not os.path.exists(cachedir): filelist = [] -@@ -2272,8 +2584,29 @@ class YumBase(depsolve.Depsolve): +@@ -2272,8 +2615,29 @@ class YumBase(depsolve.Depsolve): def doPackageLists(self, pkgnarrow='all', patterns=None, showdups=None, ignore_case=False): @@ -152649,7 +152768,7 @@ index 99039e0..198dc6d 100644 if showdups is None: showdups = self.conf.showdupesfromrepos ygh = misc.GenericHolder(iter=pkgnarrow) -@@ -2323,10 +2656,22 @@ class YumBase(depsolve.Depsolve): +@@ -2323,10 +2687,22 @@ class YumBase(depsolve.Depsolve): key = (pkg.name, pkg.arch) if pkg.pkgtup in dinst: reinstall_available.append(pkg) @@ -152675,7 +152794,7 @@ index 99039e0..198dc6d 100644 # produce the updates list of tuples elif pkgnarrow == 'updates': -@@ -2461,14 +2806,13 @@ class YumBase(depsolve.Depsolve): +@@ -2461,14 +2837,13 @@ class YumBase(depsolve.Depsolve): def findDeps(self, pkgs): @@ -152695,7 +152814,7 @@ index 99039e0..198dc6d 100644 results = {} for pkg in pkgs: -@@ -2495,10 +2839,22 @@ class YumBase(depsolve.Depsolve): +@@ -2495,10 +2870,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): @@ -152722,7 +152841,7 @@ index 99039e0..198dc6d 100644 sql_fields = [] for f in fields: sql_fields.append(RPM_TO_SQLITE.get(f, f)) -@@ -2661,6 +3017,14 @@ class YumBase(depsolve.Depsolve): +@@ -2661,6 +3048,14 @@ class YumBase(depsolve.Depsolve): yield (po, vs) def searchPackageTags(self, criteria): @@ -152737,7 +152856,7 @@ index 99039e0..198dc6d 100644 results = {} # name = [(criteria, taglist)] for c in criteria: c = c.lower() -@@ -2677,11 +3041,16 @@ class YumBase(depsolve.Depsolve): +@@ -2677,11 +3072,16 @@ class YumBase(depsolve.Depsolve): return results def searchPackages(self, fields, criteria, callback=None): @@ -152759,7 +152878,7 @@ index 99039e0..198dc6d 100644 warnings.warn(_('searchPackages() will go away in a future version of Yum.\ Use searchGenerator() instead. \n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -2700,13 +3069,23 @@ class YumBase(depsolve.Depsolve): +@@ -2700,13 +3100,23 @@ class YumBase(depsolve.Depsolve): def searchPackageProvides(self, args, callback=None, callback_has_matchfor=False): @@ -152787,7 +152906,7 @@ index 99039e0..198dc6d 100644 else: isglob = True canBeFile = misc.re_filename(arg) -@@ -2723,7 +3102,7 @@ class YumBase(depsolve.Depsolve): +@@ -2723,7 +3133,7 @@ class YumBase(depsolve.Depsolve): where = self.returnPackagesByDep(arg) else: usedDepString = False @@ -152796,7 +152915,7 @@ index 99039e0..198dc6d 100644 self.verbose_logger.log(logginglevels.DEBUG_1, P_('Searching %d package', 'Searching %d packages', len(where)), len(where)) -@@ -2817,25 +3196,160 @@ class YumBase(depsolve.Depsolve): +@@ -2817,25 +3227,160 @@ class YumBase(depsolve.Depsolve): return matches @@ -152969,7 +153088,7 @@ index 99039e0..198dc6d 100644 if uservisible: if grp.user_visible: installed.append(grp) -@@ -2847,34 +3361,98 @@ class YumBase(depsolve.Depsolve): +@@ -2847,34 +3392,98 @@ class YumBase(depsolve.Depsolve): available.append(grp) else: available.append(grp) @@ -153078,7 +153197,7 @@ index 99039e0..198dc6d 100644 thesegroups = self.comps.return_groups(grpid) if not thesegroups: raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -2898,13 +3476,58 @@ class YumBase(depsolve.Depsolve): +@@ -2898,13 +3507,58 @@ class YumBase(depsolve.Depsolve): self.tsInfo.remove(txmbr.po.pkgtup) @@ -153144,7 +153263,7 @@ index 99039e0..198dc6d 100644 """ if not self.comps.has_group(grpid): -@@ -2920,6 +3543,9 @@ class YumBase(depsolve.Depsolve): +@@ -2920,6 +3574,9 @@ class YumBase(depsolve.Depsolve): if group_package_types: package_types = group_package_types @@ -153154,7 +153273,7 @@ index 99039e0..198dc6d 100644 for thisgroup in thesegroups: if thisgroup.selected: continue -@@ -2934,12 +3560,49 @@ class YumBase(depsolve.Depsolve): +@@ -2934,12 +3591,49 @@ class YumBase(depsolve.Depsolve): if 'optional' in package_types: pkgs.extend(thisgroup.optional_packages) @@ -153205,7 +153324,7 @@ index 99039e0..198dc6d 100644 except Errors.InstallError, e: self.verbose_logger.debug(_('No package named %s available to be installed'), pkg) -@@ -2953,7 +3616,9 @@ class YumBase(depsolve.Depsolve): +@@ -2953,7 +3647,9 @@ class YumBase(depsolve.Depsolve): group_conditionals = enable_group_conditionals count_cond_test = 0 @@ -153216,7 +153335,7 @@ index 99039e0..198dc6d 100644 for condreq, cond in thisgroup.conditional_packages.iteritems(): if self.isPackageInstalled(cond): try: -@@ -2990,17 +3655,22 @@ class YumBase(depsolve.Depsolve): +@@ -2990,17 +3686,22 @@ class YumBase(depsolve.Depsolve): if cond not in self.tsInfo.conditionals: self.tsInfo.conditionals[cond] = [] self.tsInfo.conditionals[cond].extend(pkgs) @@ -153245,7 +153364,7 @@ index 99039e0..198dc6d 100644 if not self.comps.has_group(grpid): raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -3008,7 +3678,8 @@ class YumBase(depsolve.Depsolve): +@@ -3008,7 +3709,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) @@ -153255,7 +153374,7 @@ index 99039e0..198dc6d 100644 for thisgroup in thesegroups: thisgroup.selected = False -@@ -3034,13 +3705,102 @@ class YumBase(depsolve.Depsolve): +@@ -3034,13 +3736,102 @@ class YumBase(depsolve.Depsolve): for pkg in self.tsInfo.conditionals.get(txmbr.name, []): self.tsInfo.remove(pkg.pkgtup) @@ -153364,7 +153483,7 @@ index 99039e0..198dc6d 100644 # look it up in the self.localPackages first: for po in self.localPackages: if po.pkgtup == pkgtup: -@@ -3049,7 +3809,7 @@ class YumBase(depsolve.Depsolve): +@@ -3049,7 +3840,7 @@ class YumBase(depsolve.Depsolve): pkgs = self.pkgSack.searchPkgTuple(pkgtup) if len(pkgs) == 0: @@ -153373,7 +153492,7 @@ index 99039e0..198dc6d 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 +3825,21 @@ class YumBase(depsolve.Depsolve): +@@ -3065,13 +3856,21 @@ class YumBase(depsolve.Depsolve): return result def getInstalledPackageObject(self, pkgtup): @@ -153400,7 +153519,7 @@ index 99039e0..198dc6d 100644 raise Errors.RpmDBError, _('Package tuple %s could not be found in rpmdb') % str(pkgtup) # Dito. FIXME from getPackageObject() for len() > 1 ... :) -@@ -3079,9 +3847,11 @@ class YumBase(depsolve.Depsolve): +@@ -3079,9 +3878,11 @@ class YumBase(depsolve.Depsolve): return po def gpgKeyCheck(self): @@ -153414,7 +153533,7 @@ index 99039e0..198dc6d 100644 gpgkeyschecked = self.conf.cachedir + '/.gpgkeyschecked.yum' if os.path.exists(gpgkeyschecked): return 1 -@@ -3106,9 +3876,13 @@ class YumBase(depsolve.Depsolve): +@@ -3106,9 +3907,13 @@ class YumBase(depsolve.Depsolve): return 1 def returnPackagesByDep(self, depstring): @@ -153430,7 +153549,7 @@ index 99039e0..198dc6d 100644 if not depstring: return [] -@@ -3135,9 +3909,16 @@ class YumBase(depsolve.Depsolve): +@@ -3135,9 +3940,16 @@ class YumBase(depsolve.Depsolve): return self.pkgSack.getProvides(depname, depflags, depver).keys() def returnPackageByDep(self, depstring): @@ -153450,7 +153569,7 @@ index 99039e0..198dc6d 100644 # we get all sorts of randomness here errstring = depstring if type(depstring) not in types.StringTypes: -@@ -3149,16 +3930,22 @@ class YumBase(depsolve.Depsolve): +@@ -3149,16 +3961,22 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _('No Package found for %s') % errstring ps = ListPackageSack(pkglist) @@ -153477,7 +153596,7 @@ index 99039e0..198dc6d 100644 if not depstring: return [] -@@ -3184,12 +3971,47 @@ class YumBase(depsolve.Depsolve): +@@ -3184,12 +4002,47 @@ class YumBase(depsolve.Depsolve): return self.rpmdb.getProvides(depname, depflags, depver).keys() @@ -153527,7 +153646,7 @@ index 99039e0..198dc6d 100644 if len(pkglist) == 0: -@@ -3198,14 +4020,23 @@ class YumBase(depsolve.Depsolve): +@@ -3198,14 +4051,23 @@ class YumBase(depsolve.Depsolve): if len(pkglist) == 1: return pkglist[0] @@ -153557,7 +153676,7 @@ index 99039e0..198dc6d 100644 returnlist = [] compatArchList = self.arch.get_arch_list(arch) multiLib = [] -@@ -3222,9 +4053,9 @@ class YumBase(depsolve.Depsolve): +@@ -3222,9 +4084,9 @@ class YumBase(depsolve.Depsolve): singleLib.append(po) # we now have three lists. find the best package(s) of each @@ -153570,7 +153689,7 @@ index 99039e0..198dc6d 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 +4069,7 @@ class YumBase(depsolve.Depsolve): +@@ -3238,7 +4100,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: @@ -153579,7 +153698,7 @@ index 99039e0..198dc6d 100644 if best.arch == "noarch": returnlist.append(no) else: -@@ -3246,7 +4077,7 @@ class YumBase(depsolve.Depsolve): +@@ -3246,7 +4108,7 @@ class YumBase(depsolve.Depsolve): if single: returnlist.append(single) # similar for the non-multilib case elif single: @@ -153588,7 +153707,7 @@ index 99039e0..198dc6d 100644 if best.arch == "noarch": returnlist.append(no) else: -@@ -3350,28 +4181,58 @@ class YumBase(depsolve.Depsolve): +@@ -3350,28 +4212,58 @@ class YumBase(depsolve.Depsolve): done = True slow = next_func(slow) @@ -153652,7 +153771,7 @@ index 99039e0..198dc6d 100644 try: txmbrs = self.groupRemove(group_string) except yum.Errors.GroupsError: -@@ -3387,6 +4248,8 @@ class YumBase(depsolve.Depsolve): +@@ -3387,6 +4279,8 @@ class YumBase(depsolve.Depsolve): assert pattern[0] == '@' grpid = pattern[1:] @@ -153661,7 +153780,7 @@ index 99039e0..198dc6d 100644 thesegroups = self.comps.return_groups(grpid) if not thesegroups: raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -3398,7 +4261,11 @@ class YumBase(depsolve.Depsolve): +@@ -3398,7 +4292,11 @@ class YumBase(depsolve.Depsolve): def _minus_deselect(self, pattern): """ Remove things from the transaction, like kickstart. """ assert pattern[0] == '-' @@ -153674,7 +153793,7 @@ index 99039e0..198dc6d 100644 if pat and pat[0] == '@': pat = pat[1:] -@@ -3437,14 +4304,61 @@ class YumBase(depsolve.Depsolve): +@@ -3437,14 +4335,87 @@ class YumBase(depsolve.Depsolve): if flag not in self.tsInfo.probFilterFlags: self.tsInfo.probFilterFlags.append(flag) @@ -153702,6 +153821,32 @@ index 99039e0..198dc6d 100644 + return True + + return False ++ ++ def _valid_install_arch(self, po, ipkgs=None): ++ ''' See if we can install this arch of package, mainly for ++ i386 vs. i586 or ppc64 vs. ppc64 etc. ''' ++ if not ipkgs: ++ ipkgs = self.rpmdb.searchNames([po.name]) ++ else: ++ ipkgs = ipkgs[:] ++ ++ # Add these anyway, just to be sure. ++ for txmbr in self.tsInfo.matchNaevr(po.name): ++ if txmbr.output_state not in TS_INSTALL_STATES: ++ continue ++ ipkgs.append(txmbr.po) ++ ++ for ipkg in ipkgs: ++ if po.arch == ipkg.arch: ++ continue ++ if not po.verEQ(ipkg): ++ continue ++ if canCoinstall(po.arch, ipkg.arch): ++ continue ++ self.verbose_logger.log(logginglevels.INFO_2, ++ _("Package: %s - can't co-install with %s"), po, ipkg) ++ return False ++ return True + def install(self, po=None, **kwargs): - """try to mark for install the item specified. Uses provided package @@ -153742,7 +153887,7 @@ index 99039e0..198dc6d 100644 pkgs = [] was_pattern = False if po: -@@ -3477,20 +4391,12 @@ class YumBase(depsolve.Depsolve): +@@ -3477,20 +4448,12 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.debug(_('Checking for virtual provide or file-provide for %s'), arg) @@ -153769,7 +153914,7 @@ index 99039e0..198dc6d 100644 else: nevra_dict = self._nevra_kwarg_parse(kwargs) -@@ -3577,8 +4483,8 @@ class YumBase(depsolve.Depsolve): +@@ -3577,17 +4540,20 @@ class YumBase(depsolve.Depsolve): continue # make sure this shouldn't be passed to update: @@ -153780,7 +153925,11 @@ index 99039e0..198dc6d 100644 txmbrs = self.update(po=po) tx_return.extend(txmbrs) continue -@@ -3587,7 +4493,7 @@ class YumBase(depsolve.Depsolve): ++ ++ if not self._valid_install_arch(po, ipkgs): ++ continue + + # Make sure we're not installing a package which is obsoleted by # something else in the repo. Unless there is a obsoletion loop, # at which point ignore everything. obsoleting_pkg = None @@ -153789,7 +153938,7 @@ index 99039e0..198dc6d 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 +4506,23 @@ class YumBase(depsolve.Depsolve): +@@ -3600,23 +4566,23 @@ class YumBase(depsolve.Depsolve): already_obs = pkgs[0] if already_obs: @@ -153820,7 +153969,7 @@ index 99039e0..198dc6d 100644 continue # make sure we don't have a name.arch of this already installed -@@ -3630,7 +4536,7 @@ class YumBase(depsolve.Depsolve): +@@ -3630,7 +4596,7 @@ class YumBase(depsolve.Depsolve): found = True break if not found: @@ -153829,7 +153978,7 @@ index 99039e0..198dc6d 100644 txmbrs = self.update(po=po) tx_return.extend(txmbrs) continue -@@ -3719,19 +4625,47 @@ class YumBase(depsolve.Depsolve): +@@ -3719,19 +4685,47 @@ class YumBase(depsolve.Depsolve): return txmbr def update(self, po=None, requiringPo=None, update_to=False, **kwargs): @@ -153884,7 +154033,7 @@ index 99039e0..198dc6d 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 +4699,14 @@ class YumBase(depsolve.Depsolve): +@@ -3765,7 +4759,14 @@ class YumBase(depsolve.Depsolve): if new is None: continue tx_return.extend(self.update(po=new)) @@ -153900,7 +154049,7 @@ index 99039e0..198dc6d 100644 return tx_return # complications -@@ -3787,7 +4728,7 @@ class YumBase(depsolve.Depsolve): +@@ -3787,7 +4788,7 @@ class YumBase(depsolve.Depsolve): return self._minus_deselect(kwargs['pattern']) if kwargs['pattern'] and kwargs['pattern'][0] == '@': @@ -153909,7 +154058,7 @@ index 99039e0..198dc6d 100644 arg = kwargs['pattern'] if not update_to: -@@ -3843,7 +4784,7 @@ class YumBase(depsolve.Depsolve): +@@ -3843,7 +4844,7 @@ class YumBase(depsolve.Depsolve): availpkgs = self._compare_providers(availpkgs, requiringPo) availpkgs = map(lambda x: x[0], availpkgs) elif not availpkgs: @@ -153918,10 +154067,13 @@ index 99039e0..198dc6d 100644 # for any thing specified # get the list of available pkgs matching it (or take the po) -@@ -3920,6 +4861,18 @@ class YumBase(depsolve.Depsolve): +@@ -3920,6 +4921,21 @@ class YumBase(depsolve.Depsolve): tx_return.append(txmbr) for available_pkg in availpkgs: ++ if not self._valid_install_arch(available_pkg): ++ continue ++ + # "Just do it" if it's a local pkg. + if isinstance(available_pkg, YumLocalPackage): + n = available_pkg.name @@ -153937,7 +154089,7 @@ index 99039e0..198dc6d 100644 # Make sure we're not installing a package which is obsoleted by # something else in the repo. Unless there is a obsoletion loop, # at which point ignore everything. -@@ -3985,11 +4938,18 @@ class YumBase(depsolve.Depsolve): +@@ -3985,11 +5001,18 @@ class YumBase(depsolve.Depsolve): return tx_return def remove(self, po=None, **kwargs): @@ -153961,7 +154113,7 @@ index 99039e0..198dc6d 100644 if not po and not kwargs: raise Errors.RemoveError, 'Nothing specified to remove' -@@ -4055,17 +5015,19 @@ class YumBase(depsolve.Depsolve): +@@ -4055,17 +5078,19 @@ class YumBase(depsolve.Depsolve): return tx_return def installLocal(self, pkg, po=None, updateonly=False): @@ -153991,7 +154143,7 @@ index 99039e0..198dc6d 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 +5145,15 @@ class YumBase(depsolve.Depsolve): +@@ -4183,16 +5208,15 @@ class YumBase(depsolve.Depsolve): return tx_return def reinstallLocal(self, pkg, po=None): @@ -154016,7 +154168,7 @@ index 99039e0..198dc6d 100644 if not po: try: po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg, -@@ -4215,9 +5176,19 @@ class YumBase(depsolve.Depsolve): +@@ -4215,9 +5239,19 @@ class YumBase(depsolve.Depsolve): return self.reinstall(po=po) def reinstall(self, po=None, **kwargs): @@ -154039,7 +154191,7 @@ index 99039e0..198dc6d 100644 self._add_prob_flags(rpm.RPMPROB_FILTER_REPLACEPKG, rpm.RPMPROB_FILTER_REPLACENEWFILES, rpm.RPMPROB_FILTER_REPLACEOLDFILES) -@@ -4259,16 +5230,15 @@ class YumBase(depsolve.Depsolve): +@@ -4259,16 +5293,15 @@ class YumBase(depsolve.Depsolve): return tx_mbrs def downgradeLocal(self, pkg, po=None): @@ -154064,7 +154216,7 @@ index 99039e0..198dc6d 100644 if not po: try: po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg, -@@ -4309,13 +5279,19 @@ class YumBase(depsolve.Depsolve): +@@ -4309,13 +5342,19 @@ class YumBase(depsolve.Depsolve): return False def downgrade(self, po=None, **kwargs): @@ -154091,7 +154243,18 @@ index 99039e0..198dc6d 100644 if not po and not kwargs: raise Errors.DowngradeError, 'Nothing specified to downgrade' -@@ -4421,6 +5397,9 @@ class YumBase(depsolve.Depsolve): +@@ -4397,6 +5436,10 @@ class YumBase(depsolve.Depsolve): + # installed version. Indexed fromn the latest installed pkgtup. + downgrade_apkgs = {} + for pkg in sorted(apkgs): ++ # We are cleverer here, I think... ++ # if not self._valid_install_arch(pkg, ipkgs): ++ # continue ++ + na = (pkg.name, pkg.arch) + + # Here we allow downgrades from .i386 => .noarch, or .i586 => .i386 +@@ -4421,6 +5464,9 @@ class YumBase(depsolve.Depsolve): warned_nas.add(na) continue @@ -154101,7 +154264,7 @@ index 99039e0..198dc6d 100644 if pkg.verGE(lipkg): if na not in warned_nas: msg = _('Only Upgrade available on package: %s') % pkg -@@ -4457,7 +5436,7 @@ class YumBase(depsolve.Depsolve): +@@ -4457,7 +5503,7 @@ class YumBase(depsolve.Depsolve): if e and v and r: evr = '%s:%s-%s' % (e, v, r) elif v and r: @@ -154110,7 +154273,7 @@ index 99039e0..198dc6d 100644 elif e and v: evr = '%s:%s' % (e, v) elif v: # e and r etc. is just too weird to print -@@ -4500,12 +5479,24 @@ class YumBase(depsolve.Depsolve): +@@ -4500,12 +5546,24 @@ class YumBase(depsolve.Depsolve): return returndict @@ -154138,7 +154301,7 @@ index 99039e0..198dc6d 100644 old_conf_obs = self.conf.obsoletes self.conf.obsoletes = False done = False -@@ -4515,19 +5506,46 @@ class YumBase(depsolve.Depsolve): +@@ -4515,19 +5573,46 @@ class YumBase(depsolve.Depsolve): done = True for pkg in transaction.trans_data: if pkg.state == 'Downgrade': @@ -154185,7 +154348,7 @@ index 99039e0..198dc6d 100644 if self.install(pkgtup=pkg.pkgtup): done = True for pkg in transaction.trans_data: -@@ -4538,8 +5556,14 @@ class YumBase(depsolve.Depsolve): +@@ -4538,8 +5623,14 @@ class YumBase(depsolve.Depsolve): return done def history_undo(self, transaction): @@ -154202,7 +154365,7 @@ index 99039e0..198dc6d 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 +5640,7 @@ class YumBase(depsolve.Depsolve): +@@ -4616,7 +5707,7 @@ class YumBase(depsolve.Depsolve): except urlgrabber.grabber.URLGrabError, e: raise Errors.YumBaseError(_('GPG key retrieval failed: ') + @@ -154211,7 +154374,7 @@ index 99039e0..198dc6d 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 +5673,7 @@ class YumBase(depsolve.Depsolve): +@@ -4649,7 +5740,7 @@ class YumBase(depsolve.Depsolve): keys_info = misc.getgpgkeyinfo(rawkey, multiple=True) except ValueError, e: raise Errors.YumBaseError(_('Invalid GPG Key from %s: %s') % @@ -154220,7 +154383,7 @@ index 99039e0..198dc6d 100644 keys = [] for keyinfo in keys_info: thiskey = {} -@@ -4674,39 +5698,49 @@ class YumBase(depsolve.Depsolve): +@@ -4674,39 +5765,49 @@ class YumBase(depsolve.Depsolve): if pkgs: pkgs = sorted(pkgs)[-1] msg = (_('Importing %s key 0x%s:\n' @@ -154288,7 +154451,7 @@ index 99039e0..198dc6d 100644 user_cb_fail = False for keyurl in keyurls: keys = self._retrievePublicKey(keyurl, repo) -@@ -4725,7 +5759,9 @@ class YumBase(depsolve.Depsolve): +@@ -4725,7 +5826,9 @@ class YumBase(depsolve.Depsolve): # Try installing/updating GPG key self._getKeyImportMessage(info, keyurl) rc = False @@ -154299,7 +154462,7 @@ index 99039e0..198dc6d 100644 rc = True # grab the .sig/.asc for the keyurl, if it exists -@@ -4751,8 +5787,8 @@ class YumBase(depsolve.Depsolve): +@@ -4751,8 +5854,8 @@ class YumBase(depsolve.Depsolve): ts = self.rpmdb.readOnlyTS() result = ts.pgpImportPubkey(misc.procgpgkey(info['raw_key'])) if result != 0: @@ -154310,7 +154473,7 @@ index 99039e0..198dc6d 100644 self.logger.info(_('Key imported successfully')) key_installed = True -@@ -4760,18 +5796,20 @@ class YumBase(depsolve.Depsolve): +@@ -4760,18 +5863,20 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _("Didn't install any keys") if not key_installed: @@ -154336,7 +154499,7 @@ index 99039e0..198dc6d 100644 def _getAnyKeyForRepo(self, repo, destdir, keyurl_list, is_cakey=False, callback=None): """ -@@ -4788,6 +5826,18 @@ class YumBase(depsolve.Depsolve): +@@ -4788,6 +5893,18 @@ class YumBase(depsolve.Depsolve): """ key_installed = False @@ -154355,7 +154518,7 @@ index 99039e0..198dc6d 100644 user_cb_fail = False for keyurl in keyurl_list: keys = self._retrievePublicKey(keyurl, repo, getSig=not is_cakey) -@@ -4819,8 +5869,11 @@ class YumBase(depsolve.Depsolve): +@@ -4819,8 +5936,11 @@ class YumBase(depsolve.Depsolve): if not key_installed: self._getKeyImportMessage(info, keyurl, keytype) rc = False @@ -154368,7 +154531,7 @@ index 99039e0..198dc6d 100644 elif callback: rc = callback({"repo": repo, "userid": info['userid'], "hexkeyid": info['hexkeyid'], "keyurl": keyurl, -@@ -4835,7 +5888,8 @@ class YumBase(depsolve.Depsolve): +@@ -4835,7 +5955,8 @@ class YumBase(depsolve.Depsolve): # Import the key result = misc.import_key_to_pubring(info['raw_key'], info['hexkeyid'], gpgdir=destdir) if not result: @@ -154378,7 +154541,7 @@ index 99039e0..198dc6d 100644 self.logger.info(_('Key imported successfully')) key_installed = True # write out the key id to imported_cakeys in the repos basedir -@@ -4851,36 +5905,35 @@ class YumBase(depsolve.Depsolve): +@@ -4851,36 +5972,35 @@ class YumBase(depsolve.Depsolve): pass if not key_installed and user_cb_fail: @@ -154431,7 +154594,7 @@ index 99039e0..198dc6d 100644 self._getAnyKeyForRepo(repo, repo.gpgcadir, repo.gpgcakey, is_cakey=True, callback=callback) def _limit_installonly_pkgs(self): -@@ -4927,6 +5980,7 @@ class YumBase(depsolve.Depsolve): +@@ -4927,6 +6047,7 @@ class YumBase(depsolve.Depsolve): ts = self.rpmdb.readOnlyTS() (cur_kernel_v, cur_kernel_r) = misc.get_running_kernel_version_release(ts) install_only_names = set(self.conf.installonlypkgs) @@ -154439,7 +154602,7 @@ index 99039e0..198dc6d 100644 for m in self.tsInfo.getMembers(): if m.ts_state not in ('i', 'u'): continue -@@ -4937,12 +5991,21 @@ class YumBase(depsolve.Depsolve): +@@ -4937,12 +6058,21 @@ class YumBase(depsolve.Depsolve): if not po_names.intersection(install_only_names): continue @@ -154465,7 +154628,7 @@ index 99039e0..198dc6d 100644 for po in installed: if (po.version, po.release) == (cur_kernel_v, cur_kernel_r): # don't remove running -@@ -4959,19 +6022,22 @@ class YumBase(depsolve.Depsolve): +@@ -4959,19 +6089,22 @@ class YumBase(depsolve.Depsolve): txmbr.depends_on.append(rel) def processTransaction(self, callback=None,rpmTestDisplay=None, rpmDisplay=None): @@ -154501,7 +154664,7 @@ index 99039e0..198dc6d 100644 if not callback: callback = callbacks.ProcessTransNoOutputCallback() -@@ -5114,13 +6180,19 @@ class YumBase(depsolve.Depsolve): +@@ -5114,13 +6247,19 @@ class YumBase(depsolve.Depsolve): return results def add_enable_repo(self, repoid, baseurls=[], mirrorlist=None, **kwargs): @@ -154528,7 +154691,7 @@ index 99039e0..198dc6d 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 +6239,15 @@ class YumBase(depsolve.Depsolve): +@@ -5167,9 +6306,15 @@ class YumBase(depsolve.Depsolve): def setCacheDir(self, force=False, tmpdir=None, reuse=True, suffix='/$basearch/$releasever'): @@ -154547,7 +154710,7 @@ index 99039e0..198dc6d 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 +6257,7 @@ class YumBase(depsolve.Depsolve): +@@ -5179,7 +6324,7 @@ class YumBase(depsolve.Depsolve): try: cachedir = misc.getCacheDir(tmpdir, reuse) except (IOError, OSError), e: @@ -154556,7 +154719,7 @@ index 99039e0..198dc6d 100644 cachedir = None if cachedir is None: -@@ -5190,6 +6268,7 @@ class YumBase(depsolve.Depsolve): +@@ -5190,6 +6335,7 @@ class YumBase(depsolve.Depsolve): self.prerepoconf.cachedir = cachedir else: self.repos.setCacheDir(cachedir) @@ -154564,7 +154727,7 @@ index 99039e0..198dc6d 100644 self.conf.cachedir = cachedir return True # We got a new cache dir -@@ -5220,13 +6299,24 @@ class YumBase(depsolve.Depsolve): +@@ -5220,13 +6366,24 @@ class YumBase(depsolve.Depsolve): self.history.write_addon_data('config-repos', myrepos) def verify_plugins_cb(self, verify_package): @@ -154592,7 +154755,7 @@ index 99039e0..198dc6d 100644 if self.tsInfo._unresolvedMembers: if auto: self.logger.critical(_("Dependencies not solved. Will not save unresolved transaction.")) -@@ -5234,7 +6324,7 @@ class YumBase(depsolve.Depsolve): +@@ -5234,7 +6391,7 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError(_("Dependencies not solved. Will not save unresolved transaction.")) if not filename: @@ -154601,7 +154764,7 @@ index 99039e0..198dc6d 100644 fd,filename = tempfile.mkstemp(suffix='.yumtx', prefix=prefix) f = os.fdopen(fd, 'w') else: -@@ -5244,13 +6334,17 @@ class YumBase(depsolve.Depsolve): +@@ -5244,13 +6401,17 @@ class YumBase(depsolve.Depsolve): msg = "%s\n" % self.rpmdb.simpleVersion(main_only=True)[0] msg += "%s\n" % self.ts.getTsFlags() @@ -154622,7 +154785,7 @@ index 99039e0..198dc6d 100644 msg += "%s\n" % len(self.tsInfo.getMembers()) for txmbr in self.tsInfo.getMembers(): msg += txmbr._dump() -@@ -5260,13 +6354,25 @@ class YumBase(depsolve.Depsolve): +@@ -5260,13 +6421,25 @@ class YumBase(depsolve.Depsolve): except (IOError, OSError), e: self._ts_save_file = None if auto: @@ -154654,7 +154817,7 @@ index 99039e0..198dc6d 100644 # check rpmversion - if not match throw a fit # check repoversions (and repos)- if not match throw a fit # load each txmbr - if pkgs being updated don't exist, bail w/error -@@ -5276,26 +6382,45 @@ class YumBase(depsolve.Depsolve): +@@ -5276,26 +6449,45 @@ class YumBase(depsolve.Depsolve): try: data = open(filename, 'r').readlines() except (IOError, OSError), e: @@ -154702,7 +154865,7 @@ index 99039e0..198dc6d 100644 if ignorerpm: msg += _(" ignoring, as requested.") self.logger.critical(_(msg)) -@@ -5318,8 +6443,17 @@ class YumBase(depsolve.Depsolve): +@@ -5318,8 +6510,17 @@ class YumBase(depsolve.Depsolve): numrepos = int(data[2].strip()) repos = [] rindex=3+numrepos @@ -154721,7 +154884,7 @@ index 99039e0..198dc6d 100644 # pkgs/txmbrs numpkgs = int(data[rindex].strip()) -@@ -5329,6 +6463,7 @@ class YumBase(depsolve.Depsolve): +@@ -5329,6 +6530,7 @@ class YumBase(depsolve.Depsolve): pkgcount = 0 pkgprob = False curpkg = None @@ -154729,7 +154892,22 @@ index 99039e0..198dc6d 100644 for l in data[pkgstart:]: l = l.rstrip() # our main txmbrs -@@ -5438,6 +6573,11 @@ class YumBase(depsolve.Depsolve): +@@ -5356,6 +6558,7 @@ class YumBase(depsolve.Depsolve): + if not ignoremissing: + raise Errors.YumBaseError(msg) + else: ++ ignorenewrpm = True + self.logger.critical(msg) + else: + pkgcount += 1 +@@ -5432,12 +6635,18 @@ class YumBase(depsolve.Depsolve): + if pkgprob: + msg = _("Transaction members, relations are missing or ts has been modified,") + if ignoremissing: ++ ignorenewrpm = True + msg += _(" ignoring, as requested. You must redepsolve!") + self.logger.critical(msg) + else: msg += _(" aborting.") raise Errors.YumBaseError(msg) @@ -154741,7 +154919,7 @@ index 99039e0..198dc6d 100644 return self.tsInfo.getMembers() def _remove_old_deps(self): -@@ -5470,18 +6610,6 @@ class YumBase(depsolve.Depsolve): +@@ -5470,18 +6679,6 @@ class YumBase(depsolve.Depsolve): if requiring == required: # if they are self-requiring skip them continue @@ -154760,7 +154938,7 @@ index 99039e0..198dc6d 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 +6661,24 @@ class YumBase(depsolve.Depsolve): +@@ -5533,7 +6730,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 @@ -154785,7 +154963,7 @@ index 99039e0..198dc6d 100644 visited[curpkg] = True all_leaves_visited = True leaves = curpkg.requiring_packages() -@@ -5547,4 +6692,3 @@ class YumBase(depsolve.Depsolve): +@@ -5547,4 +6761,3 @@ class YumBase(depsolve.Depsolve): # Debugging output self.verbose_logger.log(logginglevels.DEBUG_2, _("%s has no user-installed revdeps."), pkg) return False @@ -154938,7 +155116,7 @@ index 7ad25ce..a9a8e53 100644 pass diff --git a/yum/comps.py b/yum/comps.py -index 65f6d5e..08e66b9 100755 +index 65f6d5e..4e765ef 100755 --- a/yum/comps.py +++ b/yum/comps.py @@ -43,6 +43,16 @@ class CompsObj(object): @@ -155096,7 +155274,7 @@ index 65f6d5e..08e66b9 100755 + msg += """ \n""" + msg += """ \n""" + for grp in self.options: -+ msg += """ %s\n""" % grp ++ msg += """ %s\n""" % grp + msg += """ \n""" + msg += """ \n""" + @@ -157735,7 +157913,7 @@ index aaa4f25..61aa586 100755 continue diff --git a/yum/misc.py b/yum/misc.py -index 2f6ddfe..a39a222 100644 +index 2f6ddfe..a0bac7b 100644 --- a/yum/misc.py +++ b/yum/misc.py @@ -8,6 +8,7 @@ import os @@ -157754,7 +157932,27 @@ index 2f6ddfe..a39a222 100644 _available_compression = ['gz', 'bz2'] try: import lzma -@@ -410,6 +412,17 @@ def procgpgkey(rawkey): +@@ -95,6 +97,19 @@ def re_glob(s): + _re_compiled_glob_match = re.compile('[*?]|\[.+\]').search + return _re_compiled_glob_match(s) + ++def compile_pattern(pat, ignore_case=False): ++ """ Compile shell wildcards, return a 'match' function. """ ++ if re_glob(pat): ++ try: ++ flags = ignore_case and re.I or 0 ++ return re.compile(fnmatch.translate(pat), flags).match ++ except re.error: ++ pass # fall back to exact match ++ if ignore_case: ++ pat = pat.lower() ++ return lambda s: s.lower() == pat ++ return lambda s: s == pat ++ + _re_compiled_filename_match = None + def re_filename(s): + """ Tests if a string could be a filename. We still get negated character +@@ -410,6 +425,17 @@ def procgpgkey(rawkey): # Decode and return return base64.decodestring(block.getvalue()) @@ -157772,7 +157970,7 @@ index 2f6ddfe..a39a222 100644 def getgpgkeyinfo(rawkey, multiple=False): '''Return a dict of info for the given ASCII armoured key text -@@ -611,6 +624,8 @@ def getCacheDir(tmpdir='/var/tmp', reuse=True, prefix='yum-'): +@@ -611,6 +637,8 @@ def getCacheDir(tmpdir='/var/tmp', reuse=True, prefix='yum-'): try: usertup = pwd.getpwuid(uid) username = usertup[0] @@ -157781,7 +157979,7 @@ index 2f6ddfe..a39a222 100644 except KeyError: return None # if it returns None then, well, it's bollocksed -@@ -744,8 +759,9 @@ def _decompress_chunked(source, dest, ztype): +@@ -744,8 +772,9 @@ def _decompress_chunked(source, dest, ztype): while True: try: data = s_fn.read(1024000) @@ -157793,7 +157991,7 @@ index 2f6ddfe..a39a222 100644 if not data: break -@@ -940,14 +956,16 @@ def unlink_f(filename): +@@ -940,14 +969,16 @@ def unlink_f(filename): if e.errno != errno.ENOENT: raise @@ -157814,7 +158012,7 @@ index 2f6ddfe..a39a222 100644 def _getloginuid(): """ Get the audit-uid/login-uid, if available. None is returned if there -@@ -992,9 +1010,17 @@ def setup_locale(override_codecs=True, override_time=False): +@@ -992,9 +1023,17 @@ def setup_locale(override_codecs=True, override_time=False): locale.setlocale(locale.LC_ALL, 'C') if override_codecs: @@ -157835,7 +158033,7 @@ index 2f6ddfe..a39a222 100644 def get_my_lang_code(): -@@ -1105,17 +1131,28 @@ def decompress(filename, dest=None, fn_only=False, check_timestamps=False): +@@ -1105,17 +1144,28 @@ def decompress(filename, dest=None, fn_only=False, check_timestamps=False): out = filename.replace('.xz', '') else: @@ -157872,11 +158070,55 @@ index 2f6ddfe..a39a222 100644 return out +@@ -1123,11 +1173,7 @@ def repo_gen_decompress(filename, generated_name, cached=False): + """ This is a wrapper around decompress, where we work out a cached + generated name, and use check_timestamps. filename _must_ be from + a repo. and generated_name is the type of the file. """ +- dest = os.path.dirname(filename) +- dest += '/gen' +- if not os.path.exists(dest): +- os.makedirs(dest, mode=0755) +- dest += '/' + generated_name ++ dest = os.path.dirname(filename) + '/gen/' + generated_name + return decompress(filename, dest=dest, check_timestamps=True,fn_only=cached) + + def read_in_items_from_dot_dir(thisglob, line_as_list=True): diff --git a/yum/packageSack.py b/yum/packageSack.py -index 4af563a..47832fc 100644 +index 4af563a..a702ac1 100644 --- a/yum/packageSack.py +++ b/yum/packageSack.py -@@ -445,6 +445,7 @@ class MetaSack(PackageSackBase): +@@ -282,11 +282,7 @@ class PackageSackBase(object): + + specs = {} + for p in pkgspecs: +- if misc.re_glob(p): +- restring = fnmatch.translate(p) +- specs[p] = re.compile(restring) +- else: +- specs[p] = p ++ specs[p] = misc.compile_pattern(p) + + # We don't use simplePkgList() here because that loads all of the + # rpmdb, if we are Eg. doing a "remove PackageKit". +@@ -304,13 +300,12 @@ class PackageSackBase(object): + )) + + for (term,query) in specs.items(): +- if term == query: +- if query in names: +- exactmatch.append(self.searchPkgTuple(pkgtup)[0]) +- unmatched.discard(term) ++ if term in names: ++ exactmatch.append(self.searchPkgTuple(pkgtup)[0]) ++ unmatched.discard(term) + else: + for n in names: +- if query.match(n): ++ if query(n): + matched.append(self.searchPkgTuple(pkgtup)[0]) + unmatched.discard(term) + return misc.unique(exactmatch), misc.unique(matched), list(unmatched) +@@ -445,6 +440,7 @@ class MetaSack(PackageSackBase): nobsdict = {} last_name = '' last_pkg = None @@ -157884,7 +158126,7 @@ index 4af563a..47832fc 100644 # It takes about 0.2 of a second to convert these into packages, just # so we can sort them, which is ~40% of this functions time. So we sort # the pkgtups "by hand". -@@ -624,6 +625,8 @@ class MetaSack(PackageSackBase): +@@ -624,6 +620,8 @@ class MetaSack(PackageSackBase): class PackageSack(PackageSackBase): """represents sets (sacks) of Package Objects""" def __init__(self): @@ -157894,7 +158136,7 @@ index 4af563a..47832fc 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..07c555c 100644 +index 5ef9951..7a2624a 100644 --- a/yum/packages.py +++ b/yum/packages.py @@ -106,14 +106,16 @@ def buildPkgRefDict(pkgs, casematch=True): @@ -157916,7 +158158,21 @@ index 5ef9951..07c555c 100644 exactmatch = [] matched = [] unmatched = [] -@@ -223,6 +225,10 @@ class FakeRepository: +@@ -130,11 +132,10 @@ def parsePackages(pkgs, usercommands, casematch=0, + trylist = pkgdict.keys() + # command and pkgdict are already lowered if not casematch + # so case sensitive is always fine +- restring = fnmatch.translate(command) +- regex = re.compile(restring) ++ regex = misc.compile_pattern(command) + foundit = 0 + for item in trylist: +- if regex.match(item): ++ if regex(item): + matched.extend(pkgdict[item]) + del pkgdict[item] + foundit = 1 +@@ -223,6 +224,10 @@ class FakeRepository: def __str__(self): return self.id @@ -157927,7 +158183,7 @@ index 5ef9951..07c555c 100644 # Goal for the below is to have a packageobject that can be used by generic # functions independent of the type of package - ie: installed or available -@@ -243,34 +249,87 @@ class PackageObject(object): +@@ -243,34 +248,87 @@ class PackageObject(object): def _ui_envra(self): if self.epoch == '0': @@ -158035,7 +158291,7 @@ index 5ef9951..07c555c 100644 def __str__(self): return self.ui_envra -@@ -481,15 +540,14 @@ class RpmBase(object): +@@ -481,15 +539,14 @@ class RpmBase(object): if prcotuple in self._prco_lookup[prcotype]: return 1 @@ -158059,7 +158315,7 @@ index 5ef9951..07c555c 100644 return 0 -@@ -611,15 +669,18 @@ class RpmBase(object): +@@ -611,15 +668,18 @@ class RpmBase(object): dirlist = property(fget=lambda self: self.returnFileEntries(ftype='dir')) ghostlist = property(fget=lambda self: self.returnFileEntries(ftype='ghost')) requires = property(fget=lambda self: self.returnPrco('requires')) @@ -158078,7 +158334,7 @@ index 5ef9951..07c555c 100644 conflicts_print = property(fget=lambda self: self.returnPrco('conflicts', True)) obsoletes_print = property(fget=lambda self: self.returnPrco('obsoletes', True)) changelog = property(fget=lambda self: self.returnChangelog()) -@@ -1083,7 +1144,7 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1083,7 +1143,7 @@ class YumAvailablePackage(PackageObject, RpmBase): misc.to_unicode(misc.to_xml(self.summary)), misc.to_unicode(misc.to_xml(self.description)), packager, url, self.filetime, @@ -158087,7 +158343,7 @@ index 5ef9951..07c555c 100644 msg += self._return_remote_location() return msg -@@ -1133,7 +1194,7 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1133,7 +1193,7 @@ class YumAvailablePackage(PackageObject, RpmBase): msg = "" mylist = getattr(self, pcotype) if mylist: msg = "\n \n" % pcotype @@ -158096,7 +158352,7 @@ index 5ef9951..07c555c 100644 pcostring = ''' %s\n""" % misc.to_xml(fn) return msg -@@ -1194,8 +1255,8 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1194,8 +1254,8 @@ class YumAvailablePackage(PackageObject, RpmBase): continue newlist.append(i) mylist = newlist @@ -158122,7 +158378,7 @@ index 5ef9951..07c555c 100644 if name.startswith('rpmlib('): continue # this drops out requires that the pkg provides for itself. -@@ -1217,13 +1278,16 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1217,13 +1277,16 @@ class YumAvailablePackage(PackageObject, RpmBase): prcostring += ''' ver="%s"''' % misc.to_xml(v, attrib=True) if r: prcostring += ''' rel="%s"''' % misc.to_xml(r, attrib=True) @@ -158141,7 +158397,7 @@ index 5ef9951..07c555c 100644 return msg def _dump_changelog(self, clog_limit): -@@ -1272,6 +1336,13 @@ class YumAvailablePackage(PackageObject, RpmBase): +@@ -1272,6 +1335,13 @@ class YumAvailablePackage(PackageObject, RpmBase): return misc.to_utf8(msg) @@ -158155,7 +158411,7 @@ index 5ef9951..07c555c 100644 # This is a tweak on YumAvailablePackage() and is a base class for packages # which are actual rpms. -@@ -1299,7 +1370,8 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1299,7 +1369,8 @@ class YumHeaderPackage(YumAvailablePackage): self.pkgid = self.hdr[rpm.RPMTAG_SHA1HEADER] if not self.pkgid: self.pkgid = "%s.%s" %(self.hdr['name'], self.hdr['buildtime']) @@ -158165,7 +158421,7 @@ index 5ef9951..07c555c 100644 self.__mode_cache = {} self.__prcoPopulated = False -@@ -1353,6 +1425,12 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1353,6 +1424,12 @@ class YumHeaderPackage(YumAvailablePackage): continue lst = hdr[getattr(rpm, 'RPMTAG_%sFLAGS' % tag)] @@ -158178,7 +158434,7 @@ index 5ef9951..07c555c 100644 flag = map(rpmUtils.miscutils.flagToString, lst) flag = map(misc.share_data, flag) -@@ -1363,6 +1441,10 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1363,6 +1440,10 @@ class YumHeaderPackage(YumAvailablePackage): prcotype = tag2prco[tag] self.prco[prcotype] = map(misc.share_data, zip(name,flag,vers)) @@ -158189,7 +158445,7 @@ index 5ef9951..07c555c 100644 def tagByName(self, tag): warnings.warn("tagByName() will go away in a furture version of Yum.\n", -@@ -1447,7 +1529,7 @@ class YumHeaderPackage(YumAvailablePackage): +@@ -1447,7 +1528,7 @@ class YumHeaderPackage(YumAvailablePackage): raise NotImplementedError() def _size(self): @@ -158803,7 +159059,7 @@ index 31b1080..eb84123 100755 tags += """ \n""" msg += tags diff --git a/yum/repos.py b/yum/repos.py -index 3793bad..6d4c20e 100644 +index 3793bad..de5da1e 100644 --- a/yum/repos.py +++ b/yum/repos.py @@ -22,6 +22,7 @@ import misc @@ -158862,15 +159118,21 @@ index 3793bad..6d4c20e 100644 def doSetup(self, thisrepo = None): self.ayum.plugins.run('prereposetup') -@@ -89,6 +131,7 @@ class RepoStorage: +@@ -87,8 +129,13 @@ class RepoStorage: + # so nothing else touches us + if not repo.enabled: self.disableRepo(repo.id) ++ else: ++ pkgdir = getattr(self.ayum.conf, 'downloaddir', None) ++ if pkgdir: ++ repo.pkgdir = pkgdir self._setup = True + self.retrieveAllMD() self.ayum.plugins.run('postreposetup') def __str__(self): -@@ -223,15 +266,16 @@ class RepoStorage: +@@ -223,15 +270,16 @@ class RepoStorage: self._cachedir = cachedir for repo in self.repos.values(): @@ -158891,7 +159153,7 @@ index 3793bad..6d4c20e 100644 def setFailureCallback(self, obj): """sets the failure callback for all repos""" -@@ -288,6 +332,16 @@ class RepoStorage: +@@ -288,6 +336,16 @@ class RepoStorage: else: data = [ mdtype ] @@ -158909,7 +159171,7 @@ index 3793bad..6d4c20e 100644 sack = repo.getPackageSack() try: diff --git a/yum/rpmsack.py b/yum/rpmsack.py -index e289a7a..a4da4ab 100644 +index e289a7a..302f613 100644 --- a/yum/rpmsack.py +++ b/yum/rpmsack.py @@ -48,6 +48,17 @@ def _open_no_umask(*args): @@ -158949,7 +159211,53 @@ index e289a7a..a4da4ab 100644 continue pkg = pkg[0] -@@ -616,7 +628,7 @@ class RPMDBPackageSack(PackageSackBase): +@@ -534,13 +546,11 @@ class RPMDBPackageSack(PackageSackBase): + qpat = pat[0] + if qpat in ('?', '*', '['): + qpat = None +- if ignore_case: +- if qpat is not None: +- qpat = qpat.lower() +- ret.append((qpat, re.compile(fnmatch.translate(pat), re.I))) +- else: +- ret.append((qpat, re.compile(fnmatch.translate(pat)))) ++ elif ignore_case: ++ qpat = qpat.lower() ++ ret.append((qpat, misc.compile_pattern(pat, ignore_case))) + return ret ++ + @staticmethod + def _match_repattern(repatterns, hdr, ignore_case): + """ This is basically parsePackages() but for rpm hdr objects. """ +@@ -558,20 +568,20 @@ class RPMDBPackageSack(PackageSackBase): + qname = qname.lower() + if qpat is not None and qpat != qname and qpat != epoch[0]: + continue +- if repat.match(hdr['name']): ++ if repat(hdr['name']): + return True +- if repat.match("%(name)s-%(version)s-%(release)s.%(arch)s" % hdr): ++ if repat("%(name)s-%(version)s-%(release)s.%(arch)s" % hdr): + return True +- if repat.match("%(name)s.%(arch)s" % hdr): ++ if repat("%(name)s.%(arch)s" % hdr): + return True +- if repat.match("%(name)s-%(version)s" % hdr): ++ if repat("%(name)s-%(version)s" % hdr): + return True +- if repat.match("%(name)s-%(version)s-%(release)s" % hdr): ++ if repat("%(name)s-%(version)s-%(release)s" % hdr): + return True +- if repat.match(epoch + ":%(name)s-%(version)s-%(release)s.%(arch)s" ++ if repat(epoch + ":%(name)s-%(version)s-%(release)s.%(arch)s" + % hdr): + return True +- if repat.match("%(name)s-%(epoch)s:%(version)s-%(release)s.%(arch)s" ++ if repat("%(name)s-%(epoch)s:%(version)s-%(release)s.%(arch)s" + % hdr): + return True + return False +@@ -616,7 +626,7 @@ class RPMDBPackageSack(PackageSackBase): for hdr, idx in self._get_packages(): if self._match_repattern(rpats, hdr, ignore_case): self._makePackageObject(hdr, idx) @@ -158958,7 +159266,7 @@ index e289a7a..a4da4ab 100644 pkgobjlist = self._idx2pkg.values() # Remove gpg-pubkeys, as no sane callers expects/likes them... -@@ -993,7 +1005,7 @@ class RPMDBPackageSack(PackageSackBase): +@@ -993,7 +1003,7 @@ class RPMDBPackageSack(PackageSackBase): return if not load_packages: @@ -158967,7 +159275,7 @@ index e289a7a..a4da4ab 100644 for pkgtup in checksum_data: if checksum_data[pkgtup] is None: -@@ -1002,7 +1014,8 @@ class RPMDBPackageSack(PackageSackBase): +@@ -1002,7 +1012,8 @@ class RPMDBPackageSack(PackageSackBase): (n, a, e, v, r) = pkgtup pkg = self.searchNevra(n, e, v, r, a) if not pkg: @@ -158977,7 +159285,7 @@ index e289a7a..a4da4ab 100644 continue pkg = pkg[0] (T, D) = checksum_data[pkgtup] -@@ -1088,7 +1101,7 @@ class RPMDBPackageSack(PackageSackBase): +@@ -1088,7 +1099,7 @@ class RPMDBPackageSack(PackageSackBase): return try: @@ -158986,7 +159294,7 @@ index e289a7a..a4da4ab 100644 except (IOError, OSError), e: return -@@ -1456,7 +1469,7 @@ class RPMDBPackageSack(PackageSackBase): +@@ -1456,7 +1467,7 @@ class RPMDBPackageSack(PackageSackBase): providers = set() # Speedup, as usual :) problems = [] for pkg in sorted(pkgs): # The sort here is mainly for "UI" @@ -158995,7 +159303,7 @@ index e289a7a..a4da4ab 100644 if rreq[0].startswith('rpmlib'): continue if rreq in providers: continue -@@ -1562,11 +1575,11 @@ class RPMDBAdditionalData(object): +@@ -1562,11 +1573,11 @@ class RPMDBAdditionalData(object): self._packages = {} # pkgid = dir if not os.path.exists(self.conf.db_path): try: @@ -159010,7 +159318,7 @@ index e289a7a..a4da4ab 100644 else: if os.access(self.conf.db_path, os.W_OK): self.conf.writable = True -@@ -1622,6 +1635,7 @@ class RPMDBAdditionalDataPackage(object): +@@ -1622,6 +1633,7 @@ class RPMDBAdditionalDataPackage(object): 'installed_by', 'changed_by', 'from_repo', 'from_repo_revision', 'from_repo_timestamp', 'releasever', @@ -159018,7 +159326,7 @@ index e289a7a..a4da4ab 100644 'command_line']) def __init__(self, conf, pkgdir, yumdb_cache=None): -@@ -1708,7 +1722,7 @@ class RPMDBAdditionalDataPackage(object): +@@ -1708,7 +1720,7 @@ class RPMDBAdditionalDataPackage(object): def _write(self, attr, value): # check for self._conf.writable before going on? if not os.path.exists(self._mydir): @@ -159027,7 +159335,7 @@ index e289a7a..a4da4ab 100644 attr = _sanitize(attr) if attr in self._read_cached_data: -@@ -1753,7 +1767,7 @@ class RPMDBAdditionalDataPackage(object): +@@ -1753,7 +1765,7 @@ class RPMDBAdditionalDataPackage(object): if attr.endswith('.tmp'): raise AttributeError, "%s has no attribute %s" % (self, attr) @@ -159037,7 +159345,7 @@ index e289a7a..a4da4ab 100644 raise AttributeError, "%s has no attribute %s" % (self, attr) diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py -index 9b265f9..61c9a0e 100644 +index 9b265f9..74a0f3f 100644 --- a/yum/rpmtrans.py +++ b/yum/rpmtrans.py @@ -119,7 +119,11 @@ class RPMBaseCallback: @@ -159091,8 +159399,11 @@ index 9b265f9..61c9a0e 100644 def _transStart(self, bytes, total, h): -@@ -621,3 +638,16 @@ class RPMTransaction: +@@ -619,5 +636,19 @@ class RPMTransaction: + msg = ("Non-fatal %s scriptlet failure in rpm package %s" % + (scriptlet_name, package_name)) self.display.errorlog(msg) ++ self._scriptout(package_name) # FIXME - what else should we do here? raise a failure and abort? + def _scriptStart(self, bytes, total, h): @@ -159109,7 +159420,7 @@ index 9b265f9..61c9a0e 100644 + + self.display.verify_txmbr(self.base, txmbr, count) diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py -index 8a6f6f3..ed57408 100644 +index 8a6f6f3..a955895 100644 --- a/yum/sqlitesack.py +++ b/yum/sqlitesack.py @@ -69,7 +69,7 @@ def _parse_pkg_n(match, regexp_match, n): @@ -159160,6 +159471,31 @@ index 8a6f6f3..ed57408 100644 if len(self.filelistsdb) == 0: # grab repo object from primarydb and force filelists population in this sack using repo +@@ -1560,7 +1563,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): + patterns = tmp + return (need_full, patterns, fields, False) + +- @catchSqliteException ++ # @catchSqliteException has no effect on generators + def _yieldSQLDataList(self, repoid, patterns, fields, ignore_case): + """Yields all the package data for the given params. Excludes are done + at this stage. """ +@@ -1593,6 +1596,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): + for x in cur: + yield (repo, x) + ++ @catchSqliteException + def _buildPkgObjList(self, repoid=None, patterns=None, ignore_case=False): + """Builds a list of packages, only containing nevra information. + Excludes are done at this stage. """ +@@ -1666,6 +1670,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): + + return returnList + ++ @catchSqliteException + def simplePkgList(self, patterns=None, ignore_case=False): + """Returns a list of pkg tuples (n, a, e, v, r), optionally from a + single repoid. Note that the packages are always filtered to those diff --git a/yum/transactioninfo.py b/yum/transactioninfo.py index 4d89d83..e7377bf 100644 --- a/yum/transactioninfo.py @@ -159393,7 +159729,7 @@ index 2cb1acb..0586c1c 100644 for pkg in un['pkglist']: for filedata in pkg['packages']: diff --git a/yum/yumRepo.py b/yum/yumRepo.py -index e5e9ece..21f65f7 100644 +index e5e9ece..e362c43 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -20,10 +20,12 @@ import time @@ -159487,7 +159823,7 @@ index e5e9ece..21f65f7 100644 + db_un_fn = self._check_uncompressed_db_gen(repo, + mydbtype) + if not db_un_fn: # Shouldn't happen? -+ raise URLGrabError(-1, 'Check uncompressed DB failed') ++ raise Errors.RepoError, '%s: Check uncompressed DB failed' % repo dobj = repo.cacheHandler.open_database(db_un_fn) @@ -159501,7 +159837,7 @@ index e5e9ece..21f65f7 100644 + gen = mymdtype + '.xml' + ret = misc.repo_gen_decompress(xml, gen, cached=repo.cache) + if not ret: -+ raise URLGrabError(-1, 'Decompress DB failed') ++ raise Errors.RepoError, '%s: Decompress DB failed' % repo + xml = ret + # Convert XML => .sqlite xmldata = repo.repoXML.getData(mymdtype) @@ -159706,6 +160042,15 @@ index e5e9ece..21f65f7 100644 'http_headers': tuple(self.__headersListFromDict(cache=cache)), 'ssl_verify_peer': self.sslverify, 'ssl_verify_host': self.sslverify, +@@ -561,7 +660,7 @@ class YumRepository(Repository, config.RepoConf): + cookie = self.cachedir + '/' + self.metadata_cookie_fn + self.setAttribute('_dir_setup_metadata_cookie', cookie) + +- for dir in [self.cachedir, self.pkgdir]: ++ for dir in [self.cachedir, self.cachedir + '/gen', self.pkgdir]: + self._dirSetupMkdir_p(dir) + + # persistdir is really root-only but try the make anyway and just @@ -714,15 +813,15 @@ class YumRepository(Repository, config.RepoConf): local = self.metalink_filename + '.tmp' if not self._metalinkCurrent(): @@ -159717,7 +160062,8 @@ index e5e9ece..21f65f7 100644 - result = ug.urlgrab(url, local, text=self.id + "/metalink") + result = ug.urlgrab(url, local, text="%s/metalink" % self.ui_id) - except urlgrabber.grabber.URLGrabError, e: +- except urlgrabber.grabber.URLGrabError, e: ++ except URLGrabError, e: if not os.path.exists(self.metalink_filename): msg = ("Cannot retrieve metalink for repository: %s. " - "Please verify its path and try again" % self ) @@ -159827,13 +160173,16 @@ index e5e9ece..21f65f7 100644 remote = package.relativepath local = package.localPkg() basepath = package.basepath -@@ -857,15 +975,26 @@ class YumRepository(Repository, config.RepoConf): +@@ -857,15 +975,29 @@ class YumRepository(Repository, config.RepoConf): return local misc.unlink_f(local) - return self._getFile(url=basepath, + if checkfunc is None: -+ checkfunc = lambda obj: package.verifyLocalPkg() ++ def checkfunc(obj): ++ if not package.verifyLocalPkg(): ++ misc.unlink_f(local) ++ raise URLGrabError(-1, _('Package does not match intended download.')) + + ret = self._getFile(url=basepath, relative=remote, @@ -159855,7 +160204,7 @@ index e5e9ece..21f65f7 100644 def getHeader(self, package, checkfunc = None, reget = 'simple', cache = True): -@@ -991,7 +1120,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -991,7 +1123,7 @@ class YumRepository(Repository, config.RepoConf): def _cachingRepoXML(self, local): """ Should we cache the current repomd.xml """ if self.cache and not os.path.exists(local): @@ -159864,7 +160213,7 @@ index e5e9ece..21f65f7 100644 if self.cache or self.metadataCurrent(): return True return False -@@ -1020,7 +1149,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1020,7 +1152,7 @@ class YumRepository(Repository, config.RepoConf): if grab_can_fail: return None raise Errors.RepoError, 'Error downloading file %s: %s' % (local, e) @@ -159873,7 +160222,7 @@ index e5e9ece..21f65f7 100644 misc.unlink_f(tfname) if grab_can_fail: return None -@@ -1047,7 +1176,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1047,7 +1179,7 @@ class YumRepository(Repository, config.RepoConf): parse_can_fail = 'old_repo_XML' in self._oldRepoMDData if parse_can_fail: return None @@ -159882,16 +160231,16 @@ index e5e9ece..21f65f7 100644 def _saveOldRepoXML(self, local): """ If we have an older repomd.xml file available, save it out. """ -@@ -1074,7 +1203,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1074,7 +1206,7 @@ class YumRepository(Repository, config.RepoConf): # We still want the old data, so we don't download twice. So we # pretend everything is good until the revert. if not self.timestamp_check: - raise Errors.RepoError, "Can't download or revert repomd.xml" -+ raise Errors.RepoError, "Can't download or revert repomd.xml for:" % self.ui_id ++ raise Errors.RepoError, "Can't download or revert repomd.xml for %s" % self.ui_id if 'old_repo_XML' not in self._oldRepoMDData: self._oldRepoMDData = {} -@@ -1260,6 +1389,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1260,6 +1392,9 @@ class YumRepository(Repository, config.RepoConf): return True def _check_db_version(self, mdtype, repoXML=None): @@ -159901,7 +160250,7 @@ index e5e9ece..21f65f7 100644 if repoXML is None: repoXML = self.repoXML if mdtype in repoXML.repoData: -@@ -1277,11 +1409,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -1277,11 +1412,11 @@ class YumRepository(Repository, config.RepoConf): return None if not file_check: @@ -159916,7 +160265,7 @@ index e5e9ece..21f65f7 100644 if not os.path.exists(local): local = misc.decompress(local, fn_only=True) compressed = True -@@ -1302,6 +1434,17 @@ class YumRepository(Repository, config.RepoConf): +@@ -1302,6 +1437,17 @@ class YumRepository(Repository, config.RepoConf): into the delete list, this means metadata can change filename without us leaking it. """ @@ -159934,7 +160283,7 @@ index e5e9ece..21f65f7 100644 def _mdtype_eq(omdtype, odata, nmdtype, ndata): """ Check if two returns from _get_mdtype_data() are equal. """ if ndata is None: -@@ -1321,6 +1464,14 @@ class YumRepository(Repository, config.RepoConf): +@@ -1321,6 +1467,14 @@ class YumRepository(Repository, config.RepoConf): return True all_mdtypes = self.retrieved.keys() @@ -159949,7 +160298,7 @@ index e5e9ece..21f65f7 100644 if mdtypes is None: mdtypes = all_mdtypes -@@ -1333,8 +1484,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1333,8 +1487,7 @@ class YumRepository(Repository, config.RepoConf): # Inited twice atm. ... sue me self._oldRepoMDData['new_MD_files'] = [] @@ -159959,7 +160308,7 @@ index e5e9ece..21f65f7 100644 for mdtype in all_mdtypes: (nmdtype, ndata) = self._get_mdtype_data(mdtype) -@@ -1371,43 +1521,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -1371,43 +1524,16 @@ class YumRepository(Repository, config.RepoConf): # No old repomd data, but we might still have uncompressed MD if self._groupCheckDataMDValid(ndata, nmdtype, mdtype): continue @@ -159974,14 +160323,14 @@ index e5e9ece..21f65f7 100644 - if len(downloading_with_size) == 1: - downloading_no_size.extend(downloading_with_size) - downloading_with_size = [] -+ def _commonRetrieveDataMD_done(self, downloading): -+ """ Uncompress the downloaded metadata """ - +- - remote_size = 0 - local_size = 0 - for (ndata, nmdtype) in downloading_with_size: # Get total size... - remote_size += int(ndata.size) -- ++ def _commonRetrieveDataMD_done(self, downloading): ++ """ Uncompress the downloaded metadata """ + - for (ndata, nmdtype) in downloading_with_size: - urlgrabber.progress.text_meter_total_size(remote_size, local_size) - if not self._retrieveMD(nmdtype, retrieve_can_fail=True): @@ -160008,7 +160357,7 @@ index e5e9ece..21f65f7 100644 def _groupLoadRepoXML(self, text=None, mdtypes=None): """ Retrieve the new repomd.xml from the repository, then check it -@@ -1421,7 +1544,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1421,7 +1547,7 @@ class YumRepository(Repository, config.RepoConf): self._commonRetrieveDataMD(mdtypes) def _mdpolicy2mdtypes(self): @@ -160017,7 +160366,7 @@ index e5e9ece..21f65f7 100644 'group:primary' : ['primary'], 'group:small' : ["primary", "updateinfo"], 'group:main' : ["primary", "group", "filelists", -@@ -1436,6 +1559,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1436,6 +1562,7 @@ class YumRepository(Repository, config.RepoConf): if not mdtypes or 'group:all' in mdtypes: mdtypes = None else: @@ -160025,7 +160374,7 @@ index e5e9ece..21f65f7 100644 mdtypes = sorted(list(mdtypes)) return mdtypes -@@ -1446,17 +1570,12 @@ class YumRepository(Repository, config.RepoConf): +@@ -1446,17 +1573,12 @@ class YumRepository(Repository, config.RepoConf): except KeyboardInterrupt: self._revertOldRepoXML() # Undo metadata cookie? raise @@ -160045,7 +160394,7 @@ index e5e9ece..21f65f7 100644 return self._repoXML -@@ -1480,7 +1599,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1480,7 +1602,7 @@ class YumRepository(Repository, config.RepoConf): result = self._getFile(relative='repodata/repomd.xml.asc', copy_local=1, local = sigfile, @@ -160054,7 +160403,7 @@ index e5e9ece..21f65f7 100644 reget=None, checkfunc=None, cache=self.http_caching == 'all', -@@ -1514,7 +1633,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1514,7 +1636,7 @@ class YumRepository(Repository, config.RepoConf): return self._checkMD(fn, mdtype, openchecksum) def _checkMD(self, fn, mdtype, openchecksum=False, @@ -160063,7 +160412,7 @@ index e5e9ece..21f65f7 100644 """ Internal function, use .checkMD() from outside yum. """ thisdata = data # So the argument name is nicer -@@ -1537,6 +1656,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -1537,6 +1659,18 @@ class YumRepository(Repository, config.RepoConf): if size is not None: size = int(size) @@ -160082,7 +160431,7 @@ index e5e9ece..21f65f7 100644 try: # get the local checksum l_csum = self._checksum(r_ctype, file, datasize=size) except Errors.RepoError, e: -@@ -1551,15 +1682,13 @@ class YumRepository(Repository, config.RepoConf): +@@ -1551,15 +1685,13 @@ class YumRepository(Repository, config.RepoConf): return None raise URLGrabError(-1, 'Metadata file does not match checksum') @@ -160099,8 +160448,20 @@ index e5e9ece..21f65f7 100644 """ Internal function, use .retrieveMD() from outside yum. """ # Note that this can raise Errors.RepoMDError if mdtype doesn't exist # for this repo. -@@ -1588,7 +1717,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1580,15 +1712,19 @@ class YumRepository(Repository, config.RepoConf): + try: + self.checkMD(local, mdtype) + except URLGrabError, e: ++ if retrieve_can_fail: ++ return None + raise Errors.RepoError, \ + "Caching enabled and local cache: %s does not match checksum" % local + else: + return local + else: # ain't there - raise ++ if retrieve_can_fail: ++ return None raise Errors.RepoError, \ "Caching enabled but no local cache of %s from %s" % (local, - self) @@ -160108,7 +160469,7 @@ index e5e9ece..21f65f7 100644 if (os.path.exists(local) or self._preload_md_from_system_cache(os.path.basename(local))): -@@ -1597,8 +1726,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -1597,8 +1733,10 @@ class YumRepository(Repository, config.RepoConf): return local # it's the same return the local one try: @@ -160121,7 +160482,7 @@ index e5e9ece..21f65f7 100644 if thisdata.size is None: reget = None else: -@@ -1613,8 +1744,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1613,8 +1751,9 @@ class YumRepository(Repository, config.RepoConf): checkfunc=checkfunc, text=text, cache=self.http_caching == 'all', @@ -160133,7 +160494,7 @@ index e5e9ece..21f65f7 100644 if retrieve_can_fail: return None raise -@@ -1622,9 +1754,8 @@ class YumRepository(Repository, config.RepoConf): +@@ -1622,9 +1761,8 @@ class YumRepository(Repository, config.RepoConf): if retrieve_can_fail: return None raise Errors.RepoError, \ @@ -160144,7 +160505,7 @@ index e5e9ece..21f65f7 100644 return local -@@ -1646,13 +1777,21 @@ class YumRepository(Repository, config.RepoConf): +@@ -1646,13 +1784,21 @@ class YumRepository(Repository, config.RepoConf): def getGroups(self): """gets groups and returns group file path for the repository, if there @@ -160155,7 +160516,7 @@ index e5e9ece..21f65f7 100644 + fn = self._retrieveMD('group_gz', retrieve_can_fail=True) + if fn: + try: -+ fn = misc.repo_gen_decompress(fn, 'comps.xml') ++ fn = misc.repo_gen_decompress(fn, 'comps.xml', cached=self.cache) + except IOError, e: + logger.warning(e) + fn = None @@ -160169,7 +160530,7 @@ index e5e9ece..21f65f7 100644 self._callbacks_changed = True def setFailureObj(self, failure_obj): -@@ -1681,7 +1820,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1681,7 +1827,7 @@ class YumRepository(Repository, config.RepoConf): print "Could not read mirrorlist %s, error was \n%s" %(url, e) content = [] for line in content: @@ -160178,6 +160539,24 @@ index e5e9ece..21f65f7 100644 continue mirror = line.rstrip() # no more trailing \n's mirror = mirror.replace('$ARCH', '$BASEARCH') +@@ -1713,7 +1859,7 @@ class YumRepository(Repository, config.RepoConf): + ugopts = self._default_grabopts() + try: + fo = urlgrabber.grabber.urlopen(url, **ugopts) +- except urlgrabber.grabber.URLGrabError, e: ++ except URLGrabError, e: + print "Could not retrieve mirrorlist %s error was\n%s: %s" % (url, e.args[0], misc.to_unicode(e.args[1])) + fo = None + +@@ -1877,7 +2023,7 @@ def getMirrorList(mirrorlist, pdict = None): + + try: + fo = urlresolver.urlopen(url, proxies=pdict) +- except urlgrabber.grabber.URLGrabError, e: ++ except URLGrabError, e: + print "Could not retrieve mirrorlist %s error was\n%s: %s" % (url, e.args[0], misc.to_unicode(e.args[1])) + fo = None + diff --git a/yumcommands.py b/yumcommands.py index 4dcbea7..a2e0b1b 100644 --- a/yumcommands.py diff --git a/yum.spec b/yum.spec index 2d4321e..ffa548b 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 43%{?dist} +Release: 44%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -56,6 +56,8 @@ Requires: python-sqlite Requires: python-urlgrabber >= 3.9.0-8 Requires: yum-metadata-parser >= 1.1.0 Requires: pygpgme +# rawhide is >= 0.5.3-7.fc18 ... as this is added. +Requires: pyliblzma Conflicts: rpm >= 5-0 # Zif is a re-implementation of yum in C, however: @@ -91,7 +93,8 @@ Provides: yum-protect-packages = 1.1.27-0.yum Provides: yum-plugin-protect-packages = 1.1.27-0.yum Obsoletes: yum-plugin-download-order <= 0.2-2 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) - +Obsoletes: yum-plugin-downloadonly <= 1.1.31-6.fc19 +Provides: yum-plugin-downloadonly = 3.4.3-44.yum %description Yum is a utility that can check for and automatically download and @@ -132,6 +135,7 @@ These are the files needed to run yum updates as a cron job. Install this package if you want auto yum updates nightly via cron. + %prep %setup -q %patch4 -p0 @@ -272,6 +276,7 @@ exit 0 %{_sysconfdir}/bash_completion.d %dir %{_datadir}/yum-cli %{_datadir}/yum-cli/* +%exclude %{_datadir}/yum-cli/completion-helper.py? %if %{yum_updatesd} %exclude %{_datadir}/yum-cli/yumupd.py* %endif @@ -315,6 +320,11 @@ exit 0 %endif %changelog +* Wed Oct 17 2012 James Antill - 3.4.3-44 +- update to latest HEAD. +- Add downloadonly into core, and enable background downloads. +- Lots of minor fixes. + * Fri Sep 7 2012 James Antill - 3.4.3-43 - update to latest HEAD. - Use .ui_id explicitly for backcompat. on strings, *sigh*. From 44fef272a7909d8c65551df459b82df31b21c23b Mon Sep 17 00:00:00 2001 From: Nils Philippsen Date: Thu, 25 Oct 2012 16:55:51 +0200 Subject: [PATCH 007/174] bump release to ensure upgrade path and satisfy PackageKit deps --- yum.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yum.spec b/yum.spec index ffa548b..4a9fc05 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 44%{?dist} +Release: 46%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -320,6 +320,9 @@ exit 0 %endif %changelog +* Thu Oct 25 2012 Nils Philippsen - 3.4.3-46 +- bump release to ensure upgrade path and satisfy PackageKit deps + * Wed Oct 17 2012 James Antill - 3.4.3-44 - update to latest HEAD. - Add downloadonly into core, and enable background downloads. From 593f7c0859c7d26ef3c03c89ac6496a23bfd80e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Pavlas?= Date: Thu, 25 Oct 2012 17:19:52 +0200 Subject: [PATCH 008/174] r47, yum-cron.py --- yum-HEAD.patch | 1611 +++++++++++++++++++++++++++++++++++++----------- yum.spec | 14 +- 2 files changed, 1271 insertions(+), 354 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index 6aba05e..c77f5ba 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -1712,6 +1712,15 @@ index 0000000..05801d1 + main(sys.argv[1:]) + except KeyboardInterrupt, e: + sys.exit(1) +diff --git a/docs/Makefile b/docs/Makefile +index dc31d0e..8cc7f9f 100644 +--- a/docs/Makefile ++++ b/docs/Makefile +@@ -13,3 +13,4 @@ install: + install -m 644 yum.conf.5 $(DESTDIR)/usr/share/man/man5/yum.conf.5 + install -m 644 yum-updatesd.8 $(DESTDIR)/usr/share/man/man8/yum-updatesd.8 + install -m 644 yum-updatesd.conf.5 $(DESTDIR)/usr/share/man/man5/yum-updatesd.conf.5 ++ install -m 644 yum-cron.8 $(DESTDIR)/usr/share/man/man8 diff --git a/docs/sphinxdocs/Makefile b/docs/sphinxdocs/Makefile new file mode 100644 index 0000000..623c22b @@ -2310,6 +2319,61 @@ index 0000000..d2a0ed1 + +if __name__ == "__main__": + generateAll(os.getcwd(), os.getcwd()) +diff --git a/docs/yum-cron.8 b/docs/yum-cron.8 +new file mode 100644 +index 0000000..4d01a5a +--- /dev/null ++++ b/docs/yum-cron.8 +@@ -0,0 +1,49 @@ ++.\" yum-cron - cron interface for yum ++.TH "yum-cron" "8" "" "Nick Jacek" "" ++.SH "NAME" ++yum-cron \- an interface to convieniently call yum from cron ++ ++.SH "SYNOPSIS" ++\fByum-cron\fP [config-file] ++ ++.SH "DESCRIPTION" ++.PP ++\fByum-cron\fP is an alternate interface to yum that is optimised to ++be convenient to call from cron. It provides methods to keep ++repository metadata up to date, and to check for, download, and apply ++updates. Rather than accepting many different command line arguments, ++the different functions of yum-cron can be accessed through config ++files. ++.PP ++\fIconfig-file\fP is used to optionally specify the path to the ++configuration file to use. If it is not given, the default ++configuration file will be used. It is useful to be able to specify ++different configuration files for different use cases. For example, ++one configuration file might be set to update the repository metadata, ++and a line could be added to the crontab to run yum-cron frequently ++using this file. Then, another configuration file might be set to ++install updates, and yum-cron could be run from cron using this file ++just once each day. ++ ++.SH "FILES" ++.nf ++/etc/yum-cron.conf ++.fi ++ ++.PP ++.SH "SEE ALSO" ++.nf ++.I yum (8) ++.fi ++ ++.PP ++.SH "AUTHORS" ++.nf ++See the Authors file included with this program. ++.fi ++ ++.PP ++.SH "BUGS" ++There of course aren't any bugs, but if you find any, you should email ++ the mailing list, yum@lists.baseurl.org, or consult bugzilla. ++.fi diff --git a/docs/yum.8 b/docs/yum.8 index 1a8202a..65ff448 100644 --- a/docs/yum.8 @@ -2967,11 +3031,17 @@ index 0cfaa4b..0000000 - -exit 0 diff --git a/etc/Makefile b/etc/Makefile -index 29a7f95..a512cdf 100644 +index 29a7f95..ec5af83 100644 --- a/etc/Makefile +++ b/etc/Makefile -@@ -29,10 +29,3 @@ install: +@@ -24,15 +24,7 @@ install: + mkdir -p $(DESTDIR)/etc/dbus-1/system.d/ + install -m 755 yum-updatesd-dbus.conf $(DESTDIR)/etc/dbus-1/system.d/yum-updatesd.conf +- +- install -m 755 yum-updatesd.conf $(DESTDIR)/etc/yum/yum-updatesd.conf +- ++ install -m 644 yum-updatesd.conf $(YUMETC) mkdir -p $(DESTDIR)/etc/bash_completion.d install -m 644 yum.bash $(DESTDIR)/etc/bash_completion.d - mkdir -p $(DESTDIR)/etc/cron.daily @@ -2981,6 +3051,7 @@ index 29a7f95..a512cdf 100644 - install -D -m 644 yum-daily.yum $(YUMETC)/yum-daily.yum - install -D -m 644 yum-weekly.yum $(YUMETC)/yum-weekly.yum - install -D -m 644 yum-cron.sysconf $(DESTDIR)/etc/sysconfig/yum-cron ++ install -m 644 yum-cron.conf $(YUMETC) diff --git a/etc/yum-cron b/etc/yum-cron deleted file mode 100755 index 63c5ec0..0000000 @@ -3089,6 +3160,67 @@ index 63c5ec0..0000000 -esac - -exit $RETVAL +diff --git a/etc/yum-cron.conf b/etc/yum-cron.conf +new file mode 100644 +index 0000000..269c6b7 +--- /dev/null ++++ b/etc/yum-cron.conf +@@ -0,0 +1,55 @@ ++[commands] ++# Whether a message should emitted when updates are available. ++update_messages = yes ++ ++# Whether updates should be downloaded when they are available. Note ++# that updates_messages must also be yes for updates to be downloaded. ++download_updates = no ++ ++# Whether updates should be applied when they are available. Note ++# that both update_messages and download_updates must also be yes for ++# the update to be applied ++apply_updates = no ++ ++# Maximum amout of time to randomly sleep, in minutes. The program ++# will sleep for a random amount of time between 0 and random_sleep ++# minutes before running. This is useful for e.g. staggering the ++# times that multiple systems will access update servers. If ++# random_sleep is 0 or negative, the program will run immediately. ++random_sleep = 0 ++ ++ ++[emitters] ++# Name to use for this system in messages that are emitted. If ++# system_name is None, the hostname will be used. ++system_name = None ++ ++# How to send messages. Valid options are stdio and email. If ++# emit_via includes stdio, messages will be sent to stdout; this is useful ++# to have cron send the messages. If emit_via includes email, this ++# program will send email itself according to the configured options. ++# If emit_via is None or left blank, no messages will be sent. ++emit_via = stdio ++ ++# The width, in characters, that messages that are emitted should be ++# formatted to. ++ouput_width = 80 ++ ++ ++[email] ++# The address to send email messages from. ++email_from = root ++ ++# List of addresses to send messages to. ++email_to = root ++ ++# Name of the host to connect to to send email messages. ++email_host = localhost ++ ++ ++[groups] ++# List of groups to update ++group_list = None ++ ++# The types of group packages to install ++group_package_types = mandatory, default diff --git a/etc/yum-cron.sysconf b/etc/yum-cron.sysconf deleted file mode 100644 index 930341c..0000000 @@ -150040,10 +150172,10 @@ index ced6ba0..e465cf7 return_code = self.doTransaction() diff --git a/yum-cron/Makefile b/yum-cron/Makefile new file mode 100644 -index 0000000..34cb397 +index 0000000..1a68a3c --- /dev/null +++ b/yum-cron/Makefile -@@ -0,0 +1,21 @@ +@@ -0,0 +1,15 @@ +all: + echo "Nothing to do" + @@ -150054,17 +150186,11 @@ index 0000000..34cb397 + mkdir -p $(DESTDIR)/etc/cron.daily + mkdir -p $(DESTDIR)/etc/rc.d/init.d + mkdir -p $(DESTDIR)/usr/sbin -+ mkdir -p $(DESTDIR)/etc/sysconfig -+ mkdir -p $(DESTDIR)/usr/share/yum-cron +# Install yum-update.cron as 0yum-update.cron so it runs before items like +# manpage update, mlocate, and prelink + install -D -m 755 yum-update.cron.sh $(DESTDIR)/etc/cron.daily/0yum-update.cron -+ install -D -m 755 yum-cleanup.cron.sh $(DESTDIR)/etc/cron.daily/yum-cleanup.cron + install -D -m 755 yum-cron.sysvinit $(DESTDIR)/etc/rc.d/init.d/yum-cron -+ install -D -m 755 yum-cron.sh $(DESTDIR)/usr/sbin/yum-cron -+ install -D -m 644 yum-cron.sysconfig $(DESTDIR)/etc/sysconfig/yum-cron -+ install -D -m 644 update.yum $(DESTDIR)/usr/share/yum-cron/update.yum -+ install -D -m 644 cleanup.yum $(DESTDIR)/usr/share/yum-cron/cleanup.yum ++ install -D -m 755 yum-cron.py $(DESTDIR)/usr/sbin/yum-cron diff --git a/yum-cron/TODO b/yum-cron/TODO new file mode 100644 index 0000000..28e1964 @@ -150090,341 +150216,1131 @@ index 0000000..28e1964 +- Figure out what to do with systemd +- Update rpm, glibc, yum, python, specially? +- Check if we're running as root; exit nicely. -diff --git a/yum-cron/cleanup.yum b/yum-cron/cleanup.yum -new file mode 100644 -index 0000000..c60fa08 ---- /dev/null -+++ b/yum-cron/cleanup.yum -@@ -0,0 +1,4 @@ -+clean packages -+clean expire-cache -+ts run -+exit -diff --git a/yum-cron/update.yum b/yum-cron/update.yum -new file mode 100644 -index 0000000..5d4e874 ---- /dev/null -+++ b/yum-cron/update.yum -@@ -0,0 +1,3 @@ -+update -+ts run -+exit -diff --git a/yum-cron/yum-cleanup.cron.sh b/yum-cron/yum-cleanup.cron.sh +diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py new file mode 100755 -index 0000000..e38e80f +index 0000000..44fc785 --- /dev/null -+++ b/yum-cron/yum-cleanup.cron.sh -@@ -0,0 +1,30 @@ -+#!/bin/bash ++++ b/yum-cron/yum-cron.py +@@ -0,0 +1,1113 @@ ++#!/usr/bin/python -tt ++import os ++import sys ++import gzip ++from socket import gethostname + -+# Only run if this flag is set. The flag is created by the yum-cron init -+# script when the service is started -- this allows one to use chkconfig and -+# the standard "service stop|start" commands to enable or disable yum-cron. -+if [[ ! -f /var/lock/subsys/yum-cron ]]; then -+ exit 0 -+fi ++import yum ++import yum.Errors ++from yum.config import BaseConfig, Option, IntOption, ListOption, BoolOption ++from yum.parser import ConfigPreProcessor ++from ConfigParser import ConfigParser, ParsingError ++from yum.constants import * ++from yum.update_md import UpdateMetadata ++from email.mime.text import MIMEText ++from yum.i18n import to_str, to_utf8, to_unicode, utf8_width, utf8_width_fill, utf8_text_fill ++from yum import _, P_ ++import smtplib ++from random import random ++from time import sleep + -+# Read configuration settings from the sysconfig directory. -+if [[ -f /etc/sysconfig/yum-cron ]]; then -+ source /etc/sysconfig/yum-cron -+fi ++# FIXME: is it really sane to use this from here? ++sys.path.append('/usr/share/yum-cli') ++import callback + -+# Only run on certain days of the week, based on the -+# settings in the above-mentioned sysconfig file. -+dow=`date +%w` -+DAYS_OF_WEEK=${DAYS_OF_WEEK:-0123456} -+if [[ "${DAYS_OF_WEEK/$dow/}" == "${DAYS_OF_WEEK}" ]]; then -+ exit 0 -+fi ++default_config_file = '/etc/yum/yum-cron.conf' + -+# And only _clean_ on a subset of the configured days. -+CLEANDAY=${CLEANDAY:-0} -+if [[ "${CLEANDAY/$dow/}" == "${CLEANDAY}" ]]; then -+ exit 0 -+fi ++class UpdateEmitter(object): ++ """Abstract class for implementing different types of emitters. ++ Most methods will add certain messages the output list. Then, ++ the sendMessage method can be overridden in a subclass to ++ combine these messages and transmit them as required. ++ """ + -+# Action! -+exec /usr/sbin/yum-cron cleanup -diff --git a/yum-cron/yum-cron.sh b/yum-cron/yum-cron.sh -new file mode 100755 -index 0000000..e300fa7 ---- /dev/null -+++ b/yum-cron/yum-cron.sh -@@ -0,0 +1,170 @@ -+#!/bin/bash ++ def __init__(self, opts): ++ self.opts = opts ++ self.output = [] + -+# This script is designed to be run from cron to automatically keep your -+# system up to date with the latest security patches and bug fixes. It -+# can download and/or apply package updates as configured in -+# /etc/sysconfig/yum-cron. ++ def updatesAvailable(self, tsInfo): ++ """Appends a message to the output list stating that there are ++ updates available. ++ ++ :param tsInfo: A :class:`yum.transactioninfo.TransactionData` ++ instance that contains information about the transaction. ++ """ ++ self.output.append('The following updates are available on %s:' % self.opts.system_name) ++ self.output.append(self._formatTransaction(tsInfo)) ++ ++ def updatesDownloading(self, tsInfo): ++ """Append a message to the output list stating that ++ downloading updates has started. ++ ++ :param tsInfo: A :class:`yum.transactioninfo.TransactionData` ++ instance that contains information about the transaction. ++ """ ++ self.output.append('The following updates will be downloaded on %s:' % self.opts.system_name) ++ self.output.append(self._formatTransaction(tsInfo)) ++ ++ def updatesDownloaded(self): ++ """Append a message to the output list stating that updates ++ have been downloaded successfully. ++ """ ++ self.output.append("Updates downloaded successfully.") ++ ++ def updatesInstalling(self, tsInfo): ++ """Append a message to the output list stating that ++ installing updates has started. ++ ++ :param tsInfo: A :class:`yum.transactioninfo.TransactionData` ++ instance that contains information about the transaction. ++ """ ++ self.output.append('The following updates will be applied on %s:' % self.opts.system_name) ++ self.output.append(self._formatTransaction(tsInfo)) ++ ++ def updatesInstalled(self): ++ """Append a message to the output list stating that updates ++ have been installed successfully. ++ """ ++ self.output.append('The updates were sucessfully applied') ++ ++ def setupFailed(self, errmsg): ++ """Append a message to the output list stating that setup ++ failed, and then call sendMessages to emit the output. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.output.append("Plugins failed to initialize with the following error message: \n%s" ++ % errmsg) ++ self.sendMessages() ++ ++ def lockFailed(self, errmsg): ++ """Append a message to the output list stating that the ++ program failed to acquire the yum lock, then call sendMessages ++ to emit the output. ++ ++ :param errmsg: a string that contains the error message ++ """ ++ self.output.append("Failed to acquire the yum lock with the following error message: \n%s" ++ % errmsg) ++ self.sendMessages() ++ ++ def checkFailed(self, errmsg): ++ """Append a message to the output stating that checking for ++ updates failed, then call sendMessages to emit the output. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.output.append("Failed to check for updates with the following error message: \n%s" ++ % errmsg) ++ self.sendMessages() ++ ++ def groupError(self, errmsg): ++ """Append a message to the output list stating that an error ++ was encountered while checking for group updates. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.output.append("Error checking for group updates: \n%s" ++ % errmsg) ++ ++ def groupFailed(self, errmsg): ++ """Append a message to the output list stating that checking ++ for group updates failed, then call sendMessages to emit the output. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.output.append("Failed to check for updates with the following error message: \n%s" ++ % errmsg) ++ self.sendMessages() ++ ++ def downloadFailed(self, errmsg): ++ """Append a message to the output list stating that ++ downloading updates failed, then call sendMessages to emit the output. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.output.append("Updates failed to download with the following error message: \n%s" ++ % errmsg) ++ self.sendMessages() ++ ++ def updatesFailed(self, errmsg): ++ """Append a message to the output list stating that installing ++ updates failed, then call sendMessages to emit the output. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.output.append("Updates failed to install with the following error message: \n%s" ++ % errmsg) ++ self.sendMessages() ++ ++ def sendMessages(self): ++ """Send the messages that have been stored. This should be ++ overridden by inheriting classes to emit the messages ++ according to their individual methods. ++ """ ++ pass ++ ++ def _format_number(self, number, SI=0, space=' '): ++ """Return a human-readable metric-like string representation ++ of a number. ++ ++ :param number: the number to be converted to a human-readable form ++ :param SI: If is 0, this function will use the convention ++ that 1 kilobyte = 1024 bytes, otherwise, the convention ++ that 1 kilobyte = 1000 bytes will be used ++ :param space: string that will be placed between the number ++ and the SI prefix ++ :return: a human-readable metric-like string representation of ++ *number* ++ """ ++ symbols = [ ' ', # (none) ++ 'k', # kilo ++ 'M', # mega ++ 'G', # giga ++ 'T', # tera ++ 'P', # peta ++ 'E', # exa ++ 'Z', # zetta ++ 'Y'] # yotta ++ ++ if SI: step = 1000.0 ++ else: step = 1024.0 ++ ++ thresh = 999 ++ depth = 0 ++ max_depth = len(symbols) - 1 ++ ++ # we want numbers between 0 and thresh, but don't exceed the length ++ # of our list. In that event, the formatting will be screwed up, ++ # but it'll still show the right number. ++ while number > thresh and depth < max_depth: ++ depth = depth + 1 ++ number = number / step ++ ++ if type(number) == type(1) or type(number) == type(1L): ++ format = '%i%s%s' ++ elif number < 9.95: ++ # must use 9.95 for proper sizing. For example, 9.99 will be ++ # rounded to 10.0 with the .1f format string (which is too long) ++ format = '%.1f%s%s' ++ else: ++ format = '%.0f%s%s' ++ ++ return(format % (float(number or 0), space, symbols[depth])) ++ ++ def _fmtColumns(self, columns, msg=u'', end=u'', text_width=utf8_width): ++ """Return a row of data formatted into a string for output. ++ Items can overflow their columns. ++ ++ :param columns: a list of tuples containing the data to ++ output. Each tuple contains first the item to be output, ++ then the amount of space allocated for the column, and then ++ optionally a type of highlighting for the item ++ :param msg: a string to begin the line of output with ++ :param end: a string to end the line of output with ++ :param text_width: a function to find the width of the items ++ in the columns. This defaults to utf8 but can be changed ++ to len() if you know it'll be fine ++ :return: a row of data formatted into a string for output ++ """ ++ total_width = len(msg) ++ data = [] ++ for col_data in columns[:-1]: ++ (val, width) = col_data ++ ++ if not width: # Don't count this column, invisible text ++ msg += u"%s" ++ data.append(val) ++ continue ++ ++ (align, width) = self._fmt_column_align_width(width) ++ val_width = text_width(val) ++ if val_width <= width: ++ # Don't use utf8_width_fill() because it sucks performance ++ # wise for 1,000s of rows. Also allows us to use len(), when ++ # we can. ++ msg += u"%s%s " ++ if (align == u'-'): ++ data.extend([val, " " * (width - val_width)]) ++ else: ++ data.extend([" " * (width - val_width), val]) ++ else: ++ msg += u"%s\n" + " " * (total_width + width + 1) ++ data.append(val) ++ total_width += width ++ total_width += 1 ++ (val, width) = columns[-1] ++ (align, width) = self._fmt_column_align_width(width) ++ val = utf8_width_fill(val, width, left=(align == u'-')) ++ msg += u"%%s%s" % end ++ data.append(val) ++ return msg % tuple(data) ++ ++ def _calcColumns(self, data, total_width, columns=None, remainder_column=0, indent=''): ++ """Dynamically calculate the widths of the columns that the ++ fields in data should be placed into for output. ++ ++ :param data: a list of dictionaries that represent the data to ++ be output. Each dictionary in the list corresponds to annn ++ column of output. The keys of the dictionary are the ++ lengths of the items to be output, and the value associated ++ with a key is the number of items of that length. ++ :param total_width: the total width of the output. ++ :param columns: a list containing the minimum amount of space ++ that must be allocated for each row. This can be used to ++ ensure that there is space available in a column if, for ++ example, the actual lengths of the items being output ++ cannot be given in *data* ++ :param remainder_column: number of the column to receive a few ++ extra spaces that may remain after other allocation has ++ taken place ++ :param indent: string that will be prefixed to a line of ++ output to create e.g. an indent ++ :return: a list of the widths of the columns that the fields ++ in data should be placed into for output ++ """ ++ if total_width is None: ++ total_width = self.term.columns ++ ++ cols = len(data) ++ # Convert the data to ascending list of tuples, (field_length, pkgs) ++ pdata = data ++ data = [None] * cols # Don't modify the passed in data ++ for d in range(0, cols): ++ data[d] = sorted(pdata[d].items()) ++ ++ # We start allocating 1 char to everything but the last column, and a ++ # space between each (again, except for the last column). Because ++ # at worst we are better with: ++ # |one two three| ++ # | four | ++ # ...than: ++ # |one two three| ++ # | f| ++ # |our | ++ # ...the later being what we get if we pre-allocate the last column, and ++ # thus. the space, due to "three" overflowing it's column by 2 chars. ++ if columns is None: ++ columns = [1] * (cols - 1) ++ columns.append(0) ++ ++ total_width -= (sum(columns) + (cols - 1) + ++ utf8_width(indent)) ++ if not columns[-1]: ++ total_width += 1 ++ while total_width > 0: ++ # Find which field all the spaces left will help best ++ helps = 0 ++ val = 0 ++ for d in xrange(0, cols): ++ thelps = self._calc_columns_spaces_helps(columns[d], data[d], ++ total_width) ++ if not thelps: ++ continue ++ # We prefer to overflow: the last column, and then earlier ++ # columns. This is so that in the best case (just overflow the ++ # last) ... grep still "works", and then we make it prettier. ++ if helps and (d == (cols - 1)) and (thelps / 2) < helps: ++ continue ++ if thelps < helps: ++ continue ++ helps = thelps ++ val = d ++ ++ # If we found a column to expand, move up to the next level with ++ # that column and start again with any remaining space. ++ if helps: ++ diff = data[val].pop(0)[0] - columns[val] ++ if not columns[val] and (val == (cols - 1)): ++ # If we are going from 0 => N on the last column, take 1 ++ # for the space before the column. ++ total_width -= 1 ++ columns[val] += diff ++ total_width -= diff ++ continue ++ ++ overflowed_columns = 0 ++ for d in xrange(0, cols): ++ if not data[d]: ++ continue ++ overflowed_columns += 1 ++ if overflowed_columns: ++ # Split the remaining spaces among each overflowed column ++ # equally ++ norm = total_width / overflowed_columns ++ for d in xrange(0, cols): ++ if not data[d]: ++ continue ++ columns[d] += norm ++ total_width -= norm ++ ++ # Split the remaining spaces among each column equally, except the ++ # last one. And put the rest into the remainder column ++ cols -= 1 ++ norm = total_width / cols ++ for d in xrange(0, cols): ++ columns[d] += norm ++ columns[remainder_column] += total_width - (cols * norm) ++ total_width = 0 ++ ++ return columns ++ ++ @staticmethod ++ def _fmt_column_align_width(width): ++ if width < 0: ++ return (u"-", -width) ++ return (u"", width) ++ ++ @staticmethod ++ def _calc_columns_spaces_helps(current, data_tups, left): ++ """ Spaces left on the current field will help how many pkgs? """ ++ ret = 0 ++ for tup in data_tups: ++ if left < (tup[0] - current): ++ break ++ ret += tup[1] ++ return ret ++ ++ def _formatTransaction(self, tsInfo): ++ """Return a string containing a human-readable formatted ++ summary of the transaction. ++ ++ :param tsInfo: :class:`yum.transactioninfo.TransactionData` ++ instance that contains information about the transaction ++ :return: a string that contains a formatted summary of the ++ transaction ++ """ ++ # Sort the packages in the transaction into different lists, ++ # e.g. installed, updated etc ++ tsInfo.makelists(True, True) ++ ++ # For each package list, pkglist_lines will contain a tuple ++ # that contains the name of the list, and a list of tuples ++ # with information about each package in the list ++ pkglist_lines = [] ++ data = {'n' : {}, 'v' : {}, 'r' : {}} ++ a_wid = 0 # Arch can't get "that big" ... so always use the max. + + -+# This is used by /etc/init.d/yum-cron on shutdown to protect against -+# abruptly shutting down mid-transaction. Therefore, you shouldn't change -+# it without changing that. -+PIDFILE=/var/lock/yum-cron.pid ++ def _add_line(lines, data, a_wid, po, obsoletes=[]): ++ # Create a tuple of strings that contain the name, arch, ++ # version, repository, size, and obsoletes of the package ++ # given in po. Then, append this tuple to lines. The ++ # strings are formatted so that the tuple can be easily ++ # joined together for output. + -+# This is the home of the yum scripts which power the various actions the -+# yum-cron system performs. -+SCRIPTDIR=/usr/share/yum-cron/ ++ ++ (n,a,e,v,r) = po.pkgtup ++ ++ # Retrieve the version, repo id, and size of the package ++ # in human-readable form ++ evr = po.printVer() ++ repoid = po.ui_from_repo ++ size = self._format_number(float(po.size)) + -+# If no command line options were given, exit with a usage message. -+if [[ -z "$1" ]]; then -+ echo "Usage: yum-cron {update|cleanup|...}" -+ exit 1 -+else -+ ACTION=$1 -+fi ++ if a is None: # gpgkeys are weird ++ a = 'noarch' + -+# If a command line option was given, it must match a yum script. -+YUMSCRIPT=${SCRIPTDIR}/${ACTION}.yum -+if [[ ! -r $YUMSCRIPT ]]; then -+ echo "Script for action \"$ACTION\" is not readable in $SCRIPTDIR." -+ exit 1 -+fi ++ lines.append((n, a, evr, repoid, size, obsoletes)) ++ # Create a dict of field_length => number of packages, for ++ # each field. ++ for (d, v) in (("n",len(n)), ("v",len(evr)), ("r",len(repoid))): ++ data[d].setdefault(v, 0) ++ data[d][v] += 1 ++ a_wid = max(a_wid, len(a)) + -+# This must be set above. But there a couple of places where horrible -+# things might happen if it's unset, so, let's check. -+if [[ -z "$PIDFILE" ]]; then -+ echo "Error! \$PIDFILE variable must be set in yum-cron." -+ exit 1 -+fi ++ return a_wid + -+# Read the settings from our config file. -+if [[ -f /etc/sysconfig/yum-cron ]]; then -+ source /etc/sysconfig/yum-cron -+fi ++ + -+# If no system name is set, use the hostname. -+[[ -z "$SYSTEMNAME" ]] && SYSTEMNAME=$( hostname ) ++ # Iterate through the different groups of packages ++ for (action, pkglist) in [(_('Installing'), tsInfo.installed), ++ (_('Updating'), tsInfo.updated), ++ (_('Removing'), tsInfo.removed), ++ (_('Reinstalling'), tsInfo.reinstalled), ++ (_('Downgrading'), tsInfo.downgraded), ++ (_('Installing for dependencies'), tsInfo.depinstalled), ++ (_('Updating for dependencies'), tsInfo.depupdated), ++ (_('Removing for dependencies'), tsInfo.depremoved)]: ++ # Create a list to hold the tuples of strings for each package ++ lines = [] + -+# If DOWNLOAD_ONLY is set, then we force CHECK_ONLY too. -+# Gotta check for updates before we can possibly download them. -+[[ "$DOWNLOAD_ONLY" == "yes" ]] && CHECK_ONLY=yes ++ # Append the tuple for each package to lines, and update a_wid ++ for txmbr in pkglist: ++ a_wid = _add_line(lines, data, a_wid, txmbr.po, txmbr.obsoletes) + -+# This holds the output from the "meat" of this script, so that it can -+# be nicely mailed to the configured destination when we're done. -+YUMOUTPUT=$(mktemp /var/run/yum-cron.XXXXXX) -+touch $YUMOUTPUT -+[[ -x /sbin/restorecon ]] && /sbin/restorecon $YUMOUTPUT ++ # Append the lines instance for this package list to pkglist_lines ++ pkglist_lines.append((action, lines)) + -+# Here is the gigantic block of lockfile logic. -+# -+# Note: the lockfile code doesn't currently try and use YUMOUTPUT to email -+# messages nicely, so this gets handled by normal cron error mailing. -+# -+ -+# We use noclobber for the pidfile, as this will test for and if possible -+# create the file in one atomic action. (So there's no race condition.) The -+# current process ID is stored in the file so we can check for staleness -+# later. -+if (set -o noclobber; echo "$$" > $PIDFILE) 2>/dev/null; then -+ # We got the lock. So now, set a trap to clean up locks and the output -+ # tempfile when the script exits or is killed. -+ trap "rm -f $PIDFILE" INT TERM EXIT -+else -+ # Lock failed -- check if a running process exists. -+ # First, if there's no PID file in the lock directory, something bad has -+ # happened. We can't know the process name, so, restart. -+ if [[ ! -f $PIDFILE ]]; then -+ echo "yum-cron: no lock PID, restarting myself" >&2 -+ exec $0 "$@" -+ fi -+ OTHERPID="$(< $PIDFILE)" 2>/dev/null -+ # if cat wasn't able to read the file anymore, another instance probably is -+ # about to remove the lock -- exit, we're *still* locked -+ if [[ $? != 0 ]]; then -+ echo "yum-cron: lock failed, PID ${OTHERPID} is active" >&2 -+ exit 0 -+ fi -+ if ! kill -0 $OTHERPID &>/dev/null; then -+ # Lock is stale. Remove it and restart. -+ echo "yum-cron: removing stale lock of nonexistant PID ${OTHERPID}" >&2 -+ rm -f $PIDFILE -+ echo "yum-cron: restarting myself" >&2 -+ exec $0 "$@" -+ else -+ # Remove lockfiles more than a day old -- they must be stale. -+ find $PIDFILE -type f -amin +1440 -exec rm -f $PIDFILE \; -+ # If it's still there, it *wasn't* too old. Bail! -+ if [[ -f $PIDFILE ]]; then -+ # Lock is valid and OTHERPID is active -- exit, we're locked! -+ echo "yum-cron: lock failed, PID ${OTHERPID} is active" >&2 -+ exit 0 -+ else -+ # Lock was invalid. Restart. -+ echo "yum-cron: removed stale lock belonging to PID ${OTHERPID}; restarting." >&2 -+ exec $0 "$@" -+ fi -+ fi -+fi ++ # # Iterate through other package lists ++ # for (action, pkglist) in [(_('Skipped (dependency problems)'), ++ # self.skipped_packages), ++ # (_('Not installed'), self._not_found_i.values()), ++ # (_('Not available'), self._not_found_a.values())]: ++ # lines = [] ++ # for po in pkglist: ++ # a_wid = _add_line(lines, data, a_wid, po) + -+# Now, do the actual work. ++ # pkglist_lines.append((action, lines)) + -+# We special case "update" because it has complicated conditionals; for -+# everything else we just run yum with the right parameters and -+# corresponding script. Right now, that's just "cleanup" but theoretically -+# there could be other actions. -+{ -+ case "$ACTION" in -+ update) -+ # There's three broad possibilties here: -+ # CHECK_ONLY (possibly with DOWNLOAD_ONLY) -+ # CHECK_FIRST (exits _silently_ if we can't access the repos) -+ # nothing special -- just do it -+ # Note that in all cases, yum is updated first, and then -+ # everything else. -+ if [[ "$CHECK_ONLY" == "yes" ]]; then -+ /usr/bin/yum $YUM_PARAMETER -e 0 -d 0 -y check-update 1> /dev/null 2>&1 -+ case $? in -+ 1) exit 1;; -+ 100) echo "New updates available for host $SYSTEMNAME"; -+ /usr/bin/yum $YUM_PARAMETER -e ${ERROR_LEVEL:-0} -d ${DEBUG_LEVEL:-0} -y -C check-update -+ if [[ "$DOWNLOAD_ONLY" == "yes" ]]; then -+ /usr/bin/yum $YUM_PARAMETER -e ${ERROR_LEVEL:-0} -d ${DEBUG_LEVEL:-0} -y --downloadonly update -+ echo "Updates downloaded. Use \"yum -C update\" manually to install them." -+ fi -+ ;; -+ esac -+ elif [[ "$CHECK_FIRST" == "yes" ]]; then -+ # Don't run if we can't access the repos -- if this is set, -+ # and there's a problem, we exit silently (but return an error -+ # code). -+ /usr/bin/yum $YUM_PARAMETER -e 0 -d 0 check-update 2>&- -+ case $? in -+ 1) exit 1;; -+ 100) /usr/bin/yum $YUM_PARAMETER -e ${ERROR_LEVEL:-0} -d ${DEBUG_LEVEL:-0} -y update yum -+ /usr/bin/yum $YUM_PARAMETER -e ${ERROR_LEVEL:-0} -d ${DEBUG_LEVEL:-0} -y shell $YUMSCRIPT -+ ;; -+ esac -+ else -+ # and here's the "just do it". -+ /usr/bin/yum $YUM_PARAMETER -e ${ERROR_LEVEL:-0} -d ${DEBUG_LEVEL:-0} -y update yum -+ /usr/bin/yum $YUM_PARAMETER -e ${ERROR_LEVEL:-0} -d ${DEBUG_LEVEL:-0} -y shell $YUMSCRIPT -+ fi -+ ;; -+ *) -+ /usr/bin/yum $YUM_PARAMETER -e ${ERROR_LEVEL:-0} -d ${DEBUG_LEVEL:-0} -y shell $YUMSCRIPT -+ ;; -+ esac ++ if not data['n']: ++ return u'' ++ else: ++ # Change data to a list with the correct number of ++ # columns, in the correct order ++ data = [data['n'], {}, data['v'], data['r'], {}] + -+} >> $YUMOUTPUT 2>&1 ++ ++ ++ # Calculate the space needed for each column ++ columns = [1, a_wid, 1, 1, 5] + -+if [[ ! -z "$MAILTO" && -x /bin/mail ]]; then -+# If MAILTO is set, use mail command for prettier output. -+ [[ -s "$YUMOUTPUT" ]] && \ -+ mail -s "System update: $SYSTEMNAME" $MAILTO < $YUMOUTPUT && \ -+ rm -f $YUMOUTPUT -+else -+# The default behavior is to use cron's internal mailing of output. -+ cat $YUMOUTPUT && rm -f $YUMOUTPUT -+fi ++ columns = self._calcColumns(data, self.opts.output_width, ++ columns, remainder_column = 2, indent=" ") + -+exit 0 -diff --git a/yum-cron/yum-cron.sysconfig b/yum-cron/yum-cron.sysconfig -new file mode 100644 -index 0000000..53477d3 ---- /dev/null -+++ b/yum-cron/yum-cron.sysconfig -@@ -0,0 +1,92 @@ -+# This is the configuration file for yum-cron, a simple system for -+# keeping your machine up to date. These options are used variously by -+# the main script, by the cron scripts, and by the init script. ++ (n_wid, a_wid, v_wid, r_wid, s_wid) = columns ++ assert s_wid == 5 + -+# Main Options -+#-------------------------------------------------------------------------- ++ # out will contain the output as a list of strings, that ++ # can be later joined together ++ out = [u""" ++%s ++%s ++%s ++""" % ('=' * self.opts.output_width, ++ self._fmtColumns(((_('Package'), -n_wid), (_('Arch'), -a_wid), ++ (_('Version'), -v_wid), (_('Repository'), -r_wid), ++ (_('Size'), s_wid)), u" "), ++ '=' * self.opts.output_width)] + -+# Pass any given parameter to yum, as run in all the scripts invoked by -+# this package. Be aware that this is global, and yum is invoked in -+# several modes by these scripts, and your parameter might not be -+# appropriate in all cases. -+YUM_PARAMETER= ++ # Add output for each package list in pkglist_lines ++ for (action, lines) in pkglist_lines: ++ #If the package list is empty, skip it ++ if not lines: ++ continue + -+# Don't install; just check and report. -+# (Valid options: yes|no) -+CHECK_ONLY=no ++ # Add the name of the package list ++ totalmsg = u"%s:\n" % action ++ # Add a line of output about an individual package ++ for (n, a, evr, repoid, size, obsoletes) in lines: ++ columns = ((n, -n_wid), (a, -a_wid), ++ (evr, -v_wid), (repoid, -r_wid), (size, s_wid)) ++ msg = self._fmtColumns(columns, u" ", u"\n") ++ for obspo in sorted(obsoletes): ++ appended = _(' replacing %s.%s %s\n') ++ appended %= (obspo.name, ++ obspo.arch, obspo.printVer()) ++ msg = msg+appended ++ totalmsg = totalmsg + msg + -+# Don't install; just check for and download any pending updates. This -+# implies CHECK_ONLY=yes, as we've gotta check first to see what to -+# download. -+# (Valid options: yes|no) -+DOWNLOAD_ONLY=no ++ # Append the line about the individual package to out ++ out.append(totalmsg) + -+# Check to see if we can reach the repos before attempting an update. -+# If there is an error, exit silently with no output. You might want -+# this if you know your network connectivity is sporadic. -+# (Valid options: yes|no) -+CHECK_FIRST=no ++ # Add a summary of the transaction ++ out.append(_(""" ++Transaction Summary ++%s ++""") % ('=' * self.opts.output_width)) ++ summary_data = ( ++ (_('Install'), len(tsInfo.installed), ++ len(tsInfo.depinstalled)), ++ (_('Upgrade'), len(tsInfo.updated), ++ len(tsInfo.depupdated)), ++ (_('Remove'), len(tsInfo.removed), ++ len(tsInfo.depremoved)), ++ (_('Reinstall'), len(tsInfo.reinstalled), 0), ++ (_('Downgrade'), len(tsInfo.downgraded), 0), ++ # (_('Skipped (dependency problems)'), len(self.skipped_packages), 0), ++ # (_('Not installed'), len(self._not_found_i.values()), 0), ++ # (_('Not available'), len(self._not_found_a.values()), 0), ++ ) ++ max_msg_action = 0 ++ max_msg_count = 0 ++ max_msg_pkgs = 0 ++ max_msg_depcount = 0 ++ for action, count, depcount in summary_data: ++ if not count and not depcount: ++ continue ++ ++ msg_pkgs = P_('Package', 'Packages', count) ++ len_msg_action = utf8_width(action) ++ len_msg_count = utf8_width(str(count)) ++ len_msg_pkgs = utf8_width(msg_pkgs) ++ ++ if depcount: ++ len_msg_depcount = utf8_width(str(depcount)) ++ else: ++ len_msg_depcount = 0 ++ ++ max_msg_action = max(len_msg_action, max_msg_action) ++ max_msg_count = max(len_msg_count, max_msg_count) ++ max_msg_pkgs = max(len_msg_pkgs, max_msg_pkgs) ++ max_msg_depcount = max(len_msg_depcount, max_msg_depcount) ++ ++ for action, count, depcount in summary_data: ++ msg_pkgs = P_('Package', 'Packages', count) ++ if depcount: ++ msg_deppkgs = P_('Dependent package', 'Dependent packages', ++ depcount) ++ if count: ++ msg = '%s %*d %s (+%*d %s)\n' ++ out.append(msg % (utf8_width_fill(action, max_msg_action), ++ max_msg_count, count, ++ utf8_width_fill(msg_pkgs, max_msg_pkgs), ++ max_msg_depcount, depcount, msg_deppkgs)) ++ else: ++ msg = '%s %*s %s ( %*d %s)\n' ++ out.append(msg % (utf8_width_fill(action, max_msg_action), ++ max_msg_count, '', ++ utf8_width_fill('', max_msg_pkgs), ++ max_msg_depcount, depcount, msg_deppkgs)) ++ elif count: ++ msg = '%s %*d %s\n' ++ out.append(msg % (utf8_width_fill(action, max_msg_action), ++ max_msg_count, count, msg_pkgs)) ++ ++ return ''.join(out) + + -+# Yum error level. The practical range is 0-10, where 0 means print -+# only critical errors, and 10 means print all errors, even ones that -+# are not important. Level 0 is the default if nothing is set. -+ERROR_LEVEL=0 ++class EmailEmitter(UpdateEmitter): ++ """Emitter class to send messages via email.""" + -+# Yum debug level. The practical range is 0-10; a higher number means -+# more output. Level 1 is a useful level if you want to see what's been -+# done and don't want to read /var/log/yum.log. Level 0 is the default -+# if no value is set here. -+DEBUG_LEVEL=0 ++ def __init__(self, opts): ++ super(EmailEmitter, self).__init__(opts) ++ self.subject = "" + -+# If MAILTO is set and the /bin/mail command is available, the mail -+# command is used to deliver yum output. If MAILTO is unset, crond will -+# send the output by itself, usually to root (but with a less useful -+# subject line). -+MAILTO=root ++ def updatesAvailable(self, tsInfo): ++ """Appends a message to the output list stating that there are ++ updates available, and set an appropriate subject line. + -+# The reports generated by this command generally use the hostname of -+# the system as reported by the hostname command. If you'd prefer to -+# use something else, you can set that here. -+#SYSTEMNAME="" ++ :param tsInfo: A :class:`yum.transactioninfo.TransactionData` ++ instance that contains information about the transaction. ++ """ ++ super(EmailEmitter, self).updatesAvailable(tsInfo) ++ self.subject = "Yum: Updates Available on %s" % self.opts.system_name + -+# Scheduling Options (used by the default cron scripts, -+# /etc/cron.daily/yum-cleanup.cron and /etc/cron.daily/0yum-update.cron) -+# -+# Note that if you use a different cron configuration (for example, -+# removing the default scripts and adding an entry in /etc/cron.d), -+# these values will have no effect -- unless you read and act on them -+# in your new configuration. -+#-------------------------------------------------------------------------- ++ def updatesDownloaded(self): ++ """Append a message to the output list stating that updates ++ have been downloaded successfully, and set an appropriate ++ subject line. ++ """ ++ self.subject = "Yum: Updates downloaded on %s" % self.opts.system_name ++ super(EmailEmitter, self).updatesDownloaded() + -+# Wait for a random time up to the given number of minutes before -+# applying updates. With a value of 60, yum-cron will delay between 1 -+# and 60 minutes. A value of 0 will result in no delay, which is handy -+# if you want to ensure that updates happen at a known time, but could -+# be bad for update servers to be hit by all clients at exactly the -+# same time. -+RANDOMWAIT=60 ++ def updatesInstalled(self): ++ """Append a message to the output list stating that updates ++ have been installed successfully, and set an appropriate ++ subject line. ++ """ ++ self.subject = "Yum: Updates installed on %s" % self.opts.system_name ++ super(EmailEmitter, self).updatesInstalled() + -+# You may set DAYS_OF_WEEK to the numeric days of the week you want to -+# run, where 0 is Sunday and 6 is Saturday. The default is to run every -+# day. -+#DAYS_OF_WEEK="0123456" ++ def setupFailed(self, errmsg): ++ """Append a message to the output list stating that setup ++ failed, and then call sendMessages to emit the output, and set ++ an appropriate subject line. + -+# The cleanup task (which clears the package cache) can run on a subset -+# of the days above. (If the value chosen here doesn't appear in -+# DAYS_OF_WEEK, the cleanup task will never happen.) -+CLEANDAY="0" ++ :param errmsgs: a string that contains the error message ++ """ ++ self.subject = "Yum: Failed to perform setup on %s" % self.opts.system_name ++ super(EmailEmitter, self).setupFailed(errmsg) + -+# Init System Options (used by /etc/init.d/yum-cron) -+#-------------------------------------------------------------------------- ++ def lockFailed(self, errmsg): ++ """Append a message to the output list stating that the ++ program failed to acquire the yum lock, then call sendMessages ++ to emit the output, and set an appropriate subject line. + -+# If SERVICE_WAITS is set to "yes", and a transaction is in progress -+# when the yum-cron service is stopped, the init script will wait -+# up to SERVICE_WAIT_TIME seconds before killing the task. Without -+# this, system shutdown continues as normal, potentially breaking -+# in-progress transactions. -+# (Valid options: yes|no) -+SERVICE_WAITS=yes ++ :param errmsg: a string that contains the error message ++ """ ++ self.subject = "Yum: Failed to acquire the yum lock on %s" % self.opts.system_name ++ super(EmailEmitter, self).lockFailed(errmsg) + -+# 300 is the default. -+SERVICE_WAIT_TIME=300 ++ def checkFailed(self, errmsg): ++ """Append a message to the output stating that checking for ++ updates failed, then call sendMessages to emit the output, and ++ set an appropriate subject line. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.subject = "Yum: Failed to check for updates on %s" % self.opts.system_name ++ super(EmailEmitter, self).checkFailed(errmsg) ++ ++ def downloadFailed(self, errmsg): ++ """Append a message to the output list stating that checking ++ for group updates failed, then call sendMessages to emit the ++ output, and add an appropriate subject line. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.subject = "Yum: Failed to download updates on %s" % self.opts.system_name ++ super(EmailEmitter, self).downloadFailed(errmsg) ++ ++ def updatesFailed(self, errmsg): ++ """Append a message to the output list stating that installing ++ updates failed, then call sendMessages to emit the output, and ++ add an appropriate subject line. ++ ++ :param errmsgs: a string that contains the error message ++ """ ++ self.subject = "Yum: Failed to install updates on %s" % self.opts.system_name ++ super(EmailEmitter, self).updatesFailed(errmsg) ++ ++ def sendMessages(self): ++ """Combine the stored messages that have been stored into a ++ single email message, and send this message. ++ """ ++ # Build up the email to be sent ++ msg = MIMEText(''.join(self.output)) ++ msg['Subject'] = self.subject ++ msg['From'] = self.opts.email_from ++ msg['To'] = ",".join(self.opts.email_to) ++ ++ # Send the email ++ s = smtplib.SMTP() ++ s.connect(self.opts.email_host) ++ s.sendmail(self.opts.email_from, self.opts.email_to, msg.as_string()) ++ s.close() ++ ++ ++class StdIOEmitter(UpdateEmitter): ++ """Emitter class to send messages to syslog.""" ++ ++ def __init__(self, opts): ++ super(StdIOEmitter, self).__init__(opts) ++ ++ def sendMessages(self) : ++ """Combine the stored messages that have been stored into a ++ single email message, and send this message to standard output. ++ """ ++ print "".join(self.output) ++ ++ ++class YumCronConfig(BaseConfig): ++ """Class to parse configuration information from the config file, and ++ to store this information. ++ """ ++ system_name = Option(gethostname()) ++ output_width = IntOption(80) ++ random_sleep = IntOption(0) ++ emit_via = ListOption(['email','stdio']) ++ email_to = ListOption(["root"]) ++ email_from = Option("root") ++ email_host = Option("localhost") ++ email_port = IntOption(25) ++ update_messages = BoolOption(False) ++ apply_updates = BoolOption(False) ++ download_updates = BoolOption(False) ++ yum_config_file = Option("/etc/yum.conf") ++ group_list = ListOption([]) ++ group_package_types = ListOption(['mandatory', 'default']) ++ ++ ++class YumCronBase(yum.YumBase): ++ """Main class to check for and apply the updates.""" ++ ++ def __init__(self, config_file_name = None): ++ """Create a YumCronBase object, and perform initial setup. ++ ++ :param config_file_name: a String specifying the name of the ++ config file to use. ++ """ ++ yum.YumBase.__init__(self) ++ ++ # Read the config file ++ self.readConfigFile(config_file_name) ++ ++ ++ # Create the emitters, and add them to the list ++ self.emitters = [] ++ if 'email' in self.opts.emit_via: ++ self.emitters.append(EmailEmitter(self.opts)) ++ if 'stdio' in self.opts.emit_via: ++ self.emitters.append(StdIOEmitter(self.opts)) ++ ++ self.updateInfo = [] ++ self.updateInfoTime = None ++ ++ def readConfigFile(self, config_file_name = None): ++ """Reads the given config file, or if none is given, the ++ default config file. ++ ++ :param config_file_name: a String specifying the name of the ++ config file to read. ++ """ ++ # Create ConfigParser and UDConfig Objects ++ confparser = ConfigParser() ++ self.opts = YumCronConfig() ++ ++ #If no config file name is given, fall back to the default ++ if config_file_name == None: ++ config_file_name = default_config_file ++ ++ # Attempt to read the config file. confparser.read will return a ++ # list of the files that were read successfully, so check that it ++ # contains config_file ++ if config_file_name not in confparser.read(config_file_name): ++ print >> sys.stderr, "Error reading config file" ++ sys.exit(1) ++ ++ # Populate the values into the opts object ++ self.opts.populate(confparser, 'commands') ++ self.opts.populate(confparser, 'emitters') ++ self.opts.populate(confparser, 'email') ++ self.opts.populate(confparser, 'groups') ++ ++ #If the system name is not given, set it by getting the hostname ++ if self.opts.system_name == 'None' : ++ self.opts.system_name = gethostname() ++ ++ if 'None' in self.opts.group_list: ++ self.opts.group_list = [] ++ ++ ++ def randomSleep(self, duration): ++ """Sleep for a random amount of time up to *duration*. ++ ++ :param duration: the maximum amount of time to sleep, in ++ minutes. The actual time slept will be between 0 and ++ *duration* minutes ++ """ ++ if duration > 0: ++ sleep(random() * 60 * duration) ++ ++ def doSetup(self): ++ """Perform set up, including setting up directories and ++ parsing options. ++ ++ :return: boolean that indicates whether setup has completed ++ successfully ++ """ ++ try : ++ # Set the configuration file ++ self.preconf.fn = self.opts.yum_config_file ++ ++ # if we are not root do the special subdir thing ++ if os.geteuid() != 0: ++ self.setCacheDir() ++ ++ # Create the configuration ++ self.conf ++ ++ except Exception, e: ++ # If there are any exceptions, send a message about them, ++ # and return False ++ self.emitSetupFailed('%s' % e) ++ sys.exit(1) ++ ++ def acquireLock(self): ++ """ Wrapper method around doLock to emit errors correctly.""" ++ ++ try: ++ self.doLock() ++ except yum.Errors.LockError, e: ++ self.emitLockFailed("%s" % e) ++ sys.exit(1) ++ ++ def populateUpdateMetadata(self): ++ """Populate the metadata for the packages in the update.""" ++ ++ self.updateMetadata = UpdateMetadata() ++ repos = [] ++ ++ for (new, old) in self.up.getUpdatesTuples(): ++ pkg = self.getPackageObject(new) ++ if pkg.repoid not in repos: ++ repo = self.repos.getRepo(pkg.repoid) ++ repos.append(repo.id) ++ try: # grab the updateinfo.xml.gz from the repodata ++ md = repo.retrieveMD('updateinfo') ++ except Exception: # can't find any; silently move on ++ continue ++ md = gzip.open(md) ++ self.updateMetadata.add(md) ++ md.close() ++ ++ def refreshUpdates(self): ++ """Check whether updates are available. ++ ++ :return: Boolean indicating whether any updates are ++ available ++ """ ++ try: ++ updatesTuples = self.up.getUpdatesTuples() ++ # If there are no updates, return False ++ if not updatesTuples: ++ return False ++ ++ # figure out the updates ++ for (new, old) in updatesTuples: ++ updates_available = True ++ updating = self.getPackageObject(new) ++ updated = self.rpmdb.searchPkgTuple(old)[0] ++ ++ self.tsInfo.addUpdate(updating, updated) ++ ++ # and the obsoletes ++ if self.conf.obsoletes: ++ for (obs, inst) in self.up.getObsoletesTuples(): ++ obsoleting = self.getPackageObject(obs) ++ installed = self.rpmdb.searchPkgTuple(inst)[0] ++ ++ self.tsInfo.addObsoleting(obsoleting, installed) ++ self.tsInfo.addObsoleted(installed, obsoleting) ++ ++ except Exception, e: ++ self.emitCheckFailed("%s" %(e,)) ++ sys.exit(1) ++ ++ else: ++ return True ++ ++ def refreshGroupUpdates(self): ++ """Check for group updates, and add them to the ++ transaction. ++ ++ :return: Boolean indicating whether there are any updates to ++ the group available ++ """ ++ update_available = False ++ try: ++ for group_string in self.opts.group_list: ++ group_matched = False ++ for group in self.comps.return_groups(group_string): ++ group_matched = True ++ try: ++ txmbrs = self.selectGroup(group.groupid, ++ self.opts.group_package_types, ++ upgrade=True) ++ ++ # If updates are available from a previous ++ # group, or there are updates are available ++ # from this group, set update_available to True ++ update_available |= (txmbrs != []) ++ ++ except yum.Errors.GroupsError: ++ self.emitGroupError('Warning: Group %s does not exist.' % group_string) ++ continue ++ ++ if not group_matched: ++ self.emitGroupError('Warning: Group %s does not exist.' % group_string) ++ continue ++ ++ except Exception, e: ++ self.emitGroupFailed("%s" % e) ++ return False ++ ++ else: ++ return update_available ++ ++ def findDeps(self): ++ """Build the transaction to resolve the dependencies for the update.""" ++ ++ try: ++ (res, resmsg) = self.buildTransaction() ++ except yum.Errors.RepoError, e: ++ self.emitCheckFailed("%s" %(e,)) ++ sys.exit() ++ if res != 2: ++ self.emitCheckFailed("Failed to build transaction: %s" %(str.join("\n", resmsg),)) ++ sys.exit(1) ++ ++ def downloadUpdates(self, emit): ++ """Download the update. ++ ++ :param emit: Boolean indicating whether to emit messages ++ about the download ++ """ ++ # Emit a message that that updates will be downloaded ++ if emit : ++ self.emitDownloading() ++ dlpkgs = map(lambda x: x.po, filter(lambda txmbr: ++ txmbr.ts_state in ("i", "u"), ++ self.tsInfo.getMembers())) ++ try: ++ # Download the updates ++ self.conf.download_only = not self.opts.apply_updates ++ self.downloadPkgs(dlpkgs) ++ except Exception, e: ++ self.emitDownloadFailed("%s" % e) ++ sys.exit(1) ++ except SystemExit, e: ++ if e.code == 0: ++ # Emit a message that the packages have been downloaded ++ self.emitDownloaded() ++ self.emitMessages() ++ raise ++ ++ def installUpdates(self, emit): ++ """Apply the available updates. ++ ++ :param emit: Boolean indicating whether to emit messages about ++ the installation ++ """ ++ # Emit a message that ++ if emit : ++ self.emitInstalling() ++ ++ dlpkgs = map(lambda x: x.po, filter(lambda txmbr: ++ txmbr.ts_state in ("i", "u"), ++ self.tsInfo.getMembers())) ++ ++ for po in dlpkgs: ++ result, err = self.sigCheckPkg(po) ++ if result == 0: ++ continue ++ elif result == 1: ++ try: ++ self.getKeyForPackage(po) ++ except yum.Errors.YumBaseError, errmsg: ++ self.emitUpdateFailed([str(errmsg)]) ++ return False ++ ++ del self.ts ++ self.initActionTs() # make a new, blank ts to populate ++ self.populateTs(keepold=0) ++ self.ts.check() #required for ordering ++ self.ts.order() # order ++ cb = callback.RPMInstallCallback(output = 0) ++ cb.filelog = True ++ ++ cb.tsInfo = self.tsInfo ++ try: ++ self.runTransaction(cb=cb) ++ except yum.Errors.YumBaseError, err: ++ ++ self.emitUpdateFailed([str(err)]) ++ sys.exit(1) ++ ++ self.emitInstalled() ++ self.emitMessages() ++ ++ def updatesCheck(self): ++ """Check to see whether updates are available for any ++ installed packages. If updates are available, install them, ++ download them, or just emit a message, depending on what ++ options are selected in the configuration file. ++ """ ++ # Sleep a random time ++ self.randomSleep(self.opts.random_sleep) ++ ++ # Perform the initial setup ++ self.doSetup() ++ ++ # Acquire the yum lock ++ self.acquireLock() ++ ++ # Update the metadata ++ self.populateUpdateMetadata() ++ ++ # Exit if we don't need to send messages, or there are no ++ # updates ++ if not (self.opts.update_messages and (self.refreshUpdates() ++ or self.refreshGroupUpdates())): ++ sys.exit(0) ++ ++ # Build the transaction to find the additional dependencies ++ self.findDeps() ++ ++ # download if set up to do so, else tell about the updates and exit ++ if not self.opts.download_updates: ++ self.emitAvailable() ++ self.emitMessages() ++ self.releaseLocks() ++ sys.exit(0) ++ ++ self.downloadUpdates(not self.opts.apply_updates) ++ ++ # now apply if we're set up to do so; else just tell that things are ++ # available ++ if not self.opts.apply_updates: ++ self.releaseLocks() ++ sys.exit(0) ++ ++ self.installUpdates(True) ++ ++ self.releaseLocks() ++ sys.exit(0) ++ ++ def releaseLocks(self): ++ """Close the rpm database, and release the yum lock.""" ++ self.closeRpmDB() ++ self.doUnlock() ++ ++ def emitAvailable(self): ++ """Emit a notice stating whether updates are available.""" ++ map(lambda x: x.updatesAvailable(self.tsInfo), self.emitters) ++ ++ def emitDownloading(self): ++ """Emit a notice stating that updates are downloading.""" ++ map(lambda x: x.updatesDownloading(self.tsInfo), self.emitters) ++ ++ def emitDownloaded(self): ++ """Emit a notice stating that updates have downloaded.""" ++ map(lambda x: x.updatesDownloaded(), self.emitters) ++ ++ def emitInstalling(self): ++ """Emit a notice stating that automatic updates are about to ++ be applied. ++ """ ++ map(lambda x: x.updatesInstalling(self.tsInfo), self.emitters) ++ ++ def emitInstalled(self): ++ """Emit a notice stating that automatic updates have been applied.""" ++ map(lambda x: x.updatesInstalled(), self.emitters) ++ ++ def emitSetupFailed(self, error): ++ """Emit a notice stating that checking for updates failed.""" ++ map(lambda x: x.setupFailed(error), self.emitters) ++ ++ def emitLockFailed(self, errmsg): ++ """Emit a notice that we failed to acquire the yum lock.""" ++ map(lambda x: x.lockFailed(errmsg), self.emitters) ++ ++ def emitCheckFailed(self, error): ++ """Emit a notice stating that checking for updates failed.""" ++ map(lambda x: x.checkFailed(error), self.emitters) ++ ++ def emitGroupError(self, error): ++ """Emit a notice stating that there was an error checking for ++ group updates. ++ """ ++ map(lambda x: x.groupError(error), self.emitters) ++ ++ def emitGroupFailed(self, error): ++ """Emit a notice stating that checking for group updates failed.""" ++ map(lambda x: x.groupFailed(error), self.emitters) ++ ++ def emitDownloadFailed(self, error): ++ """Emit a notice stating that downloading the updates failed.""" ++ map(lambda x: x.downloadFailed(error), self.emitters) ++ ++ def emitUpdateFailed(self, errmsgs): ++ """Emit a notice stating that automatic updates failed.""" ++ map(lambda x: x.updatesFailed(errmsgs), self.emitters) ++ ++ def emitMessages(self): ++ """Emit the messages from the emitters.""" ++ map(lambda x: x.sendMessages(), self.emitters) ++ ++ ++def main(): ++ """Configure and run the update check.""" ++ # If a file name was passed in, use it as the config file name. ++ base = None ++ if len(sys.argv) > 1: ++ base = YumCronBase(sys.argv[1]) ++ else: ++ base = YumCronBase() ++ ++ #Run the update check ++ base.updatesCheck() ++ ++if __name__ == "__main__": ++ main() diff --git a/yum-cron/yum-cron.sysvinit b/yum-cron/yum-cron.sysvinit new file mode 100755 -index 0000000..ee531c6 +index 0000000..7b44d5e --- /dev/null +++ b/yum-cron/yum-cron.sysvinit -@@ -0,0 +1,108 @@ +@@ -0,0 +1,105 @@ +#!/bin/bash +# +# yum-cron Enable or disable scheduled yum system updates. @@ -150434,21 +151350,18 @@ index 0000000..ee531c6 +# description: This controls whether yum-cron runs. If this service is \ +# off, the yum-cron scripts in /etc/cron.daily exit \ +# immediately; otherwise, they download and/or apply package \ -+# updates as configured in /etc/sysconfig/yum-cron. ++# updates as configured in /etc/yum/yum-cron.conf. +# processname: yum-cron -+# config: /etc/yum/yum-daily.yum +# + +# source function library +. /etc/rc.d/init.d/functions -+ -+test -f /etc/sysconfig/yum-cron && . /etc/sysconfig/yum-cron -+ +lockfile=/var/lock/subsys/yum-cron + +# This is generated by /usr/sbin/yum-cron and will exist when that script +# is running and not otherwise. +pidfile=/var/lock/yum-cron.pid ++SERVICE_WAITS=yes + +RETVAL=0 + @@ -150535,10 +151448,10 @@ index 0000000..ee531c6 +exit $RETVAL diff --git a/yum-cron/yum-update.cron.sh b/yum-cron/yum-update.cron.sh new file mode 100755 -index 0000000..b9edddf +index 0000000..06dee5f --- /dev/null +++ b/yum-cron/yum-update.cron.sh -@@ -0,0 +1,35 @@ +@@ -0,0 +1,11 @@ +#!/bin/bash + +# Only run if this flag is set. The flag is created by the yum-cron init @@ -150548,32 +151461,8 @@ index 0000000..b9edddf + exit 0 +fi + -+# Read configuration settings from the sysconfig directory. -+if [[ -f /etc/sysconfig/yum-cron ]]; then -+ source /etc/sysconfig/yum-cron -+fi -+ -+# Only run on certain days of the week, based on the -+# settings in the above-mentioned sysconfig file. -+dow=`date +%w` -+DAYS_OF_WEEK=${DAYS_OF_WEEK:-0123456} -+if [[ "${DAYS_OF_WEEK/$dow/}" == "${DAYS_OF_WEEK}" ]]; then -+ exit 0 -+fi -+ -+# Wait a random number of minutes, again based on -+# the setting in the sysconfig file. -+[[ $RANDOMWAIT -gt 0 ]] && sleep $(( $RANDOM % ($RANDOMWAIT * 60) + 1 )) -+ -+# Double-check to make sure that we're still supposed to be -+# active after the random wait. -+if [[ ! -f /var/lock/subsys/yum-cron ]]; then -+ exit 0 -+fi -+ -+ +# Action! -+exec /usr/sbin/yum-cron update ++exec /usr/sbin/yum-cron diff --git a/yum-updatesd.py b/yum-updatesd.py old mode 100644 new mode 100755 @@ -151129,7 +152018,7 @@ index 1ce4720..25e3022 gobject.threads_init() dbus.glib.threads_init() diff --git a/yum.spec b/yum.spec -index abd203f..4ad6804 100644 +index abd203f..a309594 100644 --- a/yum.spec +++ b/yum.spec @@ -1,24 +1,53 @@ @@ -151354,7 +152243,7 @@ index abd203f..4ad6804 100644 %dir /var/cache/yum %dir /var/lib/yum %ghost /var/lib/yum/uuid -@@ -188,20 +273,24 @@ exit 0 +@@ -188,20 +273,21 @@ exit 0 %ghost /var/lib/yum/yumdb %{_mandir}/man*/yum.* %{_mandir}/man*/yum-shell* @@ -151370,23 +152259,21 @@ index abd203f..4ad6804 100644 -%{_sysconfdir}/cron.daily/0yum.cron -%config(noreplace) %{_sysconfdir}/yum/yum-daily.yum -%config(noreplace) %{_sysconfdir}/yum/yum-weekly.yum -+%config(noreplace) %{_sysconfdir}/cron.daily/0yum-update.cron -+%config(noreplace) %{_sysconfdir}/cron.daily/yum-cleanup.cron ++%{_sysconfdir}/cron.daily/0yum-update.cron ++%config(noreplace) %{_sysconfdir}/yum/yum-cron.conf %{_sysconfdir}/rc.d/init.d/yum-cron +-%config(noreplace) %{_sysconfdir}/sysconfig/yum-cron +- +- +- +%{_sbindir}/yum-cron - %config(noreplace) %{_sysconfdir}/sysconfig/yum-cron -+%dir %{_datadir}/yum-cron -+%{_datadir}/yum-cron/update.yum -+%{_datadir}/yum-cron/cleanup.yum ++%{_mandir}/man*/yum-cron.* -- -- -- +%if %{yum_updatesd} %files updatesd %defattr(-, root, root) %config(noreplace) %{_sysconfdir}/yum/yum-updatesd.conf -@@ -210,8 +299,12 @@ exit 0 +@@ -210,8 +296,12 @@ exit 0 %{_datadir}/yum-cli/yumupd.py* %{_sbindir}/yum-updatesd %{_mandir}/man*/yum-updatesd* @@ -159040,10 +159927,40 @@ index bfc49b7..9ddcae6 100644 b = parsever(b) diff --git a/yum/repoMDObject.py b/yum/repoMDObject.py -index 31b1080..eb84123 100755 +index 31b1080..97256c6 100755 --- a/yum/repoMDObject.py +++ b/yum/repoMDObject.py -@@ -226,12 +226,11 @@ class RepoMD: +@@ -15,6 +15,7 @@ + # Copyright 2006 Duke University + + from yum.misc import cElementTree_iterparse as iterparse ++from yum.misc import _available_compression, stat_f + from Errors import RepoMDError + + import sys +@@ -133,6 +134,7 @@ class RepoMD: + else: + # srcfile is a file object + infile = srcfile ++ srcfile = None + + # We trust any of these to mean the repomd.xml is valid. + infile = AutoFileChecksums(infile, ['sha256', 'sha512'], +@@ -145,6 +147,13 @@ class RepoMD: + + if elem_name == "data": + thisdata = RepoData(elem=elem) ++ old = self.repoData.get(thisdata.type) ++ if (old and old.size and old.size < thisdata.size ++ and old.location[1].rsplit('.', 1)[1] in _available_compression ++ and srcfile and stat_f(srcfile.rsplit('/', 1)[0] +'/'+ ++ thisdata.location[1].rsplit('/', 1)[1]) is None): ++ # previous is smaller, can unzip it, and next is not cached ++ thisdata = old + self.repoData[thisdata.type] = thisdata + try: + nts = int(thisdata.timestamp) +@@ -226,12 +235,11 @@ class RepoMD: tag = """ %s\n""" % (to_xml(item)) tags += tag for (cpeid, item) in self.tags['distro']: diff --git a/yum.spec b/yum.spec index 4a9fc05..51537e8 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 46%{?dist} +Release: 47%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -299,14 +299,11 @@ exit 0 %files cron %defattr(-,root,root) %doc COPYING -%config(noreplace) %{_sysconfdir}/cron.daily/0yum-update.cron -%config(noreplace) %{_sysconfdir}/cron.daily/yum-cleanup.cron +%{_sysconfdir}/cron.daily/0yum-update.cron +%config(noreplace) %{_sysconfdir}/yum/yum-cron.conf %{_sysconfdir}/rc.d/init.d/yum-cron %{_sbindir}/yum-cron -%config(noreplace) %{_sysconfdir}/sysconfig/yum-cron -%dir %{_datadir}/yum-cron -%{_datadir}/yum-cron/update.yum -%{_datadir}/yum-cron/cleanup.yum +%{_mandir}/man*/yum-cron.* %if %{yum_updatesd} %files updatesd @@ -320,6 +317,9 @@ exit 0 %endif %changelog +* Thu Oct 25 2012 Zdenek Pavlas - 3.4.3-47 +- replaced yum-cron.sh with the new yum-cron.py (very alpha) + * Thu Oct 25 2012 Nils Philippsen - 3.4.3-46 - bump release to ensure upgrade path and satisfy PackageKit deps From 494c09858778c3ef65638c5ea1d6f472d8ab1e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Pavlas?= Date: Mon, 19 Nov 2012 18:03:18 +0100 Subject: [PATCH 009/174] update to latest HEAD. --- yum-HEAD.patch | 362 ++++++++++++++++++++++++++++++++++++++++--------- yum.spec | 13 +- 2 files changed, 306 insertions(+), 69 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index c77f5ba..eefa7b1 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -3162,10 +3162,10 @@ index 63c5ec0..0000000 -exit $RETVAL diff --git a/etc/yum-cron.conf b/etc/yum-cron.conf new file mode 100644 -index 0000000..269c6b7 +index 0000000..c227e40 --- /dev/null +++ b/etc/yum-cron.conf -@@ -0,0 +1,55 @@ +@@ -0,0 +1,59 @@ +[commands] +# Whether a message should emitted when updates are available. +update_messages = yes @@ -3221,6 +3221,10 @@ index 0000000..269c6b7 + +# The types of group packages to install +group_package_types = mandatory, default ++ ++[base] ++# override yum options of the same name ++# skip_broken = True diff --git a/etc/yum-cron.sysconf b/etc/yum-cron.sysconf deleted file mode 100644 index 930341c..0000000 @@ -149193,6 +149197,53 @@ index 7af3f16..ea47b03 100644 def testUpdate_so_req_diff_arch(self): rpo1 = FakePackage('foozoomer') +diff --git a/test/misc-tests.py b/test/misc-tests.py +index d34c161..7d7d06f 100644 +--- a/test/misc-tests.py ++++ b/test/misc-tests.py +@@ -114,6 +114,42 @@ class MiscTests(DepsolveTests): + res, msg = solver.buildTransaction() + return self.res[res], msg + ++ def testXML(self): ++ import yum.misc ++ for args in ( ++ ++# valid utf8 and unicode ++('\xc4\x9b\xc5\xa1\xc4\x8d', '\xc4\x9b\xc5\xa1\xc4\x8d'), ++(u'\u011b\u0161\u010d', '\xc4\x9b\xc5\xa1\xc4\x8d'), ++ ++# invalid utf8 ++('\xc3\x28', '\xc3\x83\x28'), ++('\xa0\xa1', '\xc2\xa0\xc2\xa1'), ++('Skytt\xe4', 'Skytt\xc3\xa4'), ++ ++# entity expansion ++('&<>', '&<>'), ++ ++# removal of invalid bytes ++('\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f', '\t\n\r'), ++ ++# attr flag ++('&"\'', '&"\''), ++('&"\'', True, '&"''), ++ ++# weirdness ++(None, ''), ++('abc ', 'abc'), ++ ++ ): ++ # last item is the expected result ++ args, expected = args[:-1], args[-1] ++ actual = yum.misc.to_xml(*args) ++ ++ # actual vs expected ++ self.assertEqual(type(actual), type(expected)) ++ self.assertEqual(actual, expected) ++ + def setup_logging(): + logging.basicConfig() + plainformatter = logging.Formatter("%(message)s") diff --git a/test/revdepupdatetests.py b/test/revdepupdatetests.py new file mode 100644 index 0000000..a98341d @@ -149270,7 +149321,7 @@ index 0000000..a98341d + self.assertResult( (p.installed_1, p.update_4) ) + diff --git a/test/simpleobsoletestests.py b/test/simpleobsoletestests.py -index 97a9923..55e6f14 100644 +index 97a9923..e9b2c09 100644 --- a/test/simpleobsoletestests.py +++ b/test/simpleobsoletestests.py @@ -244,6 +244,42 @@ class SimpleObsoletesTests(OperationsTests): @@ -149316,7 +149367,7 @@ index 97a9923..55e6f14 100644 def _MultiObsHelper(self): ret = {'zsh' : FakePackage('zsh', '1', '1', '0', 'noarch'), 'ksh' : FakePackage('ksh', '1', '1', '0', 'noarch'), -@@ -588,6 +624,28 @@ class SimpleObsoletesTests(OperationsTests): +@@ -588,6 +624,89 @@ class SimpleObsoletesTests(OperationsTests): # self.assert_(res=='err', msg) self.assertResult([]) @@ -149340,6 +149391,67 @@ index 97a9923..55e6f14 100644 + # In theory don't need to upgrade oc1 => oc2 + self.assertResult((oc2, osl2, osll2)) + ++ def testCircObs1(self): ++ c1 = FakePackage('test-ccc', '0.1', '1') ++ c2 = FakePackage('test-ccc', '0.2', '2') ++ c2.addObsoletes('test-ddd', None, (None, None, None)) ++ ++ d1 = FakePackage('test-ddd', '0.1', '1') ++ d2 = FakePackage('test-ddd', '0.2', '2') ++ d2.addObsoletes('test-ccc', None, (None, None, None)) ++ ++ res, msg = self.runOperation(['upgrade'], ++ [c1, d1], ++ [c1, d1, c2, d2]) ++ ++ self.assertResult((c2, d2)) ++ ++ def testCircObs2(self): ++ c1 = FakePackage('test-ccc', '0.1', '1') ++ c2 = FakePackage('test-ccc', '0.2', '2') ++ c2.addObsoletes('test-ddd', None, (None, None, None)) ++ ++ d1 = FakePackage('test-ddd', '0.1', '1') ++ d2 = FakePackage('test-ddd', '0.2', '2') ++ d2.addObsoletes('test-ccc', None, (None, None, None)) ++ ++ res, msg = self.runOperation(['upgrade', 'test-ccc', 'test-ddd'], ++ [c1, d1], ++ [c1, d1, c2, d2]) ++ ++ self.assertResult((c2, d2)) ++ ++ def testCircObs3(self): ++ c1 = FakePackage('test-ccc', '0.1', '1') ++ c2 = FakePackage('test-ccc', '0.2', '2') ++ c2.addObsoletes('test-ddd', None, (None, None, None)) ++ ++ d1 = FakePackage('test-ddd', '0.1', '1') ++ d2 = FakePackage('test-ddd', '0.2', '2') ++ d2.addObsoletes('test-ccc', None, (None, None, None)) ++ ++ res, msg = self.runOperation(['upgrade', 'test-ccc'], ++ [c1, d1], ++ [c1, d1, c2, d2]) ++ ++ # Just c2 is fine too, although less likely what the user wants ++ self.assertResult((c2,d2)) ++ ++ def testCircObs4(self): ++ c1 = FakePackage('test-ccc', '0.1', '1') ++ c2 = FakePackage('test-ccc', '0.2', '2') ++ c2.addObsoletes('test-ddd', None, (None, None, None)) ++ ++ d1 = FakePackage('test-ddd', '0.1', '1') ++ d2 = FakePackage('test-ddd', '0.2', '2') ++ d2.addObsoletes('test-ccc', None, (None, None, None)) ++ ++ res, msg = self.runOperation(['upgrade', 'test-ddd'], ++ [c1, d1], ++ [c1, d1, c2, d2]) ++ ++ # Just d2 is fine too, although less likely what the user wants ++ self.assertResult((c2,d2)) + + class GitMetapackageObsoletesTests(OperationsTests): @@ -150218,10 +150330,10 @@ index 0000000..28e1964 +- Check if we're running as root; exit nicely. diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py new file mode 100755 -index 0000000..44fc785 +index 0000000..8f6286b --- /dev/null +++ b/yum-cron/yum-cron.py -@@ -0,0 +1,1113 @@ +@@ -0,0 +1,1118 @@ +#!/usr/bin/python -tt +import os +import sys @@ -150931,6 +151043,7 @@ index 0000000..44fc785 + yum_config_file = Option("/etc/yum.conf") + group_list = ListOption([]) + group_package_types = ListOption(['mandatory', 'default']) ++ skip_broken = BoolOption() + + +class YumCronBase(yum.YumBase): @@ -151028,6 +151141,10 @@ index 0000000..44fc785 + self.emitSetupFailed('%s' % e) + sys.exit(1) + ++ # override yum options ++ if self.opts.skip_broken is not None: ++ self.conf.skip_broken = self.opts.skip_broken ++ + def acquireLock(self): + """ Wrapper method around doLock to emit errors correctly.""" + @@ -157370,7 +157487,7 @@ index d09511f..74be397 100644 if name not in cfgOptions and option.default == value: diff --git a/yum/depsolve.py b/yum/depsolve.py -index 6d744c0..5e95662 100644 +index 6d744c0..a16f1f5 100644 --- a/yum/depsolve.py +++ b/yum/depsolve.py @@ -31,13 +31,15 @@ from transactioninfo import TransactionMember @@ -157659,7 +157776,7 @@ index 6d744c0..5e95662 100644 if not len(self.tsInfo): return (0, [_('Success - empty transaction')]) -@@ -778,6 +900,25 @@ class Depsolve(object): +@@ -778,6 +900,28 @@ class Depsolve(object): if checkdep: break # The next conflict might be the same pkg @@ -157674,6 +157791,9 @@ index 6d744c0..5e95662 100644 + if otxmbr.output_state not in TS_INSTALL_STATES: + continue + if otxmbr.po.obsoletedBy([txmbr.po]): ++ if txmbr.po.obsoletedBy([otxmbr.po]): ++ # Have to deal with loops! ++ continue + self.tsInfo.remove(otxmbr.pkgtup) + # We need to remove an obsoleted entry that + # was maybe used to resolve something ... ? @@ -157685,7 +157805,7 @@ index 6d744c0..5e95662 100644 if CheckDeps: if self.dsCallback: self.dsCallback.restartLoop() self.verbose_logger.log(logginglevels.DEBUG_1, _('Restarting Loop')) -@@ -920,9 +1061,12 @@ class Depsolve(object): +@@ -920,9 +1064,12 @@ class Depsolve(object): # if this is an update, we should check what the old # requires were to make things faster @@ -157700,7 +157820,7 @@ index 6d744c0..5e95662 100644 oldreqs = set(oldreqs) ret = [] -@@ -1150,6 +1294,11 @@ class Depsolve(object): +@@ -1150,6 +1297,11 @@ class Depsolve(object): return ret def isPackageInstalled(self, pkgname): @@ -157712,7 +157832,7 @@ index 6d744c0..5e95662 100644 lst = self.tsInfo.matchNaevr(name = pkgname) for txmbr in lst: if txmbr.output_state in TS_INSTALL_STATES: -@@ -1166,7 +1315,7 @@ class Depsolve(object): +@@ -1166,7 +1318,7 @@ class Depsolve(object): return True _isPackageInstalled = isPackageInstalled @@ -157721,7 +157841,7 @@ index 6d744c0..5e95662 100644 """take the list of pkgs and score them based on the requesting package return a dictionary of po=score""" self.verbose_logger.log(logginglevels.DEBUG_4, -@@ -1210,6 +1359,24 @@ class Depsolve(object): +@@ -1210,6 +1362,24 @@ class Depsolve(object): return None return x @@ -157746,7 +157866,7 @@ index 6d744c0..5e95662 100644 # Actual start of _compare_providers(). # Do a NameArch filtering, based on repo. __cmp__ -@@ -1332,6 +1499,26 @@ class Depsolve(object): +@@ -1332,6 +1502,26 @@ class Depsolve(object): _('common prefix of %s between %s and %s' % (cpl, po, reqpo))) pkgresults[po] += cpl*2 @@ -157773,7 +157893,7 @@ index 6d744c0..5e95662 100644 # If we have more than one "best", see what would happen if we picked # each package ... ie. what things do they require that _aren't_ already -@@ -1393,42 +1580,52 @@ class Depsolve(object): +@@ -1393,42 +1583,52 @@ class Depsolve(object): class DepCheck(object): @@ -158800,7 +158920,7 @@ index aaa4f25..61aa586 100755 continue diff --git a/yum/misc.py b/yum/misc.py -index 2f6ddfe..a0bac7b 100644 +index 2f6ddfe..6c3c349 100644 --- a/yum/misc.py +++ b/yum/misc.py @@ -8,6 +8,7 @@ import os @@ -158878,7 +158998,103 @@ index 2f6ddfe..a0bac7b 100644 if not data: break -@@ -940,14 +969,16 @@ def unlink_f(filename): +@@ -868,67 +897,39 @@ def seq_max_split(seq, max_entries): + ret.append(seq[beg:]) + return ret + +-def _ugly_utf8_string_hack(item): +- """hands back a unicoded string""" +- # this is backward compat for handling non-utf8 filenames +- # and content inside packages. :( +- # content that xml can cope with but isn't really kosher +- +- # if we're anything obvious - do them first +- if item is None: +- return '' +- elif isinstance(item, unicode): +- return item +- +- # this handles any bogon formats we see +- du = False +- try: +- x = unicode(item, 'ascii') +- du = True +- except UnicodeError: +- encodings = ['utf-8', 'iso-8859-1', 'iso-8859-15', 'iso-8859-2'] +- for enc in encodings: +- try: +- x = unicode(item, enc) +- except UnicodeError: +- pass +- +- else: +- if x.encode(enc) == item: +- if enc != 'utf-8': +- print '\n%s encoding on %s\n' % (enc, item) +- return x.encode('utf-8') +- +- +- # Kill bytes (or libxml will die) not in the small byte portion of: +- # http://www.w3.org/TR/REC-xml/#NT-Char +- # we allow high bytes, if it passed the utf8 check above. Eg. +- # good chars = #x9 | #xA | #xD | [#x20-...] +- newitem = '' +- bad_small_bytes = range(0, 8) + [11, 12] + range(14, 32) +- for char in item: +- if ord(char) in bad_small_bytes: +- pass # Just ignore these bytes... +- elif not du and ord(char) > 127: +- newitem = newitem + '?' # byte by byte equiv of escape +- else: +- newitem = newitem + char +- return newitem ++_deletechars = ''.join(chr(i) for i in range(32) if i not in (9, 10, 13)) + +-__cached_saxutils = None + def to_xml(item, attrib=False): +- global __cached_saxutils +- if __cached_saxutils is None: +- import xml.sax.saxutils +- __cached_saxutils = xml.sax.saxutils ++ """ Returns xml-friendly utf-8 encoded string. ++ Accepts utf-8, iso-8859-1, or unicode. ++ """ ++ if type(item) is str: ++ # check if valid utf8 ++ try: unicode(item, 'utf-8') ++ except UnicodeDecodeError: ++ # assume iso-8859-1 ++ item = unicode(item, 'iso-8859-1').encode('utf-8') ++ elif type(item) is unicode: ++ item = item.encode('utf-8') ++ elif item is None: ++ return '' ++ else: ++ raise ValueError, 'String expected, got %s' % repr(item) + +- item = _ugly_utf8_string_hack(item) +- item = to_utf8(item) ++ # compat cruft... + item = item.rstrip() ++ ++ # kill ivalid low bytes ++ item = item.translate(None, _deletechars) ++ ++ # quote reserved XML characters ++ item = item.replace('&', '&') ++ item = item.replace('<', '<') ++ item = item.replace('>', '>') + if attrib: +- item = __cached_saxutils.escape(item, entities={'"':"""}) +- else: +- item = __cached_saxutils.escape(item) ++ item = item.replace('"', '"') ++ item = item.replace("'", ''') ++ + return item + + def unlink_f(filename): +@@ -940,14 +941,16 @@ def unlink_f(filename): if e.errno != errno.ENOENT: raise @@ -158899,7 +159115,7 @@ index 2f6ddfe..a0bac7b 100644 def _getloginuid(): """ Get the audit-uid/login-uid, if available. None is returned if there -@@ -992,9 +1023,17 @@ def setup_locale(override_codecs=True, override_time=False): +@@ -992,9 +995,17 @@ def setup_locale(override_codecs=True, override_time=False): locale.setlocale(locale.LC_ALL, 'C') if override_codecs: @@ -158920,7 +159136,7 @@ index 2f6ddfe..a0bac7b 100644 def get_my_lang_code(): -@@ -1105,17 +1144,28 @@ def decompress(filename, dest=None, fn_only=False, check_timestamps=False): +@@ -1105,17 +1116,28 @@ def decompress(filename, dest=None, fn_only=False, check_timestamps=False): out = filename.replace('.xz', '') else: @@ -158957,7 +159173,7 @@ index 2f6ddfe..a0bac7b 100644 return out -@@ -1123,11 +1173,7 @@ def repo_gen_decompress(filename, generated_name, cached=False): +@@ -1123,11 +1145,7 @@ def repo_gen_decompress(filename, generated_name, cached=False): """ This is a wrapper around decompress, where we work out a cached generated name, and use check_timestamps. filename _must_ be from a repo. and generated_name is the type of the file. """ @@ -159023,7 +159239,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..7a2624a 100644 +index 5ef9951..1ce45f4 100644 --- a/yum/packages.py +++ b/yum/packages.py @@ -106,14 +106,16 @@ def buildPkgRefDict(pkgs, casematch=True): @@ -159341,6 +159557,15 @@ index 5ef9951..7a2624a 100644 def _is_pre_req(self, flag): """check the flags for a requirement, return 1 or 0 whether or not requires +@@ -1946,7 +2027,7 @@ class YumInstalledPackage(YumHeaderPackage): + my_csum = digest_type + ':' + my_csum + my_st_size = fp.read_size + +- if pf.verify_digest and my_csum != csum: ++ if pf.verify_digest and my_csum != csum and my_csum: + prob = _PkgVerifyProb('checksum', + 'checksum does not match', ftypes) + prob.database_value = csum diff --git a/yum/parser.py b/yum/parser.py index fccf528..f443ce7 100644 --- a/yum/parser.py @@ -160088,7 +160313,7 @@ index 3793bad..de5da1e 100644 sack = repo.getPackageSack() try: diff --git a/yum/rpmsack.py b/yum/rpmsack.py -index e289a7a..302f613 100644 +index e289a7a..4e26d51 100644 --- a/yum/rpmsack.py +++ b/yum/rpmsack.py @@ -48,6 +48,17 @@ def _open_no_umask(*args): @@ -160170,7 +160395,7 @@ index e289a7a..302f613 100644 % hdr): return True - if repat.match("%(name)s-%(epoch)s:%(version)s-%(release)s.%(arch)s" -+ if repat("%(name)s-%(epoch)s:%(version)s-%(release)s.%(arch)s" ++ if repat(("%(name)s-" + epoch + ":%(version)s-%(release)s.%(arch)s") % hdr): return True return False @@ -160646,7 +160871,7 @@ index 2cb1acb..0586c1c 100644 for pkg in un['pkglist']: for filedata in pkg['packages']: diff --git a/yum/yumRepo.py b/yum/yumRepo.py -index e5e9ece..e362c43 100644 +index e5e9ece..4f5f7a6 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -20,10 +20,12 @@ import time @@ -160699,7 +160924,7 @@ index e5e9ece..e362c43 100644 + continue + + if self._check_db_version(repo, mydbtype): -+ if not self._check_uncompressed_db(repo, mydbtype): ++ if not self._check_uncompressed_db_gen(repo, mydbtype): + repo._retrieveMD(mydbtype, async=True, failfunc=None) + def populate(self, repo, mdtype='metadata', callback=None, cacheonly=0): @@ -160820,7 +161045,7 @@ index e5e9ece..e362c43 100644 def __cmp__(self, other): """ Sort yum repos. by cost, and then by alphanumeric on their id. """ -@@ -311,6 +366,35 @@ class YumRepository(Repository, config.RepoConf): +@@ -311,6 +366,37 @@ class YumRepository(Repository, config.RepoConf): return self._sack sack = property(_getSack) @@ -160839,8 +161064,10 @@ index e5e9ece..e362c43 100644 + val = ini['metalink'] + elif 'mirrorlist' in ini: + val = ini['mirrorlist'] -+ else: ++ elif 'baseurl' in ini: + val = ini['baseurl'] ++ else: ++ val = '' + ret = self.id + if '$releasever' in val: + ret += '/' @@ -160856,7 +161083,7 @@ index e5e9ece..e362c43 100644 def close(self): if self._sack is not None: self.sack.close() -@@ -350,6 +434,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -350,6 +436,10 @@ class YumRepository(Repository, config.RepoConf): return thisdata.location def __str__(self): @@ -160867,7 +161094,7 @@ index e5e9ece..e362c43 100644 return self.id def _checksum(self, sumtype, file, CHUNK=2**16, checksum_can_fail=False, -@@ -378,7 +466,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -378,7 +468,7 @@ class YumRepository(Repository, config.RepoConf): 'basecachedir', 'http_headers', 'metadata_cookie', 'metadata_cookie_fn', 'quick_enable_disable', 'repoMDFile', 'timestamp_check', 'urls', 'mirrorurls', @@ -160876,7 +161103,7 @@ index e5e9ece..e362c43 100644 for attr in dir(self): if attr.startswith('_'): continue -@@ -422,7 +510,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -422,7 +512,7 @@ class YumRepository(Repository, config.RepoConf): on then raise a repo error""" if len(self._urls) < 1 and not self.mediaid: raise Errors.RepoError, \ @@ -160885,7 +161112,7 @@ index e5e9ece..e362c43 100644 def doProxyDict(self): if self._proxy_dict: -@@ -431,25 +519,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -431,25 +521,18 @@ class YumRepository(Repository, config.RepoConf): self._proxy_dict = {} # zap it proxy_string = None empty = (None, '_none_', '') @@ -160919,7 +161146,7 @@ index e5e9ece..e362c43 100644 if proxy_string is not None: self._proxy_dict['http'] = proxy_string -@@ -483,13 +564,30 @@ class YumRepository(Repository, config.RepoConf): +@@ -483,13 +566,30 @@ class YumRepository(Repository, config.RepoConf): ugopts = self._default_grabopts() self._grabfunc = URLGrabber(progress_obj=self.callback, @@ -160951,7 +161178,7 @@ index e5e9ece..e362c43 100644 failure_callback=self.mirror_failure_obj) def _default_grabopts(self, cache=True): -@@ -499,6 +597,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -499,6 +599,7 @@ class YumRepository(Repository, config.RepoConf): 'throttle': self.throttle, 'proxies': self.proxy_dict, 'timeout': self.timeout, @@ -160959,7 +161186,7 @@ index e5e9ece..e362c43 100644 'http_headers': tuple(self.__headersListFromDict(cache=cache)), 'ssl_verify_peer': self.sslverify, 'ssl_verify_host': self.sslverify, -@@ -561,7 +660,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -561,7 +662,7 @@ class YumRepository(Repository, config.RepoConf): cookie = self.cachedir + '/' + self.metadata_cookie_fn self.setAttribute('_dir_setup_metadata_cookie', cookie) @@ -160968,7 +161195,7 @@ index e5e9ece..e362c43 100644 self._dirSetupMkdir_p(dir) # persistdir is really root-only but try the make anyway and just -@@ -714,15 +813,15 @@ class YumRepository(Repository, config.RepoConf): +@@ -714,15 +815,15 @@ class YumRepository(Repository, config.RepoConf): local = self.metalink_filename + '.tmp' if not self._metalinkCurrent(): url = misc.to_utf8(self.metalink) @@ -160988,7 +161215,7 @@ index e5e9ece..e362c43 100644 raise Errors.RepoError, msg # Now, we have an old usable metalink, so we can't move to # a newer repomd.xml ... or checksums won't match. -@@ -749,9 +848,22 @@ class YumRepository(Repository, config.RepoConf): +@@ -749,9 +850,22 @@ class YumRepository(Repository, config.RepoConf): value), fdel=lambda self: setattr(self, "_metalink", None)) @@ -161012,7 +161239,7 @@ index e5e9ece..e362c43 100644 """retrieve file from the mirrorgroup for the repo relative to local, optionally get range from start to end, also optionally retrieve from a specific baseurl""" -@@ -768,7 +880,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -768,7 +882,7 @@ class YumRepository(Repository, config.RepoConf): if local is None or relative is None: raise Errors.RepoError, \ @@ -161021,7 +161248,7 @@ index e5e9ece..e362c43 100644 if self.cache == 1: if os.path.exists(local): # FIXME - we should figure out a way -@@ -778,7 +890,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -778,7 +892,7 @@ class YumRepository(Repository, config.RepoConf): raise Errors.RepoError, \ "Caching enabled but no local cache of %s from %s" % (local, @@ -161030,7 +161257,7 @@ index e5e9ece..e362c43 100644 if url: (scheme, netloc, path, query, fragid) = urlparse.urlsplit(url) -@@ -796,6 +908,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -796,6 +910,16 @@ class YumRepository(Repository, config.RepoConf): except Errors.MediaError, e: verbose_logger.log(logginglevels.DEBUG_2, "Error getting package from media; falling back to url %s" %(e,)) @@ -161047,7 +161274,7 @@ index e5e9ece..e362c43 100644 if url and scheme != "media": ugopts = self._default_grabopts(cache=cache) ug = URLGrabber(progress_obj = self.callback, -@@ -815,14 +937,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -815,14 +939,11 @@ class YumRepository(Repository, config.RepoConf): range=(start, end), ) except URLGrabError, e: @@ -161064,7 +161291,7 @@ index e5e9ece..e362c43 100644 else: -@@ -835,19 +954,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -835,19 +956,18 @@ class YumRepository(Repository, config.RepoConf): reget = reget, checkfunc=checkfunc, http_headers=headers, @@ -161090,7 +161317,7 @@ index e5e9ece..e362c43 100644 remote = package.relativepath local = package.localPkg() basepath = package.basepath -@@ -857,15 +975,29 @@ class YumRepository(Repository, config.RepoConf): +@@ -857,15 +977,30 @@ class YumRepository(Repository, config.RepoConf): return local misc.unlink_f(local) @@ -161111,7 +161338,8 @@ index e5e9ece..e362c43 100644 + **kwargs ) -+ if not package.verifyLocalPkg(): # Don't return as "success" when bad. ++ if not kwargs.get('async') and not package.verifyLocalPkg(): ++ # Don't return as "success" when bad. + msg = "Downloaded package %s, from %s, but it was invalid." + msg = msg % (package, package.repo.id) + raise Errors.RepoError, msg @@ -161121,7 +161349,7 @@ index e5e9ece..e362c43 100644 def getHeader(self, package, checkfunc = None, reget = 'simple', cache = True): -@@ -991,7 +1123,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -991,7 +1126,7 @@ class YumRepository(Repository, config.RepoConf): def _cachingRepoXML(self, local): """ Should we cache the current repomd.xml """ if self.cache and not os.path.exists(local): @@ -161130,7 +161358,7 @@ index e5e9ece..e362c43 100644 if self.cache or self.metadataCurrent(): return True return False -@@ -1020,7 +1152,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1020,7 +1155,7 @@ class YumRepository(Repository, config.RepoConf): if grab_can_fail: return None raise Errors.RepoError, 'Error downloading file %s: %s' % (local, e) @@ -161139,7 +161367,7 @@ index e5e9ece..e362c43 100644 misc.unlink_f(tfname) if grab_can_fail: return None -@@ -1047,7 +1179,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1047,7 +1182,7 @@ class YumRepository(Repository, config.RepoConf): parse_can_fail = 'old_repo_XML' in self._oldRepoMDData if parse_can_fail: return None @@ -161148,7 +161376,7 @@ index e5e9ece..e362c43 100644 def _saveOldRepoXML(self, local): """ If we have an older repomd.xml file available, save it out. """ -@@ -1074,7 +1206,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1074,7 +1209,7 @@ class YumRepository(Repository, config.RepoConf): # We still want the old data, so we don't download twice. So we # pretend everything is good until the revert. if not self.timestamp_check: @@ -161157,7 +161385,7 @@ index e5e9ece..e362c43 100644 if 'old_repo_XML' not in self._oldRepoMDData: self._oldRepoMDData = {} -@@ -1260,6 +1392,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1260,6 +1395,9 @@ class YumRepository(Repository, config.RepoConf): return True def _check_db_version(self, mdtype, repoXML=None): @@ -161167,7 +161395,7 @@ index e5e9ece..e362c43 100644 if repoXML is None: repoXML = self.repoXML if mdtype in repoXML.repoData: -@@ -1277,11 +1412,11 @@ class YumRepository(Repository, config.RepoConf): +@@ -1277,11 +1415,11 @@ class YumRepository(Repository, config.RepoConf): return None if not file_check: @@ -161182,7 +161410,7 @@ index e5e9ece..e362c43 100644 if not os.path.exists(local): local = misc.decompress(local, fn_only=True) compressed = True -@@ -1302,6 +1437,17 @@ class YumRepository(Repository, config.RepoConf): +@@ -1302,6 +1440,17 @@ class YumRepository(Repository, config.RepoConf): into the delete list, this means metadata can change filename without us leaking it. """ @@ -161200,7 +161428,7 @@ index e5e9ece..e362c43 100644 def _mdtype_eq(omdtype, odata, nmdtype, ndata): """ Check if two returns from _get_mdtype_data() are equal. """ if ndata is None: -@@ -1321,6 +1467,14 @@ class YumRepository(Repository, config.RepoConf): +@@ -1321,6 +1470,14 @@ class YumRepository(Repository, config.RepoConf): return True all_mdtypes = self.retrieved.keys() @@ -161215,7 +161443,7 @@ index e5e9ece..e362c43 100644 if mdtypes is None: mdtypes = all_mdtypes -@@ -1333,8 +1487,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1333,8 +1490,7 @@ class YumRepository(Repository, config.RepoConf): # Inited twice atm. ... sue me self._oldRepoMDData['new_MD_files'] = [] @@ -161225,7 +161453,7 @@ index e5e9ece..e362c43 100644 for mdtype in all_mdtypes: (nmdtype, ndata) = self._get_mdtype_data(mdtype) -@@ -1371,43 +1524,16 @@ class YumRepository(Repository, config.RepoConf): +@@ -1371,43 +1527,16 @@ class YumRepository(Repository, config.RepoConf): # No old repomd data, but we might still have uncompressed MD if self._groupCheckDataMDValid(ndata, nmdtype, mdtype): continue @@ -161274,7 +161502,7 @@ index e5e9ece..e362c43 100644 def _groupLoadRepoXML(self, text=None, mdtypes=None): """ Retrieve the new repomd.xml from the repository, then check it -@@ -1421,7 +1547,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1421,7 +1550,7 @@ class YumRepository(Repository, config.RepoConf): self._commonRetrieveDataMD(mdtypes) def _mdpolicy2mdtypes(self): @@ -161283,7 +161511,7 @@ index e5e9ece..e362c43 100644 'group:primary' : ['primary'], 'group:small' : ["primary", "updateinfo"], 'group:main' : ["primary", "group", "filelists", -@@ -1436,6 +1562,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1436,6 +1565,7 @@ class YumRepository(Repository, config.RepoConf): if not mdtypes or 'group:all' in mdtypes: mdtypes = None else: @@ -161291,7 +161519,7 @@ index e5e9ece..e362c43 100644 mdtypes = sorted(list(mdtypes)) return mdtypes -@@ -1446,17 +1573,12 @@ class YumRepository(Repository, config.RepoConf): +@@ -1446,17 +1576,12 @@ class YumRepository(Repository, config.RepoConf): except KeyboardInterrupt: self._revertOldRepoXML() # Undo metadata cookie? raise @@ -161311,7 +161539,7 @@ index e5e9ece..e362c43 100644 return self._repoXML -@@ -1480,7 +1602,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1480,7 +1605,7 @@ class YumRepository(Repository, config.RepoConf): result = self._getFile(relative='repodata/repomd.xml.asc', copy_local=1, local = sigfile, @@ -161320,7 +161548,7 @@ index e5e9ece..e362c43 100644 reget=None, checkfunc=None, cache=self.http_caching == 'all', -@@ -1514,7 +1636,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1514,7 +1639,7 @@ class YumRepository(Repository, config.RepoConf): return self._checkMD(fn, mdtype, openchecksum) def _checkMD(self, fn, mdtype, openchecksum=False, @@ -161329,7 +161557,7 @@ index e5e9ece..e362c43 100644 """ Internal function, use .checkMD() from outside yum. """ thisdata = data # So the argument name is nicer -@@ -1537,6 +1659,18 @@ class YumRepository(Repository, config.RepoConf): +@@ -1537,6 +1662,18 @@ class YumRepository(Repository, config.RepoConf): if size is not None: size = int(size) @@ -161348,7 +161576,7 @@ index e5e9ece..e362c43 100644 try: # get the local checksum l_csum = self._checksum(r_ctype, file, datasize=size) except Errors.RepoError, e: -@@ -1551,15 +1685,13 @@ class YumRepository(Repository, config.RepoConf): +@@ -1551,15 +1688,13 @@ class YumRepository(Repository, config.RepoConf): return None raise URLGrabError(-1, 'Metadata file does not match checksum') @@ -161365,7 +161593,7 @@ index e5e9ece..e362c43 100644 """ Internal function, use .retrieveMD() from outside yum. """ # Note that this can raise Errors.RepoMDError if mdtype doesn't exist # for this repo. -@@ -1580,15 +1712,19 @@ class YumRepository(Repository, config.RepoConf): +@@ -1580,15 +1715,19 @@ class YumRepository(Repository, config.RepoConf): try: self.checkMD(local, mdtype) except URLGrabError, e: @@ -161386,7 +161614,7 @@ index e5e9ece..e362c43 100644 if (os.path.exists(local) or self._preload_md_from_system_cache(os.path.basename(local))): -@@ -1597,8 +1733,10 @@ class YumRepository(Repository, config.RepoConf): +@@ -1597,8 +1736,10 @@ class YumRepository(Repository, config.RepoConf): return local # it's the same return the local one try: @@ -161399,7 +161627,7 @@ index e5e9ece..e362c43 100644 if thisdata.size is None: reget = None else: -@@ -1613,8 +1751,9 @@ class YumRepository(Repository, config.RepoConf): +@@ -1613,8 +1754,9 @@ class YumRepository(Repository, config.RepoConf): checkfunc=checkfunc, text=text, cache=self.http_caching == 'all', @@ -161411,7 +161639,7 @@ index e5e9ece..e362c43 100644 if retrieve_can_fail: return None raise -@@ -1622,9 +1761,8 @@ class YumRepository(Repository, config.RepoConf): +@@ -1622,9 +1764,8 @@ class YumRepository(Repository, config.RepoConf): if retrieve_can_fail: return None raise Errors.RepoError, \ @@ -161422,7 +161650,7 @@ index e5e9ece..e362c43 100644 return local -@@ -1646,13 +1784,21 @@ class YumRepository(Repository, config.RepoConf): +@@ -1646,13 +1787,21 @@ class YumRepository(Repository, config.RepoConf): def getGroups(self): """gets groups and returns group file path for the repository, if there @@ -161447,7 +161675,7 @@ index e5e9ece..e362c43 100644 self._callbacks_changed = True def setFailureObj(self, failure_obj): -@@ -1681,7 +1827,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1681,7 +1830,7 @@ class YumRepository(Repository, config.RepoConf): print "Could not read mirrorlist %s, error was \n%s" %(url, e) content = [] for line in content: @@ -161456,7 +161684,7 @@ index e5e9ece..e362c43 100644 continue mirror = line.rstrip() # no more trailing \n's mirror = mirror.replace('$ARCH', '$BASEARCH') -@@ -1713,7 +1859,7 @@ class YumRepository(Repository, config.RepoConf): +@@ -1713,7 +1862,7 @@ class YumRepository(Repository, config.RepoConf): ugopts = self._default_grabopts() try: fo = urlgrabber.grabber.urlopen(url, **ugopts) @@ -161465,7 +161693,7 @@ index e5e9ece..e362c43 100644 print "Could not retrieve mirrorlist %s error was\n%s: %s" % (url, e.args[0], misc.to_unicode(e.args[1])) fo = None -@@ -1877,7 +2023,7 @@ def getMirrorList(mirrorlist, pdict = None): +@@ -1877,7 +2026,7 @@ def getMirrorList(mirrorlist, pdict = None): try: fo = urlresolver.urlopen(url, proxies=pdict) diff --git a/yum.spec b/yum.spec index 51537e8..7cd1616 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 47%{?dist} +Release: 48%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -317,7 +317,16 @@ exit 0 %endif %changelog -* Thu Oct 25 2012 Zdenek Pavlas - 3.4.3-47 +* Mon Nov 19 2012 Zdenek Pavlas - 3.4.3-48 +- update to latest HEAD. +- add skip-broken option to yum-cron. +- get rid of bogus "Downloaded package .. but it was invalid." +- clean up misc.to_xml(), make it faster. BZ 716235. +- checksum not available implies checksum does not match. BZ 825272. +- avoid checksumming existing .sqlite.bz2 files. +- fix circular obsoletes in transaction members check. BZ 868840. + +* Tu Oct 25 2012 Zdenek Pavlas - 3.4.3-47 - replaced yum-cron.sh with the new yum-cron.py (very alpha) * Thu Oct 25 2012 Nils Philippsen - 3.4.3-46 From 0e55c6ec4ee54c7ba8280e371d2c89c4b3eddf2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Pavlas?= Date: Mon, 19 Nov 2012 18:05:22 +0100 Subject: [PATCH 010/174] fix a typo in .spec --- yum.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yum.spec b/yum.spec index 7cd1616..bafd613 100644 --- a/yum.spec +++ b/yum.spec @@ -326,7 +326,7 @@ exit 0 - avoid checksumming existing .sqlite.bz2 files. - fix circular obsoletes in transaction members check. BZ 868840. -* Tu Oct 25 2012 Zdenek Pavlas - 3.4.3-47 +* Thu Oct 25 2012 Zdenek Pavlas - 3.4.3-47 - replaced yum-cron.sh with the new yum-cron.py (very alpha) * Thu Oct 25 2012 Nils Philippsen - 3.4.3-46 From b3089c7fdec1126f29f9902373c4ee2a2dfd31d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Pavlas?= Date: Wed, 28 Nov 2012 14:57:13 +0100 Subject: [PATCH 011/174] update to latest HEAD. --- yum-HEAD.patch | 44 ++++++++++++++++++++++++++++++++++++-------- yum.spec | 9 +++++++-- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index eefa7b1..7e987b0 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -152135,7 +152135,7 @@ index 1ce4720..25e3022 gobject.threads_init() dbus.glib.threads_init() diff --git a/yum.spec b/yum.spec -index abd203f..a309594 100644 +index abd203f..d7568db 100644 --- a/yum.spec +++ b/yum.spec @@ -1,24 +1,53 @@ @@ -152248,6 +152248,15 @@ index abd203f..a309594 100644 Requires(postun): /sbin/service +@@ -72,7 +113,7 @@ can notify you when they are available via email, syslog or dbus. + %package cron + Summary: Files needed to run yum updates as a cron job + Group: System Environment/Base +-Requires: yum >= 3.0 vixie-cron crontabs yum-plugin-downloadonly findutils ++Requires: yum >= 3.0 cronie crontabs findutils + Requires(post): /sbin/chkconfig + Requires(post): /sbin/service + Requires(preun): /sbin/chkconfig @@ -83,18 +124,46 @@ Requires(postun): /sbin/service These are the files needed to run yum updates as a cron job. Install this package if you want auto yum updates nightly via cron. @@ -160562,7 +160571,7 @@ index 9b265f9..74a0f3f 100644 + + self.display.verify_txmbr(self.base, txmbr, count) diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py -index 8a6f6f3..a955895 100644 +index 8a6f6f3..65401a9 100644 --- a/yum/sqlitesack.py +++ b/yum/sqlitesack.py @@ -69,7 +69,7 @@ def _parse_pkg_n(match, regexp_match, n): @@ -160583,7 +160592,26 @@ index 8a6f6f3..a955895 100644 match[0] != n[0] and match[0] != e[0]): return False -@@ -382,6 +382,10 @@ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase): +@@ -298,13 +298,14 @@ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase): + "WHERE packages.pkgId = ?", (self.pkgId,)) + for ob in cur: + dirname = ob['dirname'] ++ if dirname == '.': ++ dirname = '' ++ elif dirname and dirname[-1] != '/': ++ dirname += '/' + filetypes = decodefiletypelist(ob['filetypes']) + filenames = decodefilenamelist(ob['filenames']) + while(filetypes): +- if dirname: +- filename = dirname+'/'+filenames.pop() +- else: +- filename = filenames.pop() ++ filename = dirname + filenames.pop() + filetype = _share_data(filetypes.pop()) + result.setdefault(filetype,[]).append(filename) + self._loadedfiles = True +@@ -382,6 +383,10 @@ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase): def returnPrco(self, prcotype, printable=False): prcotype = _share_data(prcotype) @@ -160594,7 +160622,7 @@ index 8a6f6f3..a955895 100644 if isinstance(self.prco[prcotype], tuple): sql = "SELECT name, version, release, epoch, flags " \ "FROM %s WHERE pkgKey = ?" % prcotype -@@ -406,7 +410,7 @@ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase): +@@ -406,7 +411,7 @@ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase): requires = [] for ob in cur: pre = "0" @@ -160603,7 +160631,7 @@ index 8a6f6f3..a955895 100644 pre = "1" prco_set = (_share_data(ob['name']), _share_data(ob['flags']), (_share_data(ob['epoch']), -@@ -917,8 +921,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): +@@ -917,8 +922,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): # ultra simple optimization if misc.re_primary_filename(name): @@ -160613,7 +160641,7 @@ index 8a6f6f3..a955895 100644 if len(self.filelistsdb) == 0: # grab repo object from primarydb and force filelists population in this sack using repo -@@ -1560,7 +1563,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): +@@ -1560,7 +1564,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): patterns = tmp return (need_full, patterns, fields, False) @@ -160622,7 +160650,7 @@ index 8a6f6f3..a955895 100644 def _yieldSQLDataList(self, repoid, patterns, fields, ignore_case): """Yields all the package data for the given params. Excludes are done at this stage. """ -@@ -1593,6 +1596,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): +@@ -1593,6 +1597,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): for x in cur: yield (repo, x) @@ -160630,7 +160658,7 @@ index 8a6f6f3..a955895 100644 def _buildPkgObjList(self, repoid=None, patterns=None, ignore_case=False): """Builds a list of packages, only containing nevra information. Excludes are done at this stage. """ -@@ -1666,6 +1670,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): +@@ -1666,6 +1671,7 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack): return returnList diff --git a/yum.spec b/yum.spec index bafd613..0fe3ed7 100644 --- a/yum.spec +++ b/yum.spec @@ -18,7 +18,7 @@ Summary: RPM package installer/updater/manager Name: yum Version: 3.4.3 -Release: 48%{?dist} +Release: 49%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz @@ -123,7 +123,7 @@ can notify you when they are available via email, syslog or dbus. %package cron Summary: Files needed to run yum updates as a cron job Group: System Environment/Base -Requires: yum >= 3.0 vixie-cron crontabs yum-plugin-downloadonly findutils +Requires: yum >= 3.0 cronie crontabs findutils Requires(post): /sbin/chkconfig Requires(post): /sbin/service Requires(preun): /sbin/chkconfig @@ -317,6 +317,11 @@ exit 0 %endif %changelog +* Wed Nov 28 2012 Zdenek Pavlas - 3.4.3-49 +- update to latest HEAD. +- Fix ugly paths in po.xml_dump_*(). BZ 835565. +- Fix yum-cron requires. + * Mon Nov 19 2012 Zdenek Pavlas - 3.4.3-48 - update to latest HEAD. - add skip-broken option to yum-cron. From e8e7766e145ca8e1ca48d46d06a224a0fa83e28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Pavlas?= Date: Thu, 6 Dec 2012 12:27:30 +0100 Subject: [PATCH 012/174] update to latest HEAD. --- yum-HEAD.patch | 477 ++++++++++++++++++++++++++++++++----------------- yum.spec | 9 +- 2 files changed, 326 insertions(+), 160 deletions(-) diff --git a/yum-HEAD.patch b/yum-HEAD.patch index 7e987b0..a6156a1 100644 --- a/yum-HEAD.patch +++ b/yum-HEAD.patch @@ -2375,7 +2375,7 @@ index 0000000..4d01a5a + the mailing list, yum@lists.baseurl.org, or consult bugzilla. +.fi diff --git a/docs/yum.8 b/docs/yum.8 -index 1a8202a..65ff448 100644 +index 1a8202a..604bc26 100644 --- a/docs/yum.8 +++ b/docs/yum.8 @@ -52,6 +52,7 @@ gnome\-packagekit application\&. @@ -2543,7 +2543,7 @@ index 1a8202a..65ff448 100644 .IP +.IP "\fBrepoinfo\fP" +.IP -+This ocmmand works exactly like repolist -v. ++This command works exactly like repolist -v. +.IP .IP "\fBversion\fP" Produces a "version" of the rpmdb, and of the enabled repositories if "all" is @@ -3649,7 +3649,7 @@ index f1e06e8..d484f8d 100644 complete -F _yum -o filenames yum yummain.py diff --git a/output.py b/output.py -index b6aa277..05b255e 100755 +index b6aa277..885eb09 100755 --- a/output.py +++ b/output.py @@ -1,6 +1,6 @@ @@ -4730,7 +4730,7 @@ index b6aa277..05b255e 100755 if len(remote_pkgs) <= 1: return if not hasattr(urlgrabber.progress, 'TerminalLine'): -@@ -1434,8 +1960,17 @@ to exit. +@@ -1434,10 +1960,21 @@ to exit. return tids, printall def historyListCmd(self, extcmds): @@ -4748,8 +4748,12 @@ index b6aa277..05b255e 100755 + """ tids, printall = self._history_list_transactions(extcmds) if tids is None: ++ if not extcmds: # This is not a real error... ++ return 0, ['No accessible history to list'] return 1, ['Failed history list'] -@@ -1564,6 +2099,16 @@ to exit. + + limit = 20 +@@ -1564,6 +2101,16 @@ to exit. return old[0] def historyInfoCmd(self, extcmds): @@ -4766,7 +4770,7 @@ index b6aa277..05b255e 100755 def str2int(x): try: return int(x) -@@ -1656,6 +2201,9 @@ to exit. +@@ -1656,6 +2203,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. """ @@ -4776,7 +4780,7 @@ index b6aa277..05b255e 100755 ipkgs = self.rpmdb.searchPkgTuple(hpkg.pkgtup) if not ipkgs: apkgs = self.pkgSack.searchPkgTuple(hpkg.pkgtup) -@@ -1672,13 +2220,12 @@ to exit. +@@ -1672,13 +2222,12 @@ to exit. 'o' : _('Updated'), 'n' : _('Downgraded')} _pkg_states_available = {'i' : _('Installed'), 'e' : _('Not installed'), 'o' : _('Older'), 'n' : _('Newer')} @@ -4793,7 +4797,7 @@ index b6aa277..05b255e 100755 prefix = " " * prefix_len if was_installed: _pkg_states = _pkg_states_installed -@@ -1702,9 +2249,11 @@ to exit. +@@ -1702,9 +2251,11 @@ to exit. else: (hibeg, hiend) = self._highlight('normal') state = utf8_width_fill(state, _pkg_states['maxlen']) @@ -4807,7 +4811,7 @@ index b6aa277..05b255e 100755 if type(old.tid) == type([]): print _("Transaction ID :"), "%u..%u" % (old.tid[0], old.tid[-1]) -@@ -1778,8 +2327,8 @@ to exit. +@@ -1778,8 +2329,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: @@ -4818,7 +4822,7 @@ index b6aa277..05b255e 100755 if old.trans_with: # This is _possible_, but not common -@@ -1794,7 +2343,9 @@ to exit. +@@ -1794,7 +2345,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: @@ -4829,7 +4833,7 @@ index b6aa277..05b255e 100755 if old.rpmdb_problems: print _("Rpmdb Problems:") -@@ -1833,6 +2384,13 @@ to exit. +@@ -1833,6 +2386,13 @@ to exit. 'Updated' : _('Updated'), } def historyInfoCmdPkgsAltered(self, old, pats=[]): @@ -4843,7 +4847,7 @@ index b6aa277..05b255e 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 +2444,10 @@ to exit. +@@ -1886,6 +2446,10 @@ to exit. self._hpkg2from_repo(hpkg)) def historySummaryCmd(self, extcmds): @@ -4854,7 +4858,7 @@ index b6aa277..05b255e 100755 tids, printall = self._history_list_transactions(extcmds) if tids is None: return 1, ['Failed history info'] -@@ -1946,6 +2508,10 @@ to exit. +@@ -1946,6 +2510,10 @@ to exit. utf8_width_fill(uiacts, 16, 16), count) def historyAddonInfoCmd(self, extcmds): @@ -4865,7 +4869,7 @@ index b6aa277..05b255e 100755 tid = None if len(extcmds) > 1: tid = extcmds[1] -@@ -1983,16 +2549,19 @@ to exit. +@@ -1983,16 +2551,19 @@ to exit. for item in extcmds[2:]: if item in addon_info: @@ -4891,7 +4895,7 @@ index b6aa277..05b255e 100755 tids = self.history.search(extcmds) limit = None if extcmds and not tids: -@@ -2078,9 +2647,94 @@ to exit. +@@ -2078,9 +2649,94 @@ to exit. if lastdbv.end_rpmdbversion != rpmdbv: self._rpmdb_warn_checks() @@ -4987,7 +4991,7 @@ index b6aa277..05b255e 100755 def __init__(self, ayum=None): """requires yum-cli log and errorlog functions as arguments""" -@@ -2089,6 +2743,25 @@ class DepSolveProgressCallBack: +@@ -2089,6 +2745,25 @@ class DepSolveProgressCallBack: self.ayum = ayum def pkgAdded(self, pkgtup, mode): @@ -5013,7 +5017,7 @@ index b6aa277..05b255e 100755 modedict = { 'i': _('installed'), 'u': _('an update'), 'e': _('erased'), -@@ -2104,43 +2777,85 @@ class DepSolveProgressCallBack: +@@ -2104,43 +2779,85 @@ class DepSolveProgressCallBack: modeterm) def start(self): @@ -5101,7 +5105,7 @@ index b6aa277..05b255e 100755 needname, needflags, needversion = reqTup yb = self.ayum -@@ -2225,46 +2940,106 @@ class DepSolveProgressCallBack: +@@ -2225,46 +2942,106 @@ class DepSolveProgressCallBack: return msg def procConflict(self, name, confname): @@ -5213,7 +5217,7 @@ index b6aa277..05b255e 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 +3091,7 @@ def _pkgname_ui(ayum, pkgname, ts_states=None): +@@ -2316,10 +3093,7 @@ def _pkgname_ui(ayum, pkgname, ts_states=None): return pkgname class YumCliRPMCallBack(RPMBaseCallback): @@ -5225,7 +5229,7 @@ index b6aa277..05b255e 100755 width = property(lambda x: _term_width()) -@@ -2337,21 +3109,34 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2337,21 +3111,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)): @@ -5270,7 +5274,7 @@ index b6aa277..05b255e 100755 if type(package) not in types.StringTypes: pkgname = str(package) -@@ -2363,9 +3148,25 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2363,9 +3150,25 @@ class YumCliRPMCallBack(RPMBaseCallback): percent = 0 else: percent = (te_current*100L)/te_total @@ -5297,7 +5301,7 @@ index b6aa277..05b255e 100755 pkgname=pkgname, wid1=wid1) msg = fmt % (utf8_width_fill(process, wid1, wid1), utf8_width_fill(pkgname, wid2, wid2)) -@@ -2377,6 +3178,11 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2377,6 +3180,11 @@ class YumCliRPMCallBack(RPMBaseCallback): print " " def scriptout(self, package, msgs): @@ -5309,7 +5313,7 @@ index b6aa277..05b255e 100755 if msgs: sys.stdout.write(to_unicode(msgs)) sys.stdout.flush() -@@ -2429,8 +3235,30 @@ class YumCliRPMCallBack(RPMBaseCallback): +@@ -2429,8 +3237,30 @@ class YumCliRPMCallBack(RPMBaseCallback): wid2 = pnl return fmt, wid1, wid2 @@ -152440,7 +152444,7 @@ index c1af4ad..e3e3956 100644 pass diff --git a/yum/__init__.py b/yum/__init__.py -index 99039e0..604ccce 100644 +index 99039e0..6401645 100644 --- a/yum/__init__.py +++ b/yum/__init__.py @@ -21,6 +21,7 @@ The Yum RPM software updater. @@ -153106,7 +153110,16 @@ index 99039e0..604ccce 100644 if pkgtup is None: return self._not_found_i[pkgtup] = YumNotFoundPackage(pkgtup) -@@ -1454,8 +1630,14 @@ class YumBase(depsolve.Depsolve): +@@ -1382,6 +1558,8 @@ class YumBase(depsolve.Depsolve): + for txmbr in self.tsInfo.getMembers(dep.pkgtup): + for pkg in (txmbr.updates + txmbr.obsoletes): + toRemove.add(pkg) ++ if dep in toRemove: # If this is true we inf. recurse, so check ++ continue # even though it shouldn't happen. bz#874065 + toRemove.add(dep) + self._getDepsToRemove(dep, deptree, toRemove) + +@@ -1454,8 +1632,14 @@ class YumBase(depsolve.Depsolve): return probs def runTransaction(self, cb): @@ -153122,7 +153135,7 @@ index 99039e0..604ccce 100644 self.plugins.run('pretrans') # We may want to put this other places, eventually, but for now it's -@@ -1516,10 +1698,23 @@ class YumBase(depsolve.Depsolve): +@@ -1516,10 +1700,23 @@ class YumBase(depsolve.Depsolve): pass self._ts_save_file = None @@ -153146,7 +153159,7 @@ index 99039e0..604ccce 100644 # make resultobject - just a plain yumgenericholder object resultobject = misc.GenericHolder() -@@ -1567,13 +1762,24 @@ class YumBase(depsolve.Depsolve): +@@ -1567,13 +1764,24 @@ 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): @@ -153176,7 +153189,7 @@ index 99039e0..604ccce 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,9 +1790,16 @@ class YumBase(depsolve.Depsolve): +@@ -1584,9 +1792,16 @@ 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 @@ -153193,7 +153206,7 @@ index 99039e0..604ccce 100644 for txmbr in self.tsInfo: if txmbr.output_state in TS_INSTALL_STATES: if not self.rpmdb.contains(po=txmbr.po): -@@ -1596,7 +1809,9 @@ class YumBase(depsolve.Depsolve): +@@ -1596,7 +1811,9 @@ 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 @@ -153203,7 +153216,7 @@ index 99039e0..604ccce 100644 po = self.getInstalledPackageObject(txmbr.pkgtup) rpo = txmbr.po po.yumdb_info.from_repo = rpo.repoid -@@ -1630,6 +1845,10 @@ class YumBase(depsolve.Depsolve): +@@ -1630,6 +1847,10 @@ class YumBase(depsolve.Depsolve): if md: po.yumdb_info.from_repo_timestamp = str(md.timestamp) @@ -153214,7 +153227,7 @@ index 99039e0..604ccce 100644 loginuid = misc.getloginuid() if txmbr.updates or txmbr.downgrades or txmbr.reinstall: if txmbr.updates: -@@ -1640,11 +1859,16 @@ class YumBase(depsolve.Depsolve): +@@ -1640,11 +1861,16 @@ class YumBase(depsolve.Depsolve): opo = po if 'installed_by' in opo.yumdb_info: po.yumdb_info.installed_by = opo.yumdb_info.installed_by @@ -153231,7 +153244,7 @@ index 99039e0..604ccce 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 +1886,13 @@ class YumBase(depsolve.Depsolve): +@@ -1662,10 +1888,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 @@ -153245,7 +153258,7 @@ index 99039e0..604ccce 100644 self.verbose_logger.log(logginglevels.DEBUG_2, 'What is this? %s' % txmbr.po) self.plugins.run('postverifytrans') -@@ -1680,10 +1907,11 @@ class YumBase(depsolve.Depsolve): +@@ -1680,10 +1909,11 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.debug('VerifyTransaction time: %0.3f' % (time.time() - vt_st)) def costExcludePackages(self): @@ -153261,7 +153274,7 @@ index 99039e0..604ccce 100644 # if all the repo.costs are equal then don't bother running things costs = {} for r in self.repos.listEnabled(): -@@ -1705,10 +1933,12 @@ class YumBase(depsolve.Depsolve): +@@ -1705,10 +1935,12 @@ class YumBase(depsolve.Depsolve): done = True def excludePackages(self, repo=None): @@ -153277,7 +153290,7 @@ index 99039e0..604ccce 100644 if "all" in self.conf.disable_excludes: return -@@ -1735,9 +1965,11 @@ class YumBase(depsolve.Depsolve): +@@ -1735,9 +1967,11 @@ class YumBase(depsolve.Depsolve): self.pkgSack.addPackageExcluder(repoid, exid,'exclude.match', match) def includePackages(self, repo): @@ -153292,7 +153305,7 @@ index 99039e0..604ccce 100644 includelist = repo.getIncludePkgList() if len(includelist) == 0: -@@ -1757,8 +1989,11 @@ class YumBase(depsolve.Depsolve): +@@ -1757,8 +1991,11 @@ class YumBase(depsolve.Depsolve): self.pkgSack.addPackageExcluder(repo.id, exid, 'exclude.marked') def doLock(self, lockfile = YUM_PID_FILE): @@ -153306,7 +153319,7 @@ index 99039e0..604ccce 100644 if self.conf.uid != 0: # If we are a user, assume we are using the root cache ... so don't # bother locking. -@@ -1774,38 +2009,26 @@ class YumBase(depsolve.Depsolve): +@@ -1774,38 +2011,26 @@ class YumBase(depsolve.Depsolve): mypid=str(os.getpid()) while not self._lock(lockfile, mypid, 0644): @@ -153360,7 +153373,7 @@ index 99039e0..604ccce 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 +2053,69 @@ class YumBase(depsolve.Depsolve): +@@ -1830,31 +2055,69 @@ class YumBase(depsolve.Depsolve): self._unlock(lockfile) self._lockfile = None @@ -153440,7 +153453,7 @@ index 99039e0..604ccce 100644 failed = False if type(fo) is types.InstanceType: -@@ -1894,9 +2155,16 @@ class YumBase(depsolve.Depsolve): +@@ -1894,9 +2157,16 @@ class YumBase(depsolve.Depsolve): def verifyChecksum(self, fo, checksumType, csum): @@ -153460,7 +153473,7 @@ index 99039e0..604ccce 100644 try: filesum = misc.checksum(checksumType, fo) except Errors.MiscError, e: -@@ -1908,6 +2176,17 @@ class YumBase(depsolve.Depsolve): +@@ -1908,6 +2178,17 @@ class YumBase(depsolve.Depsolve): return 0 def downloadPkgs(self, pkglist, callback=None, callback_total=None): @@ -153478,7 +153491,7 @@ index 99039e0..604ccce 100644 def mediasort(apo, bpo): # FIXME: we should probably also use the mediaid; else we # could conceivably ping-pong between different disc1's -@@ -1943,6 +2222,7 @@ class YumBase(depsolve.Depsolve): +@@ -1943,6 +2224,7 @@ class YumBase(depsolve.Depsolve): self.history.close() self.plugins.run('predownload', pkglist=pkglist) @@ -153486,7 +153499,7 @@ index 99039e0..604ccce 100644 repo_cached = False remote_pkgs = [] remote_size = 0 -@@ -1961,6 +2241,14 @@ class YumBase(depsolve.Depsolve): +@@ -1961,6 +2243,14 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.debug(_("using local copy of %s") %(po,)) continue @@ -153501,7 +153514,7 @@ index 99039e0..604ccce 100644 remote_pkgs.append(po) remote_size += po.size -@@ -1969,7 +2257,11 @@ class YumBase(depsolve.Depsolve): +@@ -1969,7 +2259,11 @@ class YumBase(depsolve.Depsolve): # way to save this, report the error and return if (self.conf.cache or repo_cached) and errors: return errors @@ -153514,7 +153527,7 @@ index 99039e0..604ccce 100644 remote_pkgs.sort(mediasort) # This is kind of a hack and does nothing in non-Fedora versions, -@@ -1979,8 +2271,9 @@ class YumBase(depsolve.Depsolve): +@@ -1979,8 +2273,9 @@ class YumBase(depsolve.Depsolve): urlgrabber.progress.text_meter_total_size(remote_size) beg_download = time.time() i = 0 @@ -153525,7 +153538,7 @@ index 99039e0..604ccce 100644 for po in remote_pkgs: # Recheck if the file is there, works around a couple of weird # edge cases. -@@ -1992,67 +2285,94 @@ class YumBase(depsolve.Depsolve): +@@ -1992,67 +2287,94 @@ class YumBase(depsolve.Depsolve): remote_size -= po.size if hasattr(urlgrabber.progress, 'text_meter_total_size'): urlgrabber.progress.text_meter_total_size(remote_size, @@ -153653,7 +153666,7 @@ index 99039e0..604ccce 100644 if type(fo) is types.InstanceType: fo = fo.filename -@@ -2076,9 +2396,12 @@ class YumBase(depsolve.Depsolve): +@@ -2076,9 +2398,12 @@ class YumBase(depsolve.Depsolve): return 1 def downloadHeader(self, po): @@ -153668,7 +153681,7 @@ index 99039e0..604ccce 100644 if hasattr(po, 'pkgtype') and po.pkgtype == 'local': return -@@ -2122,15 +2445,17 @@ class YumBase(depsolve.Depsolve): +@@ -2122,15 +2447,17 @@ class YumBase(depsolve.Depsolve): return def sigCheckPkg(self, po): @@ -153694,7 +153707,7 @@ index 99039e0..604ccce 100644 if self._override_sigchecks: check = False hasgpgkey = 0 -@@ -2181,6 +2506,9 @@ class YumBase(depsolve.Depsolve): +@@ -2181,6 +2508,9 @@ class YumBase(depsolve.Depsolve): return result, msg def cleanUsedHeadersPackages(self): @@ -153704,7 +153717,7 @@ index 99039e0..604ccce 100644 filelist = [] for txmbr in self.tsInfo: if txmbr.po.state not in TS_INSTALL_STATES: -@@ -2218,27 +2546,42 @@ class YumBase(depsolve.Depsolve): +@@ -2218,27 +2548,42 @@ class YumBase(depsolve.Depsolve): _('%s removed'), fn) def cleanHeaders(self): @@ -153749,7 +153762,7 @@ index 99039e0..604ccce 100644 cachedir = self.conf.persistdir + "/rpmdb-indexes/" if not os.path.exists(cachedir): filelist = [] -@@ -2272,8 +2615,29 @@ class YumBase(depsolve.Depsolve): +@@ -2272,8 +2617,29 @@ class YumBase(depsolve.Depsolve): def doPackageLists(self, pkgnarrow='all', patterns=None, showdups=None, ignore_case=False): @@ -153781,7 +153794,7 @@ index 99039e0..604ccce 100644 if showdups is None: showdups = self.conf.showdupesfromrepos ygh = misc.GenericHolder(iter=pkgnarrow) -@@ -2323,10 +2687,22 @@ class YumBase(depsolve.Depsolve): +@@ -2323,10 +2689,22 @@ class YumBase(depsolve.Depsolve): key = (pkg.name, pkg.arch) if pkg.pkgtup in dinst: reinstall_available.append(pkg) @@ -153807,7 +153820,7 @@ index 99039e0..604ccce 100644 # produce the updates list of tuples elif pkgnarrow == 'updates': -@@ -2461,14 +2837,13 @@ class YumBase(depsolve.Depsolve): +@@ -2461,14 +2839,13 @@ class YumBase(depsolve.Depsolve): def findDeps(self, pkgs): @@ -153827,7 +153840,7 @@ index 99039e0..604ccce 100644 results = {} for pkg in pkgs: -@@ -2495,10 +2870,22 @@ class YumBase(depsolve.Depsolve): +@@ -2495,10 +2872,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): @@ -153854,7 +153867,7 @@ index 99039e0..604ccce 100644 sql_fields = [] for f in fields: sql_fields.append(RPM_TO_SQLITE.get(f, f)) -@@ -2661,6 +3048,14 @@ class YumBase(depsolve.Depsolve): +@@ -2661,6 +3050,14 @@ class YumBase(depsolve.Depsolve): yield (po, vs) def searchPackageTags(self, criteria): @@ -153869,7 +153882,7 @@ index 99039e0..604ccce 100644 results = {} # name = [(criteria, taglist)] for c in criteria: c = c.lower() -@@ -2677,11 +3072,16 @@ class YumBase(depsolve.Depsolve): +@@ -2677,11 +3074,16 @@ class YumBase(depsolve.Depsolve): return results def searchPackages(self, fields, criteria, callback=None): @@ -153891,7 +153904,7 @@ index 99039e0..604ccce 100644 warnings.warn(_('searchPackages() will go away in a future version of Yum.\ Use searchGenerator() instead. \n'), Errors.YumFutureDeprecationWarning, stacklevel=2) -@@ -2700,13 +3100,23 @@ class YumBase(depsolve.Depsolve): +@@ -2700,13 +3102,23 @@ class YumBase(depsolve.Depsolve): def searchPackageProvides(self, args, callback=None, callback_has_matchfor=False): @@ -153919,7 +153932,7 @@ index 99039e0..604ccce 100644 else: isglob = True canBeFile = misc.re_filename(arg) -@@ -2723,7 +3133,7 @@ class YumBase(depsolve.Depsolve): +@@ -2723,7 +3135,7 @@ class YumBase(depsolve.Depsolve): where = self.returnPackagesByDep(arg) else: usedDepString = False @@ -153928,7 +153941,7 @@ index 99039e0..604ccce 100644 self.verbose_logger.log(logginglevels.DEBUG_1, P_('Searching %d package', 'Searching %d packages', len(where)), len(where)) -@@ -2817,25 +3227,160 @@ class YumBase(depsolve.Depsolve): +@@ -2817,25 +3229,160 @@ class YumBase(depsolve.Depsolve): return matches @@ -154101,7 +154114,7 @@ index 99039e0..604ccce 100644 if uservisible: if grp.user_visible: installed.append(grp) -@@ -2847,34 +3392,98 @@ class YumBase(depsolve.Depsolve): +@@ -2847,34 +3394,98 @@ class YumBase(depsolve.Depsolve): available.append(grp) else: available.append(grp) @@ -154210,7 +154223,7 @@ index 99039e0..604ccce 100644 thesegroups = self.comps.return_groups(grpid) if not thesegroups: raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -2898,13 +3507,58 @@ class YumBase(depsolve.Depsolve): +@@ -2898,13 +3509,58 @@ class YumBase(depsolve.Depsolve): self.tsInfo.remove(txmbr.po.pkgtup) @@ -154276,7 +154289,7 @@ index 99039e0..604ccce 100644 """ if not self.comps.has_group(grpid): -@@ -2920,6 +3574,9 @@ class YumBase(depsolve.Depsolve): +@@ -2920,6 +3576,9 @@ class YumBase(depsolve.Depsolve): if group_package_types: package_types = group_package_types @@ -154286,7 +154299,7 @@ index 99039e0..604ccce 100644 for thisgroup in thesegroups: if thisgroup.selected: continue -@@ -2934,12 +3591,49 @@ class YumBase(depsolve.Depsolve): +@@ -2934,12 +3593,49 @@ class YumBase(depsolve.Depsolve): if 'optional' in package_types: pkgs.extend(thisgroup.optional_packages) @@ -154337,7 +154350,7 @@ index 99039e0..604ccce 100644 except Errors.InstallError, e: self.verbose_logger.debug(_('No package named %s available to be installed'), pkg) -@@ -2953,7 +3647,9 @@ class YumBase(depsolve.Depsolve): +@@ -2953,7 +3649,9 @@ class YumBase(depsolve.Depsolve): group_conditionals = enable_group_conditionals count_cond_test = 0 @@ -154348,7 +154361,7 @@ index 99039e0..604ccce 100644 for condreq, cond in thisgroup.conditional_packages.iteritems(): if self.isPackageInstalled(cond): try: -@@ -2990,17 +3686,22 @@ class YumBase(depsolve.Depsolve): +@@ -2990,17 +3688,22 @@ class YumBase(depsolve.Depsolve): if cond not in self.tsInfo.conditionals: self.tsInfo.conditionals[cond] = [] self.tsInfo.conditionals[cond].extend(pkgs) @@ -154377,7 +154390,7 @@ index 99039e0..604ccce 100644 if not self.comps.has_group(grpid): raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -3008,7 +3709,8 @@ class YumBase(depsolve.Depsolve): +@@ -3008,7 +3711,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) @@ -154387,7 +154400,7 @@ index 99039e0..604ccce 100644 for thisgroup in thesegroups: thisgroup.selected = False -@@ -3034,13 +3736,102 @@ class YumBase(depsolve.Depsolve): +@@ -3034,13 +3738,102 @@ class YumBase(depsolve.Depsolve): for pkg in self.tsInfo.conditionals.get(txmbr.name, []): self.tsInfo.remove(pkg.pkgtup) @@ -154496,7 +154509,7 @@ index 99039e0..604ccce 100644 # look it up in the self.localPackages first: for po in self.localPackages: if po.pkgtup == pkgtup: -@@ -3049,7 +3840,7 @@ class YumBase(depsolve.Depsolve): +@@ -3049,7 +3842,7 @@ class YumBase(depsolve.Depsolve): pkgs = self.pkgSack.searchPkgTuple(pkgtup) if len(pkgs) == 0: @@ -154505,7 +154518,7 @@ index 99039e0..604ccce 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 +3856,21 @@ class YumBase(depsolve.Depsolve): +@@ -3065,13 +3858,21 @@ class YumBase(depsolve.Depsolve): return result def getInstalledPackageObject(self, pkgtup): @@ -154532,7 +154545,7 @@ index 99039e0..604ccce 100644 raise Errors.RpmDBError, _('Package tuple %s could not be found in rpmdb') % str(pkgtup) # Dito. FIXME from getPackageObject() for len() > 1 ... :) -@@ -3079,9 +3878,11 @@ class YumBase(depsolve.Depsolve): +@@ -3079,9 +3880,11 @@ class YumBase(depsolve.Depsolve): return po def gpgKeyCheck(self): @@ -154546,7 +154559,7 @@ index 99039e0..604ccce 100644 gpgkeyschecked = self.conf.cachedir + '/.gpgkeyschecked.yum' if os.path.exists(gpgkeyschecked): return 1 -@@ -3106,9 +3907,13 @@ class YumBase(depsolve.Depsolve): +@@ -3106,9 +3909,13 @@ class YumBase(depsolve.Depsolve): return 1 def returnPackagesByDep(self, depstring): @@ -154562,7 +154575,7 @@ index 99039e0..604ccce 100644 if not depstring: return [] -@@ -3135,9 +3940,16 @@ class YumBase(depsolve.Depsolve): +@@ -3135,9 +3942,16 @@ class YumBase(depsolve.Depsolve): return self.pkgSack.getProvides(depname, depflags, depver).keys() def returnPackageByDep(self, depstring): @@ -154582,7 +154595,7 @@ index 99039e0..604ccce 100644 # we get all sorts of randomness here errstring = depstring if type(depstring) not in types.StringTypes: -@@ -3149,16 +3961,22 @@ class YumBase(depsolve.Depsolve): +@@ -3149,16 +3963,22 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _('No Package found for %s') % errstring ps = ListPackageSack(pkglist) @@ -154609,7 +154622,7 @@ index 99039e0..604ccce 100644 if not depstring: return [] -@@ -3184,12 +4002,47 @@ class YumBase(depsolve.Depsolve): +@@ -3184,12 +4004,47 @@ class YumBase(depsolve.Depsolve): return self.rpmdb.getProvides(depname, depflags, depver).keys() @@ -154659,7 +154672,7 @@ index 99039e0..604ccce 100644 if len(pkglist) == 0: -@@ -3198,14 +4051,23 @@ class YumBase(depsolve.Depsolve): +@@ -3198,14 +4053,23 @@ class YumBase(depsolve.Depsolve): if len(pkglist) == 1: return pkglist[0] @@ -154689,7 +154702,7 @@ index 99039e0..604ccce 100644 returnlist = [] compatArchList = self.arch.get_arch_list(arch) multiLib = [] -@@ -3222,9 +4084,9 @@ class YumBase(depsolve.Depsolve): +@@ -3222,9 +4086,9 @@ class YumBase(depsolve.Depsolve): singleLib.append(po) # we now have three lists. find the best package(s) of each @@ -154702,7 +154715,7 @@ index 99039e0..604ccce 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 +4100,7 @@ class YumBase(depsolve.Depsolve): +@@ -3238,7 +4102,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: @@ -154711,7 +154724,7 @@ index 99039e0..604ccce 100644 if best.arch == "noarch": returnlist.append(no) else: -@@ -3246,7 +4108,7 @@ class YumBase(depsolve.Depsolve): +@@ -3246,7 +4110,7 @@ class YumBase(depsolve.Depsolve): if single: returnlist.append(single) # similar for the non-multilib case elif single: @@ -154720,7 +154733,7 @@ index 99039e0..604ccce 100644 if best.arch == "noarch": returnlist.append(no) else: -@@ -3350,28 +4212,58 @@ class YumBase(depsolve.Depsolve): +@@ -3350,28 +4214,58 @@ class YumBase(depsolve.Depsolve): done = True slow = next_func(slow) @@ -154784,7 +154797,7 @@ index 99039e0..604ccce 100644 try: txmbrs = self.groupRemove(group_string) except yum.Errors.GroupsError: -@@ -3387,6 +4279,8 @@ class YumBase(depsolve.Depsolve): +@@ -3387,6 +4281,8 @@ class YumBase(depsolve.Depsolve): assert pattern[0] == '@' grpid = pattern[1:] @@ -154793,7 +154806,7 @@ index 99039e0..604ccce 100644 thesegroups = self.comps.return_groups(grpid) if not thesegroups: raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid) -@@ -3398,7 +4292,11 @@ class YumBase(depsolve.Depsolve): +@@ -3398,7 +4294,11 @@ class YumBase(depsolve.Depsolve): def _minus_deselect(self, pattern): """ Remove things from the transaction, like kickstart. """ assert pattern[0] == '-' @@ -154806,7 +154819,7 @@ index 99039e0..604ccce 100644 if pat and pat[0] == '@': pat = pat[1:] -@@ -3437,14 +4335,87 @@ class YumBase(depsolve.Depsolve): +@@ -3437,14 +4337,87 @@ class YumBase(depsolve.Depsolve): if flag not in self.tsInfo.probFilterFlags: self.tsInfo.probFilterFlags.append(flag) @@ -154900,7 +154913,7 @@ index 99039e0..604ccce 100644 pkgs = [] was_pattern = False if po: -@@ -3477,20 +4448,12 @@ class YumBase(depsolve.Depsolve): +@@ -3477,20 +4450,12 @@ class YumBase(depsolve.Depsolve): self.verbose_logger.debug(_('Checking for virtual provide or file-provide for %s'), arg) @@ -154927,7 +154940,7 @@ index 99039e0..604ccce 100644 else: nevra_dict = self._nevra_kwarg_parse(kwargs) -@@ -3577,17 +4540,20 @@ class YumBase(depsolve.Depsolve): +@@ -3577,17 +4542,20 @@ class YumBase(depsolve.Depsolve): continue # make sure this shouldn't be passed to update: @@ -154951,7 +154964,7 @@ index 99039e0..604ccce 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 +4566,23 @@ class YumBase(depsolve.Depsolve): +@@ -3600,23 +4568,23 @@ class YumBase(depsolve.Depsolve): already_obs = pkgs[0] if already_obs: @@ -154982,7 +154995,7 @@ index 99039e0..604ccce 100644 continue # make sure we don't have a name.arch of this already installed -@@ -3630,7 +4596,7 @@ class YumBase(depsolve.Depsolve): +@@ -3630,7 +4598,7 @@ class YumBase(depsolve.Depsolve): found = True break if not found: @@ -154991,7 +155004,7 @@ index 99039e0..604ccce 100644 txmbrs = self.update(po=po) tx_return.extend(txmbrs) continue -@@ -3719,19 +4685,47 @@ class YumBase(depsolve.Depsolve): +@@ -3719,19 +4687,47 @@ class YumBase(depsolve.Depsolve): return txmbr def update(self, po=None, requiringPo=None, update_to=False, **kwargs): @@ -155046,7 +155059,7 @@ index 99039e0..604ccce 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 +4759,14 @@ class YumBase(depsolve.Depsolve): +@@ -3765,7 +4761,14 @@ class YumBase(depsolve.Depsolve): if new is None: continue tx_return.extend(self.update(po=new)) @@ -155062,7 +155075,7 @@ index 99039e0..604ccce 100644 return tx_return # complications -@@ -3787,7 +4788,7 @@ class YumBase(depsolve.Depsolve): +@@ -3787,7 +4790,7 @@ class YumBase(depsolve.Depsolve): return self._minus_deselect(kwargs['pattern']) if kwargs['pattern'] and kwargs['pattern'][0] == '@': @@ -155071,7 +155084,7 @@ index 99039e0..604ccce 100644 arg = kwargs['pattern'] if not update_to: -@@ -3843,7 +4844,7 @@ class YumBase(depsolve.Depsolve): +@@ -3843,7 +4846,7 @@ class YumBase(depsolve.Depsolve): availpkgs = self._compare_providers(availpkgs, requiringPo) availpkgs = map(lambda x: x[0], availpkgs) elif not availpkgs: @@ -155080,7 +155093,7 @@ index 99039e0..604ccce 100644 # for any thing specified # get the list of available pkgs matching it (or take the po) -@@ -3920,6 +4921,21 @@ class YumBase(depsolve.Depsolve): +@@ -3920,6 +4923,21 @@ class YumBase(depsolve.Depsolve): tx_return.append(txmbr) for available_pkg in availpkgs: @@ -155102,7 +155115,7 @@ index 99039e0..604ccce 100644 # Make sure we're not installing a package which is obsoleted by # something else in the repo. Unless there is a obsoletion loop, # at which point ignore everything. -@@ -3985,11 +5001,18 @@ class YumBase(depsolve.Depsolve): +@@ -3985,11 +5003,18 @@ class YumBase(depsolve.Depsolve): return tx_return def remove(self, po=None, **kwargs): @@ -155126,7 +155139,7 @@ index 99039e0..604ccce 100644 if not po and not kwargs: raise Errors.RemoveError, 'Nothing specified to remove' -@@ -4055,17 +5078,19 @@ class YumBase(depsolve.Depsolve): +@@ -4055,17 +5080,19 @@ class YumBase(depsolve.Depsolve): return tx_return def installLocal(self, pkg, po=None, updateonly=False): @@ -155156,7 +155169,7 @@ index 99039e0..604ccce 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 +5208,15 @@ class YumBase(depsolve.Depsolve): +@@ -4183,16 +5210,15 @@ class YumBase(depsolve.Depsolve): return tx_return def reinstallLocal(self, pkg, po=None): @@ -155181,7 +155194,7 @@ index 99039e0..604ccce 100644 if not po: try: po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg, -@@ -4215,9 +5239,19 @@ class YumBase(depsolve.Depsolve): +@@ -4215,9 +5241,19 @@ class YumBase(depsolve.Depsolve): return self.reinstall(po=po) def reinstall(self, po=None, **kwargs): @@ -155204,7 +155217,7 @@ index 99039e0..604ccce 100644 self._add_prob_flags(rpm.RPMPROB_FILTER_REPLACEPKG, rpm.RPMPROB_FILTER_REPLACENEWFILES, rpm.RPMPROB_FILTER_REPLACEOLDFILES) -@@ -4259,16 +5293,15 @@ class YumBase(depsolve.Depsolve): +@@ -4259,16 +5295,15 @@ class YumBase(depsolve.Depsolve): return tx_mbrs def downgradeLocal(self, pkg, po=None): @@ -155229,7 +155242,7 @@ index 99039e0..604ccce 100644 if not po: try: po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg, -@@ -4309,13 +5342,19 @@ class YumBase(depsolve.Depsolve): +@@ -4309,13 +5344,19 @@ class YumBase(depsolve.Depsolve): return False def downgrade(self, po=None, **kwargs): @@ -155256,7 +155269,7 @@ index 99039e0..604ccce 100644 if not po and not kwargs: raise Errors.DowngradeError, 'Nothing specified to downgrade' -@@ -4397,6 +5436,10 @@ class YumBase(depsolve.Depsolve): +@@ -4397,6 +5438,10 @@ class YumBase(depsolve.Depsolve): # installed version. Indexed fromn the latest installed pkgtup. downgrade_apkgs = {} for pkg in sorted(apkgs): @@ -155267,7 +155280,7 @@ index 99039e0..604ccce 100644 na = (pkg.name, pkg.arch) # Here we allow downgrades from .i386 => .noarch, or .i586 => .i386 -@@ -4421,6 +5464,9 @@ class YumBase(depsolve.Depsolve): +@@ -4421,6 +5466,9 @@ class YumBase(depsolve.Depsolve): warned_nas.add(na) continue @@ -155277,7 +155290,7 @@ index 99039e0..604ccce 100644 if pkg.verGE(lipkg): if na not in warned_nas: msg = _('Only Upgrade available on package: %s') % pkg -@@ -4457,7 +5503,7 @@ class YumBase(depsolve.Depsolve): +@@ -4457,7 +5505,7 @@ class YumBase(depsolve.Depsolve): if e and v and r: evr = '%s:%s-%s' % (e, v, r) elif v and r: @@ -155286,7 +155299,7 @@ index 99039e0..604ccce 100644 elif e and v: evr = '%s:%s' % (e, v) elif v: # e and r etc. is just too weird to print -@@ -4500,12 +5546,24 @@ class YumBase(depsolve.Depsolve): +@@ -4500,12 +5548,24 @@ class YumBase(depsolve.Depsolve): return returndict @@ -155314,7 +155327,7 @@ index 99039e0..604ccce 100644 old_conf_obs = self.conf.obsoletes self.conf.obsoletes = False done = False -@@ -4515,19 +5573,46 @@ class YumBase(depsolve.Depsolve): +@@ -4515,19 +5575,46 @@ class YumBase(depsolve.Depsolve): done = True for pkg in transaction.trans_data: if pkg.state == 'Downgrade': @@ -155361,7 +155374,7 @@ index 99039e0..604ccce 100644 if self.install(pkgtup=pkg.pkgtup): done = True for pkg in transaction.trans_data: -@@ -4538,8 +5623,14 @@ class YumBase(depsolve.Depsolve): +@@ -4538,8 +5625,14 @@ class YumBase(depsolve.Depsolve): return done def history_undo(self, transaction): @@ -155378,7 +155391,7 @@ index 99039e0..604ccce 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 +5707,7 @@ class YumBase(depsolve.Depsolve): +@@ -4616,7 +5709,7 @@ class YumBase(depsolve.Depsolve): except urlgrabber.grabber.URLGrabError, e: raise Errors.YumBaseError(_('GPG key retrieval failed: ') + @@ -155387,7 +155400,7 @@ index 99039e0..604ccce 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 +5740,7 @@ class YumBase(depsolve.Depsolve): +@@ -4649,7 +5742,7 @@ class YumBase(depsolve.Depsolve): keys_info = misc.getgpgkeyinfo(rawkey, multiple=True) except ValueError, e: raise Errors.YumBaseError(_('Invalid GPG Key from %s: %s') % @@ -155396,7 +155409,7 @@ index 99039e0..604ccce 100644 keys = [] for keyinfo in keys_info: thiskey = {} -@@ -4674,39 +5765,49 @@ class YumBase(depsolve.Depsolve): +@@ -4674,39 +5767,49 @@ class YumBase(depsolve.Depsolve): if pkgs: pkgs = sorted(pkgs)[-1] msg = (_('Importing %s key 0x%s:\n' @@ -155464,7 +155477,7 @@ index 99039e0..604ccce 100644 user_cb_fail = False for keyurl in keyurls: keys = self._retrievePublicKey(keyurl, repo) -@@ -4725,7 +5826,9 @@ class YumBase(depsolve.Depsolve): +@@ -4725,7 +5828,9 @@ class YumBase(depsolve.Depsolve): # Try installing/updating GPG key self._getKeyImportMessage(info, keyurl) rc = False @@ -155475,7 +155488,7 @@ index 99039e0..604ccce 100644 rc = True # grab the .sig/.asc for the keyurl, if it exists -@@ -4751,8 +5854,8 @@ class YumBase(depsolve.Depsolve): +@@ -4751,8 +5856,8 @@ class YumBase(depsolve.Depsolve): ts = self.rpmdb.readOnlyTS() result = ts.pgpImportPubkey(misc.procgpgkey(info['raw_key'])) if result != 0: @@ -155486,7 +155499,7 @@ index 99039e0..604ccce 100644 self.logger.info(_('Key imported successfully')) key_installed = True -@@ -4760,18 +5863,20 @@ class YumBase(depsolve.Depsolve): +@@ -4760,18 +5865,20 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError, _("Didn't install any keys") if not key_installed: @@ -155512,7 +155525,7 @@ index 99039e0..604ccce 100644 def _getAnyKeyForRepo(self, repo, destdir, keyurl_list, is_cakey=False, callback=None): """ -@@ -4788,6 +5893,18 @@ class YumBase(depsolve.Depsolve): +@@ -4788,6 +5895,18 @@ class YumBase(depsolve.Depsolve): """ key_installed = False @@ -155531,7 +155544,7 @@ index 99039e0..604ccce 100644 user_cb_fail = False for keyurl in keyurl_list: keys = self._retrievePublicKey(keyurl, repo, getSig=not is_cakey) -@@ -4819,8 +5936,11 @@ class YumBase(depsolve.Depsolve): +@@ -4819,8 +5938,11 @@ class YumBase(depsolve.Depsolve): if not key_installed: self._getKeyImportMessage(info, keyurl, keytype) rc = False @@ -155544,7 +155557,7 @@ index 99039e0..604ccce 100644 elif callback: rc = callback({"repo": repo, "userid": info['userid'], "hexkeyid": info['hexkeyid'], "keyurl": keyurl, -@@ -4835,7 +5955,8 @@ class YumBase(depsolve.Depsolve): +@@ -4835,7 +5957,8 @@ class YumBase(depsolve.Depsolve): # Import the key result = misc.import_key_to_pubring(info['raw_key'], info['hexkeyid'], gpgdir=destdir) if not result: @@ -155554,7 +155567,7 @@ index 99039e0..604ccce 100644 self.logger.info(_('Key imported successfully')) key_installed = True # write out the key id to imported_cakeys in the repos basedir -@@ -4851,36 +5972,35 @@ class YumBase(depsolve.Depsolve): +@@ -4851,36 +5974,35 @@ class YumBase(depsolve.Depsolve): pass if not key_installed and user_cb_fail: @@ -155607,7 +155620,7 @@ index 99039e0..604ccce 100644 self._getAnyKeyForRepo(repo, repo.gpgcadir, repo.gpgcakey, is_cakey=True, callback=callback) def _limit_installonly_pkgs(self): -@@ -4927,6 +6047,7 @@ class YumBase(depsolve.Depsolve): +@@ -4927,6 +6049,7 @@ class YumBase(depsolve.Depsolve): ts = self.rpmdb.readOnlyTS() (cur_kernel_v, cur_kernel_r) = misc.get_running_kernel_version_release(ts) install_only_names = set(self.conf.installonlypkgs) @@ -155615,7 +155628,7 @@ index 99039e0..604ccce 100644 for m in self.tsInfo.getMembers(): if m.ts_state not in ('i', 'u'): continue -@@ -4937,12 +6058,21 @@ class YumBase(depsolve.Depsolve): +@@ -4937,12 +6060,21 @@ class YumBase(depsolve.Depsolve): if not po_names.intersection(install_only_names): continue @@ -155641,7 +155654,7 @@ index 99039e0..604ccce 100644 for po in installed: if (po.version, po.release) == (cur_kernel_v, cur_kernel_r): # don't remove running -@@ -4959,19 +6089,22 @@ class YumBase(depsolve.Depsolve): +@@ -4959,19 +6091,22 @@ class YumBase(depsolve.Depsolve): txmbr.depends_on.append(rel) def processTransaction(self, callback=None,rpmTestDisplay=None, rpmDisplay=None): @@ -155677,7 +155690,7 @@ index 99039e0..604ccce 100644 if not callback: callback = callbacks.ProcessTransNoOutputCallback() -@@ -5114,13 +6247,19 @@ class YumBase(depsolve.Depsolve): +@@ -5114,13 +6249,19 @@ class YumBase(depsolve.Depsolve): return results def add_enable_repo(self, repoid, baseurls=[], mirrorlist=None, **kwargs): @@ -155704,7 +155717,7 @@ index 99039e0..604ccce 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 +6306,15 @@ class YumBase(depsolve.Depsolve): +@@ -5167,9 +6308,15 @@ class YumBase(depsolve.Depsolve): def setCacheDir(self, force=False, tmpdir=None, reuse=True, suffix='/$basearch/$releasever'): @@ -155723,7 +155736,7 @@ index 99039e0..604ccce 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 +6324,7 @@ class YumBase(depsolve.Depsolve): +@@ -5179,7 +6326,7 @@ class YumBase(depsolve.Depsolve): try: cachedir = misc.getCacheDir(tmpdir, reuse) except (IOError, OSError), e: @@ -155732,7 +155745,7 @@ index 99039e0..604ccce 100644 cachedir = None if cachedir is None: -@@ -5190,6 +6335,7 @@ class YumBase(depsolve.Depsolve): +@@ -5190,6 +6337,7 @@ class YumBase(depsolve.Depsolve): self.prerepoconf.cachedir = cachedir else: self.repos.setCacheDir(cachedir) @@ -155740,7 +155753,7 @@ index 99039e0..604ccce 100644 self.conf.cachedir = cachedir return True # We got a new cache dir -@@ -5220,13 +6366,24 @@ class YumBase(depsolve.Depsolve): +@@ -5220,13 +6368,24 @@ class YumBase(depsolve.Depsolve): self.history.write_addon_data('config-repos', myrepos) def verify_plugins_cb(self, verify_package): @@ -155768,7 +155781,7 @@ index 99039e0..604ccce 100644 if self.tsInfo._unresolvedMembers: if auto: self.logger.critical(_("Dependencies not solved. Will not save unresolved transaction.")) -@@ -5234,7 +6391,7 @@ class YumBase(depsolve.Depsolve): +@@ -5234,7 +6393,7 @@ class YumBase(depsolve.Depsolve): raise Errors.YumBaseError(_("Dependencies not solved. Will not save unresolved transaction.")) if not filename: @@ -155777,7 +155790,7 @@ index 99039e0..604ccce 100644 fd,filename = tempfile.mkstemp(suffix='.yumtx', prefix=prefix) f = os.fdopen(fd, 'w') else: -@@ -5244,13 +6401,17 @@ class YumBase(depsolve.Depsolve): +@@ -5244,13 +6403,17 @@ class YumBase(depsolve.Depsolve): msg = "%s\n" % self.rpmdb.simpleVersion(main_only=True)[0] msg += "%s\n" % self.ts.getTsFlags() @@ -155798,7 +155811,7 @@ index 99039e0..604ccce 100644 msg += "%s\n" % len(self.tsInfo.getMembers()) for txmbr in self.tsInfo.getMembers(): msg += txmbr._dump() -@@ -5260,13 +6421,25 @@ class YumBase(depsolve.Depsolve): +@@ -5260,13 +6423,25 @@ class YumBase(depsolve.Depsolve): except (IOError, OSError), e: self._ts_save_file = None if auto: @@ -155830,7 +155843,7 @@ index 99039e0..604ccce 100644 # check rpmversion - if not match throw a fit # check repoversions (and repos)- if not match throw a fit # load each txmbr - if pkgs being updated don't exist, bail w/error -@@ -5276,26 +6449,45 @@ class YumBase(depsolve.Depsolve): +@@ -5276,26 +6451,45 @@ class YumBase(depsolve.Depsolve): try: data = open(filename, 'r').readlines() except (IOError, OSError), e: @@ -155878,7 +155891,7 @@ index 99039e0..604ccce 100644 if ignorerpm: msg += _(" ignoring, as requested.") self.logger.critical(_(msg)) -@@ -5318,8 +6510,17 @@ class YumBase(depsolve.Depsolve): +@@ -5318,8 +6512,17 @@ class YumBase(depsolve.Depsolve): numrepos = int(data[2].strip()) repos = [] rindex=3+numrepos @@ -155897,7 +155910,7 @@ index 99039e0..604ccce 100644 # pkgs/txmbrs numpkgs = int(data[rindex].strip()) -@@ -5329,6 +6530,7 @@ class YumBase(depsolve.Depsolve): +@@ -5329,6 +6532,7 @@ class YumBase(depsolve.Depsolve): pkgcount = 0 pkgprob = False curpkg = None @@ -155905,7 +155918,7 @@ index 99039e0..604ccce 100644 for l in data[pkgstart:]: l = l.rstrip() # our main txmbrs -@@ -5356,6 +6558,7 @@ class YumBase(depsolve.Depsolve): +@@ -5356,6 +6560,7 @@ class YumBase(depsolve.Depsolve): if not ignoremissing: raise Errors.YumBaseError(msg) else: @@ -155913,7 +155926,7 @@ index 99039e0..604ccce 100644 self.logger.critical(msg) else: pkgcount += 1 -@@ -5432,12 +6635,18 @@ class YumBase(depsolve.Depsolve): +@@ -5432,12 +6637,18 @@ class YumBase(depsolve.Depsolve): if pkgprob: msg = _("Transaction members, relations are missing or ts has been modified,") if ignoremissing: @@ -155932,7 +155945,7 @@ index 99039e0..604ccce 100644 return self.tsInfo.getMembers() def _remove_old_deps(self): -@@ -5470,18 +6679,6 @@ class YumBase(depsolve.Depsolve): +@@ -5470,18 +6681,6 @@ class YumBase(depsolve.Depsolve): if requiring == required: # if they are self-requiring skip them continue @@ -155951,7 +155964,7 @@ index 99039e0..604ccce 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 +6730,24 @@ class YumBase(depsolve.Depsolve): +@@ -5533,7 +6732,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 @@ -155976,7 +155989,7 @@ index 99039e0..604ccce 100644 visited[curpkg] = True all_leaves_visited = True leaves = curpkg.requiring_packages() -@@ -5547,4 +6761,3 @@ class YumBase(depsolve.Depsolve): +@@ -5547,4 +6763,3 @@ class YumBase(depsolve.Depsolve): # Debugging output self.verbose_logger.log(logginglevels.DEBUG_2, _("%s has no user-installed revdeps."), pkg) return False @@ -159248,7 +159261,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..1ce45f4 100644 +index 5ef9951..62f989f 100644 --- a/yum/packages.py +++ b/yum/packages.py @@ -106,14 +106,16 @@ def buildPkgRefDict(pkgs, casematch=True): @@ -159446,16 +159459,59 @@ index 5ef9951..1ce45f4 100644 conflicts_print = property(fget=lambda self: self.returnPrco('conflicts', True)) obsoletes_print = property(fget=lambda self: self.returnPrco('obsoletes', True)) changelog = property(fget=lambda self: self.returnChangelog()) -@@ -1083,7 +1143,7 @@ class YumAvailablePackage(PackageObject, RpmBase): - misc.to_unicode(misc.to_xml(self.summary)), - misc.to_unicode(misc.to_xml(self.description)), +@@ -797,22 +857,14 @@ class YumAvailablePackage(PackageObject, RpmBase): + if hasattr(self, '_committer_ret'): + return self._committer_ret + +- def _nf2ascii(x): +- """ does .encode("ascii", "replace") but it never fails. """ +- ret = [] +- for val in x: +- if ord(val) >= 128: +- val = '?' +- ret.append(val) +- return "".join(ret) +- + if not len(self.changelog): # Empty changelog is _possible_ I guess + self._committer_ret = self.packager + return self._committer_ret + val = self.changelog[0][1] + # Chagnelog data is in multiple locale's, so we convert to ascii + # ignoring "bad" chars. +- val = _nf2ascii(val) ++ val = misc.to_unicode(val, errors='replace') ++ val = val.encode('ascii', 'replace') + # Hacky way to get rid of version numbers... + ix = val.find('> ') + if ix != -1: +@@ -1063,10 +1115,10 @@ class YumAvailablePackage(PackageObject, RpmBase): + + packager = url = '' + if self.packager: +- packager = misc.to_unicode(misc.to_xml(self.packager)) ++ packager = misc.to_xml(self.packager) + + if self.url: +- url = misc.to_unicode(misc.to_xml(self.url)) ++ url = misc.to_xml(self.url) + (csum_type, csum, csumid) = self.checksums[0] + msg = """ + %s +@@ -1080,10 +1132,10 @@ class YumAvailablePackage(PackageObject, RpmBase): +