Package rpmUtils :: Module updates
[hide private]
[frames] | no frames]

Source Code for Module rpmUtils.updates

  1  #!/usr/bin/python -tt 
  2  # This program is free software; you can redistribute it and/or modify 
  3  # it under the terms of the GNU General Public License as published by 
  4  # the Free Software Foundation; either version 2 of the License, or 
  5  # (at your option) any later version. 
  6  # 
  7  # This program is distributed in the hope that it will be useful, 
  8  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  9  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 10  # GNU Library General Public License for more details. 
 11  # 
 12  # You should have received a copy of the GNU General Public License 
 13  # along with this program; if not, write to the Free Software 
 14  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 15  # Copyright 2004 Duke University 
 16   
 17  import rpmUtils 
 18  import rpmUtils.miscutils 
 19  import rpmUtils.arch 
 20   
21 -def _vertup_cmp(tup1, tup2):
22 return rpmUtils.miscutils.compareEVR(tup1, tup2)
23 -class Updates:
24 """ 25 This class computes and keeps track of updates and obsoletes. 26 initialize, add installed packages, add available packages (both as 27 unique lists of name, arch, ver, rel, epoch tuples), add an optional dict 28 of obsoleting packages with obsoletes and what they obsolete ie:: 29 foo, i386, 0, 1.1, 1: bar >= 1.1. 30 """ 31
32 - def __init__(self, instlist, availlist):
33 34 self.installed = instlist # list of installed pkgs (n, a, e, v, r) 35 self.available = availlist # list of available pkgs (n, a, e, v, r) 36 37 self.rawobsoletes = {} # dict of obsoleting package->[what it obsoletes] 38 self._obsoletes_by_name = None 39 self.obsoleted_dict = {} # obsoleted pkgtup -> [ obsoleting pkgtups ] 40 self.obsoleting_dict = {} # obsoleting pkgtup -> [ obsoleted pkgtups ] 41 42 self.exactarch = 1 # don't change archs by default 43 self.exactarchlist = set(['kernel', 'kernel-smp', 'glibc', 44 'kernel-hugemem', 45 'kernel-enterprise', 'kernel-bigmem', 46 'kernel-BOOT']) 47 48 self.myarch = rpmUtils.arch.canonArch # set this if you want to 49 # test on some other arch 50 # otherwise leave it alone 51 self._is_multilib = rpmUtils.arch.isMultiLibArch(self.myarch) 52 53 self._archlist = rpmUtils.arch.getArchList(self.myarch) 54 55 self._multilib_compat_arches = rpmUtils.arch.getMultiArchInfo(self.myarch) 56 57 # make some dicts from installed and available 58 self.installdict = self.makeNADict(self.installed, 1) 59 self.availdict = self.makeNADict(self.available, 0) # Done in doUpdate 60 61 # holder for our updates dict 62 self.updatesdict = {} 63 self.updating_dict = {} 64 #debug, ignore me 65 self.debug = 0 66 self.obsoletes = {}
67
68 - def _delFromDict(self, dict_, keys, value):
69 for key in keys: 70 if key not in dict_: 71 continue 72 dict_[key] = filter(value.__ne__, dict_[key]) 73 if not dict_[key]: 74 del dict_[key]
75
76 - def _delFromNADict(self, dict_, pkgtup):
77 (n, a, e, v, r) = pkgtup 78 if dict_.has_key((n, a)): 79 dict_[(n, a)] = filter((e,v,r).__ne__, dict_[(n, a)]) 80 if not dict_[(n, a)]: 81 del dict_[(n, a)] 82 if dict_.has_key((n, None)): 83 dict_[(n, None)] = filter((e,v,r).__ne__, dict_[(n, None)]) 84 if not dict_[(n, None)]: 85 del dict_[(n, None)]
86
87 - def delPackage(self, pkgtup):
88 """remove available pkgtup that is no longer available""" 89 if pkgtup not in self.available: 90 return 91 self.available.remove(pkgtup) 92 self._delFromNADict(self.availdict, pkgtup) 93 94 self._delFromDict(self.updating_dict, self.updatesdict.get(pkgtup, []), pkgtup) 95 self._delFromDict(self.updatesdict, self.updating_dict.get(pkgtup, []), pkgtup) 96 97 if self.rawobsoletes.has_key(pkgtup): 98 if self._obsoletes_by_name: 99 for name, flag, version in self.rawobsoletes[pkgtup]: 100 self._delFromDict(self._obsoletes_by_name, [name], (flag, version, pkgtup)) 101 del self.rawobsoletes[pkgtup] 102 103 self._delFromDict(self.obsoleted_dict, self.obsoleting_dict.get(pkgtup, []), pkgtup) 104 self._delFromDict(self.obsoleting_dict, self.obsoleted_dict.get(pkgtup, []), pkgtup)
105
106 - def debugprint(self, msg):
107 if self.debug: 108 print msg
109
110 - def makeNADict(self, pkglist, Nonelists):
111 """return lists of (e,v,r) tuples as value of a dict keyed on (n, a) 112 optionally will return a (n, None) entry with all the a for that 113 n in tuples of (a,e,v,r)""" 114 115 returndict = {} 116 for (n, a, e, v, r) in pkglist: 117 if not returndict.has_key((n, a)): 118 returndict[(n, a)] = [] 119 returndict[(n, a)].append((e,v,r)) 120 121 if Nonelists: 122 if not returndict.has_key((n, None)): 123 returndict[(n, None)] = [] 124 returndict[(n, None)].append((a, e, v, r)) 125 126 return returndict
127 128
129 - def returnNewest(self, evrlist):
130 """takes a list of (e, v, r) tuples and returns the newest one""" 131 if len(evrlist)==0: 132 raise rpmUtils.RpmUtilsError, "Zero Length List in returnNewest call" 133 134 if len(evrlist)==1: 135 return evrlist[0] 136 137 (new_e, new_v, new_r) = evrlist[0] # we'll call the first ones 'newest' 138 139 for (e, v, r) in evrlist[1:]: 140 rc = rpmUtils.miscutils.compareEVR((e, v, r), (new_e, new_v, new_r)) 141 if rc > 0: 142 new_e = e 143 new_v = v 144 new_r = r 145 return (new_e, new_v, new_r)
146 147
148 - def returnHighestVerFromAllArchsByName(self, name, archlist, pkglist):
149 """returns a list of package tuples in a list (n, a, e, v, r) 150 takes a package name, a list of archs, and a list of pkgs in 151 (n, a, e, v, r) form.""" 152 returnlist = [] 153 high_vertup = None 154 for pkgtup in pkglist: 155 (n, a, e, v, r) = pkgtup 156 # FIXME: returnlist used to _possibly_ contain things not in 157 # archlist ... was that desired? 158 if name == n and a in archlist: 159 vertup = (e, v, r) 160 if (high_vertup is None or 161 (_vertup_cmp(high_vertup, vertup) < 0)): 162 high_vertup = vertup 163 returnlist = [] 164 if vertup == high_vertup: 165 returnlist.append(pkgtup) 166 167 return returnlist
168
169 - def condenseUpdates(self):
170 """remove any accidental duplicates in updates""" 171 172 for tup in self.updatesdict: 173 if len(self.updatesdict[tup]) > 1: 174 mylist = self.updatesdict[tup] 175 self.updatesdict[tup] = rpmUtils.miscutils.unique(mylist)
176 177
178 - def checkForObsolete(self, pkglist, newest=1):
179 """accept a list of packages to check to see if anything obsoletes them 180 return an obsoleted_dict in the format of makeObsoletedDict""" 181 if self._obsoletes_by_name is None: 182 self._obsoletes_by_name = {} 183 for pkgtup, obsoletes in self.rawobsoletes.iteritems(): 184 for name, flag, version in obsoletes: 185 self._obsoletes_by_name.setdefault(name, []).append( 186 (flag, version, pkgtup) ) 187 188 obsdict = {} # obseleting package -> [obsoleted package] 189 pkgdict = self.makeNADict(pkglist, 1) 190 191 for pkgtup in pkglist: 192 (name, arch, epoch, ver, rel) = pkgtup 193 for obs_flag, obs_version, obsoleting in self._obsoletes_by_name.get(name, []): 194 if obs_flag in [None, 0] and name == obsoleting[0]: continue 195 if rpmUtils.miscutils.rangeCheck( (name, obs_flag, obs_version), pkgtup): 196 obsdict.setdefault(obsoleting, []).append(pkgtup) 197 198 obslist = obsdict.keys() 199 if newest: 200 obslist = self._reduceListNewestByNameArch(obslist) 201 202 returndict = {} 203 for new in obslist: 204 for old in obsdict[new]: 205 if not returndict.has_key(old): 206 returndict[old] = [] 207 returndict[old].append(new) 208 209 return returndict
210
211 - def doObsoletes(self):
212 """figures out what things available obsolete things installed, returns 213 them in a dict attribute of the class.""" 214 215 obsdict = {} # obseleting package -> [obsoleted package] 216 # this needs to keep arch in mind 217 # if foo.i386 obsoletes bar 218 # it needs to obsoletes bar.i386 preferentially, not bar.x86_64 219 # if there is only one bar and only one foo then obsolete it, but try to 220 # match the arch. 221 222 # look through all the obsoleting packages look for multiple archs per name 223 # if you find it look for the packages they obsolete 224 # 225 obs_arches = {} 226 for (n, a, e, v, r) in self.rawobsoletes: 227 if not obs_arches.has_key(n): 228 obs_arches[n] = [] 229 obs_arches[n].append(a) 230 231 for pkgtup in self.rawobsoletes: 232 (name, arch, epoch, ver, rel) = pkgtup 233 for (obs_n, flag, (obs_e, obs_v, obs_r)) in self.rawobsoletes[(pkgtup)]: 234 if self.installdict.has_key((obs_n, None)): 235 for (rpm_a, rpm_e, rpm_v, rpm_r) in self.installdict[(obs_n, None)]: 236 if flag in [None, 0] or \ 237 rpmUtils.miscutils.rangeCheck((obs_n, flag, (obs_e, obs_v, obs_r)), 238 (obs_n, rpm_a, rpm_e, rpm_v, rpm_r)): 239 # make sure the obsoleting pkg is not already installed 240 willInstall = 1 241 if self.installdict.has_key((name, None)): 242 for (ins_a, ins_e, ins_v, ins_r) in self.installdict[(name, None)]: 243 pkgver = (epoch, ver, rel) 244 installedver = (ins_e, ins_v, ins_r) 245 if self.returnNewest((pkgver, installedver)) == installedver: 246 willInstall = 0 247 break 248 if rpm_a != arch and rpm_a in obs_arches[name]: 249 willInstall = 0 250 if willInstall: 251 if not obsdict.has_key(pkgtup): 252 obsdict[pkgtup] = [] 253 obsdict[pkgtup].append((obs_n, rpm_a, rpm_e, rpm_v, rpm_r)) 254 self.obsoletes = obsdict 255 self.makeObsoletedDict()
256
257 - def makeObsoletedDict(self):
258 """creates a dict of obsoleted packages -> [obsoleting package], this 259 is to make it easier to look up what package obsoletes what item in 260 the rpmdb""" 261 self.obsoleted_dict = {} 262 for new in self.obsoletes: 263 for old in self.obsoletes[new]: 264 if not self.obsoleted_dict.has_key(old): 265 self.obsoleted_dict[old] = [] 266 self.obsoleted_dict[old].append(new) 267 self.obsoleting_dict = {} 268 for obsoleted, obsoletings in self.obsoleted_dict.iteritems(): 269 for obsoleting in obsoletings: 270 self.obsoleting_dict.setdefault(obsoleting, []).append(obsoleted)
271
272 - def doUpdates(self):
273 """check for key lists as populated then commit acts of evil to 274 determine what is updated and/or obsoleted, populate self.updatesdict 275 """ 276 277 278 # best bet is to chew through the pkgs and throw out the new ones early 279 # then deal with the ones where there are a single pkg installed and a 280 # single pkg available 281 # then deal with the multiples 282 283 # we should take the whole list as a 'newlist' and remove those entries 284 # which are clearly: 285 # 1. updates 286 # 2. identical to the ones in ourdb 287 # 3. not in our archdict at all 288 289 simpleupdate = [] 290 complexupdate = [] 291 292 updatedict = {} # (old n, a, e, v, r) : [(new n, a, e, v, r)] 293 # make the new ones a list b/c while we _shouldn't_ 294 # have multiple updaters, we might and well, it needs 295 # to be solved one way or the other <sigh> 296 newpkgs = self.availdict 297 298 archlist = self._archlist 299 for (n, a) in newpkgs.keys(): 300 if a not in archlist: 301 # high log here 302 del newpkgs[(n, a)] 303 continue 304 305 # remove the older stuff - if we're doing an update we only want the 306 # newest evrs 307 for (n, a) in newpkgs: 308 (new_e,new_v,new_r) = self.returnNewest(newpkgs[(n, a)]) 309 for (e, v, r) in newpkgs[(n, a)][:]: 310 if (new_e, new_v, new_r) != (e, v, r): 311 newpkgs[(n, a)].remove((e, v, r)) 312 313 for (n, a) in newpkgs: 314 # simple ones - look for exact matches or older stuff 315 if self.installdict.has_key((n, a)): 316 for (rpm_e, rpm_v, rpm_r) in self.installdict[(n, a)]: 317 try: 318 (e, v, r) = self.returnNewest(newpkgs[(n,a)]) 319 except rpmUtils.RpmUtilsError: 320 continue 321 else: 322 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r)) 323 if rc <= 0: 324 try: 325 newpkgs[(n, a)].remove((e, v, r)) 326 except ValueError: 327 pass 328 329 # Now we add the (n, None) entries back... 330 for na in newpkgs.keys(): 331 all_arches = map(lambda x: (na[1], x[0], x[1], x[2]), newpkgs[na]) 332 newpkgs.setdefault((na[0], None), []).extend(all_arches) 333 334 # get rid of all the empty dict entries: 335 for nakey in newpkgs.keys(): 336 if len(newpkgs[nakey]) == 0: 337 del newpkgs[nakey] 338 339 340 # ok at this point our newpkgs list should be thinned, we should have only 341 # the newest e,v,r's and only archs we can actually use 342 for (n, a) in newpkgs: 343 if a is None: # the None archs are only for lookups 344 continue 345 346 if (n, None) in self.installdict: 347 installarchs = [] 348 availarchs = [] 349 for (a, e, v ,r) in newpkgs[(n, None)]: 350 availarchs.append(a) 351 for (a, e, v, r) in self.installdict[(n, None)]: 352 installarchs.append(a) 353 354 if len(availarchs) > 1 or len(installarchs) > 1: 355 self.debugprint('putting %s in complex update' % n) 356 complexupdate.append(n) 357 else: 358 #log(4, 'putting %s in simple update list' % name) 359 self.debugprint('putting %s in simple update' % n) 360 simpleupdate.append((n, a)) 361 362 # we have our lists to work with now 363 364 # simple cases 365 for (n, a) in simpleupdate: 366 # try to be as precise as possible 367 if n in self.exactarchlist: 368 if self.installdict.has_key((n, a)): 369 (rpm_e, rpm_v, rpm_r) = self.returnNewest(self.installdict[(n, a)]) 370 if newpkgs.has_key((n,a)): 371 (e, v, r) = self.returnNewest(newpkgs[(n, a)]) 372 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r)) 373 if rc > 0: 374 # this is definitely an update - put it in the dict 375 if not updatedict.has_key((n, a, rpm_e, rpm_v, rpm_r)): 376 updatedict[(n, a, rpm_e, rpm_v, rpm_r)] = [] 377 updatedict[(n, a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r)) 378 379 else: 380 # we could only have 1 arch in our rpmdb and 1 arch of pkg 381 # available - so we shouldn't have to worry about the lists, here 382 # we just need to find the arch of the installed pkg so we can 383 # check it's (e, v, r) 384 (rpm_a, rpm_e, rpm_v, rpm_r) = self.installdict[(n, None)][0] 385 if newpkgs.has_key((n, None)): 386 for (a, e, v, r) in newpkgs[(n, None)]: 387 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r)) 388 if rc > 0: 389 # this is definitely an update - put it in the dict 390 if not updatedict.has_key((n, rpm_a, rpm_e, rpm_v, rpm_r)): 391 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)] = [] 392 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r)) 393 394 395 # complex cases 396 397 # we're multilib/biarch 398 # we need to check the name.arch in two different trees 399 # one for the multiarch itself and one for the compat arch 400 # ie: x86_64 and athlon(i686-i386) - we don't want to descend 401 # x86_64->i686 402 # however, we do want to descend x86_64->noarch, sadly. 403 404 archlists = [] 405 if self._is_multilib: 406 if rpmUtils.arch.multilibArches.has_key(self.myarch): 407 biarches = [self.myarch] 408 else: 409 biarches = [self.myarch, rpmUtils.arch.arches[self.myarch]] 410 biarches.append('noarch') 411 412 multicompat = self._multilib_compat_arches[0] 413 multiarchlist = rpmUtils.arch.getArchList(multicompat) 414 archlists = [ set(biarches), set(multiarchlist) ] 415 # archlists = [ biarches, multiarchlist ] 416 else: 417 archlists = [ set(archlist) ] 418 # archlists = [ archlist ] 419 420 for n in complexupdate: 421 for thisarchlist in archlists: 422 # we need to get the highest version and the archs that have it 423 # of the installed pkgs 424 tmplist = [] 425 for (a, e, v, r) in self.installdict[(n, None)]: 426 tmplist.append((n, a, e, v, r)) 427 428 highestinstalledpkgs = self.returnHighestVerFromAllArchsByName(n, 429 thisarchlist, tmplist) 430 hipdict = self.makeNADict(highestinstalledpkgs, 0) 431 432 433 if n in self.exactarchlist: 434 tmplist = [] 435 for (a, e, v, r) in newpkgs[(n, None)]: 436 tmplist.append((n, a, e, v, r)) 437 highestavailablepkgs = self.returnHighestVerFromAllArchsByName(n, 438 thisarchlist, tmplist) 439 440 hapdict = self.makeNADict(highestavailablepkgs, 0) 441 442 for (n, a) in hipdict: 443 if (n, a) in hapdict: 444 self.debugprint('processing %s.%s' % (n, a)) 445 # we've got a match - get our versions and compare 446 (rpm_e, rpm_v, rpm_r) = hipdict[(n, a)][0] # only ever going to be first one 447 (e, v, r) = hapdict[(n, a)][0] # there can be only one 448 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r)) 449 if rc > 0: 450 # this is definitely an update - put it in the dict 451 if not updatedict.has_key((n, a, rpm_e, rpm_v, rpm_r)): 452 updatedict[(n, a, rpm_e, rpm_v, rpm_r)] = [] 453 updatedict[(n, a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r)) 454 else: 455 self.debugprint('processing %s' % n) 456 # this is where we have to have an arch contest if there 457 # is more than one arch updating with the highest ver 458 instarchs = [] 459 for (n,a) in hipdict: 460 instarchs.append(a) 461 462 rpm_a = rpmUtils.arch.getBestArchFromList(instarchs, myarch=self.myarch) 463 if rpm_a is None: 464 continue 465 466 tmplist = [] 467 for (a, e, v, r) in newpkgs[(n, None)]: 468 tmplist.append((n, a, e, v, r)) 469 highestavailablepkgs = self.returnHighestVerFromAllArchsByName(n, 470 thisarchlist, tmplist) 471 472 hapdict = self.makeNADict(highestavailablepkgs, 0) 473 availarchs = [] 474 for (n,a) in hapdict: 475 availarchs.append(a) 476 a = rpmUtils.arch.getBestArchFromList(availarchs, myarch=self.myarch) 477 if a is None: 478 continue 479 480 (rpm_e, rpm_v, rpm_r) = hipdict[(n, rpm_a)][0] # there can be just one 481 (e, v, r) = hapdict[(n, a)][0] # just one, I'm sure, I swear! 482 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r)) 483 if rc > 0: 484 # this is definitely an update - put it in the dict 485 if not updatedict.has_key((n, rpm_a, rpm_e, rpm_v, rpm_r)): 486 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)] = [] 487 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r)) 488 489 self.updatesdict = updatedict 490 self.makeUpdatingDict()
491
492 - def makeUpdatingDict(self):
493 """creates a dict of available packages -> [installed package], this 494 is to make it easier to look up what package will be updating what 495 in the rpmdb""" 496 self.updating_dict = {} 497 for old in self.updatesdict: 498 for new in self.updatesdict[old]: 499 if not self.updating_dict.has_key(new): 500 self.updating_dict[new] = [] 501 self.updating_dict[new].append(old)
502
503 - def reduceListByNameArch(self, pkglist, name=None, arch=None):
504 """returns a set of pkg naevr tuples reduced based on name or arch""" 505 returnlist = [] 506 507 if name or arch: 508 for (n, a, e, v, r) in pkglist: 509 if name: 510 if name == n: 511 returnlist.append((n, a, e, v, r)) 512 continue 513 if arch: 514 if arch == a: 515 returnlist.append((n, a, e, v, r)) 516 continue 517 else: 518 returnlist = pkglist 519 520 return returnlist
521 522
523 - def getUpdatesTuples(self, name=None, arch=None):
524 """returns updates for packages in a list of tuples of: 525 (updating naevr, installed naevr)""" 526 returnlist = [] 527 for oldtup in self.updatesdict: 528 for newtup in self.updatesdict[oldtup]: 529 returnlist.append((newtup, oldtup)) 530 531 # self.reduceListByNameArch() for double tuples 532 tmplist = [] 533 if name: 534 for ((n, a, e, v, r), oldtup) in returnlist: 535 if name != n: 536 tmplist.append(((n, a, e, v, r), oldtup)) 537 if arch: 538 for ((n, a, e, v, r), oldtup) in returnlist: 539 if arch != a: 540 tmplist.append(((n, a, e, v, r), oldtup)) 541 542 for item in tmplist: 543 try: 544 returnlist.remove(item) 545 except ValueError: 546 pass 547 548 return returnlist
549
550 - def getUpdatesList(self, name=None, arch=None):
551 """returns updating packages in a list of (naevr) tuples""" 552 returnlist = [] 553 554 for oldtup in self.updatesdict: 555 for newtup in self.updatesdict[oldtup]: 556 returnlist.append(newtup) 557 558 returnlist = self.reduceListByNameArch(returnlist, name, arch) 559 560 return returnlist
561 562 # NOTE: This returns obsoleters and obsoletees, but narrows based on 563 # _obsoletees_ (unlike getObsoletesList). Look at getObsoletersTuples
564 - def getObsoletesTuples(self, newest=0, name=None, arch=None):
565 """returns obsoletes for packages in a list of tuples of: 566 (obsoleting naevr, installed naevr). You can specify name and/or 567 arch of the installed package to narrow the results. 568 You can also specify newest=1 to get the set of newest pkgs (name, arch) 569 sorted, that obsolete something""" 570 571 tmplist = [] 572 obslist = self.obsoletes.keys() 573 if newest: 574 obslist = self._reduceListNewestByNameArch(obslist) 575 576 for obstup in obslist: 577 for rpmtup in self.obsoletes[obstup]: 578 tmplist.append((obstup, rpmtup)) 579 580 # self.reduceListByNameArch() for double tuples 581 returnlist = [] 582 if name or arch: 583 for (obstup, (n, a, e, v, r)) in tmplist: 584 if name: 585 if name == n: 586 returnlist.append((obstup, (n, a, e, v, r))) 587 continue 588 if arch: 589 if arch == a: 590 returnlist.append((obstup, (n, a, e, v, r))) 591 continue 592 else: 593 returnlist = tmplist 594 595 return returnlist
596 597 # NOTE: This returns obsoleters and obsoletees, but narrows based on 598 # _obsoleters_ (like getObsoletesList).
599 - def getObsoletersTuples(self, newest=0, name=None, arch=None):
600 """returns obsoletes for packages in a list of tuples of: 601 (obsoleting naevr, installed naevr). You can specify name and/or 602 arch of the obsoleting package to narrow the results. 603 You can also specify newest=1 to get the set of newest pkgs (name, arch) 604 sorted, that obsolete something""" 605 606 tmplist = [] 607 obslist = self.obsoletes.keys() 608 if newest: 609 obslist = self._reduceListNewestByNameArch(obslist) 610 611 for obstup in obslist: 612 for rpmtup in self.obsoletes[obstup]: 613 tmplist.append((obstup, rpmtup)) 614 615 # self.reduceListByNameArch() for double tuples 616 returnlist = [] 617 if name or arch: 618 for ((n, a, e, v, r), insttup) in tmplist: 619 if name: 620 if name == n: 621 returnlist.append(((n, a, e, v, r), insttup)) 622 continue 623 if arch: 624 if arch == a: 625 returnlist.append(((n, a, e, v, r), insttup)) 626 continue 627 else: 628 returnlist = tmplist 629 630 return returnlist
631 632 # NOTE: This returns _obsoleters_, and narrows based on that (unlike 633 # getObsoletesTuples, but like getObsoletersTuples)
634 - def getObsoletesList(self, newest=0, name=None, arch=None):
635 """returns obsoleting packages in a list of naevr tuples of just the 636 packages that obsolete something that is installed. You can specify 637 name and/or arch of the obsoleting packaging to narrow the results. 638 You can also specify newest=1 to get the set of newest pkgs (name, arch) 639 sorted, that obsolete something""" 640 641 tmplist = self.obsoletes.keys() 642 if newest: 643 tmplist = self._reduceListNewestByNameArch(tmplist) 644 645 returnlist = self.reduceListByNameArch(tmplist, name, arch) 646 647 return returnlist
648
649 - def getObsoletedList(self, newest=0, name=None):
650 """returns a list of pkgtuples obsoleting the package in name""" 651 returnlist = [] 652 for new in self.obsoletes: 653 for obstup in self.obsoletes[new]: 654 (n, a, e, v, r) = obstup 655 if n == name: 656 returnlist.append(new) 657 continue 658 return returnlist
659 660 661
662 - def getOthersList(self, name=None, arch=None):
663 """returns a naevr tuple of the packages that are neither installed 664 nor an update - this may include something that obsoletes an installed 665 package""" 666 updates = {} 667 inst = {} 668 tmplist = [] 669 670 for pkgtup in self.getUpdatesList(): 671 updates[pkgtup] = 1 672 673 for pkgtup in self.installed: 674 inst[pkgtup] = 1 675 676 for pkgtup in self.available: 677 if pkgtup not in updates and pkgtup not in inst: 678 tmplist.append(pkgtup) 679 680 returnlist = self.reduceListByNameArch(tmplist, name, arch) 681 682 return returnlist
683 684 685
686 - def _reduceListNewestByNameArch(self, tuplelist):
687 """return list of newest packages based on name, arch matching 688 this means(in name.arch form): foo.i386 and foo.noarch are not 689 compared to each other for highest version only foo.i386 and 690 foo.i386 will be compared""" 691 highdict = {} 692 for pkgtup in tuplelist: 693 (n, a, e, v, r) = pkgtup 694 if not highdict.has_key((n, a)): 695 highdict[(n, a)] = pkgtup 696 else: 697 pkgtup2 = highdict[(n, a)] 698 (n2, a2, e2, v2, r2) = pkgtup2 699 rc = rpmUtils.miscutils.compareEVR((e,v,r), (e2, v2, r2)) 700 if rc > 0: 701 highdict[(n, a)] = pkgtup 702 703 return highdict.values()
704 705 706 # def getProblems(self): 707 # """return list of problems: 708 # - Packages that are both obsoleted and updated. 709 # - Packages that have multiple obsoletes. 710 # - Packages that _still_ have multiple updates 711 # """ 712