Package yum :: Module transactioninfo
[hide private]
[frames] | no frames]

Source Code for Module yum.transactioninfo

  1  # This program is free software; you can redistribute it and/or modify 
  2  # it under the terms of the GNU General Public License as published by 
  3  # the Free Software Foundation; either version 2 of the License, or 
  4  # (at your option) any later version. 
  5  # 
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU Library General Public License for more details. 
 10  # 
 11  # You should have received a copy of the GNU General Public License 
 12  # along with this program; if not, write to the Free Software 
 13  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 14  # Copyright 2005 Duke University 
 15  # Written by Seth Vidal 
 16   
 17  # TODOS: make all the package relationships deal with package objects 
 18  # search by package object for TransactionData, etc. 
 19  # provide a real TransactionData.remove(txmbr) method, It should  
 20  # remove the given txmbr and iterate to remove all those in depedent relationships 
 21  # with the given txmbr.  
 22   
 23  """ 
 24  Classes and functions for manipulating a transaction to be passed 
 25  to rpm. 
 26  """ 
 27   
 28  from constants import * 
 29  from packageSack import PackageSack, PackageSackVersion 
 30  from packages import YumInstalledPackage 
 31  from sqlitesack import YumAvailablePackageSqlite 
 32  import Errors 
 33  import warnings 
 34  import misc 
 35   
36 -class GetProvReqOnlyPackageSack(PackageSack):
37 - def __init__(self, need_files=False):
38 PackageSack.__init__(self) 39 self._need_index_files = need_files
40
42 for ftype in obj.returnFileTypes(): 43 for file in obj.returnFileEntries(ftype, primary_only=True): 44 self._addToDictAsList(self.filenames, file, obj)
45 - def __addPackageToIndex_files(self, obj):
46 for ftype in obj.returnFileTypes(): 47 for file in obj.returnFileEntries(ftype): 48 self._addToDictAsList(self.filenames, file, obj)
49 - def _addPackageToIndex(self, obj):
50 for (n, fl, (e,v,r)) in obj.returnPrco('provides'): 51 self._addToDictAsList(self.provides, n, obj) 52 for (n, fl, (e,v,r)) in obj.returnPrco('requires'): 53 self._addToDictAsList(self.requires, n, obj) 54 if self._need_index_files: 55 self.__addPackageToIndex_files(obj) 56 else: 57 self.__addPackageToIndex_primary_files(obj)
58
59 - def __buildFileIndexes(self):
60 for repoid in self.pkgsByRepo: 61 for obj in self.pkgsByRepo[repoid]: 62 self.__addPackageToIndex_files(obj)
63 - def searchFiles(self, name):
64 if not self._need_index_files and not misc.re_primary_filename(name): 65 self._need_index_files = True 66 if self.indexesBuilt: 67 self.filenames = {} 68 self.__buildFileIndexes() 69 70 return PackageSack.searchFiles(self, name)
71
72 -class TransactionData:
73 """Data Structure designed to hold information on a yum Transaction Set"""
74 - def __init__(self):
75 self.flags = [] 76 self.vsflags = [] 77 self.probFilterFlags = [] 78 self.root = '/' 79 self.pkgdict = {} # key = pkgtup, val = list of TransactionMember obj 80 self._namedict = {} # name -> list of TransactionMember obj 81 self._unresolvedMembers = set() 82 self.debug = 0 83 self.changed = False 84 self.installonlypkgs = [] 85 86 self.conditionals = {} # key = pkgname, val = list of pos to add 87 88 self.rpmdb = None 89 self.pkgSack = None 90 self.pkgSackPackages = 0 91 self.localSack = PackageSack() 92 # FIXME: This is turned off atm. ... it'll be turned on when 93 # the new yum-metadata-parser with the "pkgfiles" index is std. 94 self._inSack = None # GetProvReqOnlyPackageSack() 95 96 # lists of txmbrs in their states - just placeholders 97 self.instgroups = [] 98 self.removedgroups = [] 99 self.removed = [] 100 self.installed = [] 101 self.updated = [] 102 self.obsoleted = [] 103 self.depremoved = [] 104 self.depinstalled = [] 105 self.depupdated = [] 106 self.reinstalled = [] 107 self.downgraded = []
108
109 - def __len__(self):
110 return len(self.pkgdict)
111
112 - def __iter__(self):
113 if hasattr(self.getMembers(), '__iter__'): 114 return self.getMembers().__iter__() 115 else: 116 return iter(self.getMembers())
117
118 - def debugprint(self, msg):
119 if self.debug: 120 print msg
121
122 - def getMembersWithState(self, pkgtup=None, output_states=None):
123 return filter(lambda p: p.output_state in output_states, 124 self.getMembers(pkgtup))
125
126 - def getMembers(self, pkgtup=None):
127 """takes an optional package tuple and returns all transaction members 128 matching, no pkgtup means it returns all transaction members""" 129 130 returnlist = [] 131 132 if pkgtup is None: 133 for members in self.pkgdict.itervalues(): 134 returnlist.extend(members) 135 elif self.pkgdict.has_key(pkgtup): 136 returnlist.extend(self.pkgdict[pkgtup]) 137 return returnlist
138 139 # The order we resolve things in _matters_, so for sanity sort the list 140 # otherwise .i386 can be different to .x86_64 etc.
141 - def getUnresolvedMembers(self):
142 return list(sorted(self._unresolvedMembers))
143
144 - def markAsResolved(self, txmbr):
145 self._unresolvedMembers.discard(txmbr)
146
147 - def resetResolved(self, hard=False):
148 if hard or len(self) < len(self._unresolvedMembers): 149 self._unresolvedMembers.clear() 150 self._unresolvedMembers.update(self.getMembers()) 151 return True 152 return False
153
154 - def getMode(self, name=None, arch=None, epoch=None, ver=None, rel=None):
155 """returns the mode of the first match from the transaction set, 156 otherwise, returns None""" 157 158 txmbrs = self.matchNaevr(name=name, arch=arch, epoch=epoch, ver=ver, rel=rel) 159 if not len(txmbrs): 160 return None 161 states = [] 162 for txmbr in txmbrs: 163 states.append(txmbr.ts_state) 164 165 if 'u' in states: 166 return 'u' 167 elif 'i' in states: 168 return 'i' 169 else: 170 return states[0]
171
172 - def matchNaevr(self, name=None, arch=None, epoch=None, ver=None, rel=None):
173 """returns the list of packages matching the args above""" 174 if name is None: 175 txmbrs = self.getMembers() 176 else: 177 txmbrs = self._namedict.get(name, []) 178 if arch is None and epoch is None and ver is None and rel is None: 179 return txmbrs[:] 180 181 result = [] 182 183 for txmbr in txmbrs: 184 (n, a, e, v, r) = txmbr.pkgtup 185 # Name is done above 186 if arch is not None and arch != a: 187 continue 188 if epoch is not None and epoch != e: 189 continue 190 if ver is not None and ver != v: 191 continue 192 if rel is not None and rel != r: 193 continue 194 result.append(txmbr) 195 196 return result
197
198 - def _isLocalPackage(self, txmember):
199 # Is this the right criteria? 200 # FIXME: This is kinda weird, we really want all local pkgs to be in a 201 # special pkgsack before this point ... so that "yum up ./*.rpm" works. 202 # Also FakePackage() sets it off ... which is confusing and not what 203 # happens IRL. 204 return txmember.ts_state in ('u', 'i') and not isinstance(txmember.po, (YumInstalledPackage, YumAvailablePackageSqlite))
205
206 - def _allowedMultipleInstalls(self, po):
207 """takes a packageObject, returns 1 or 0 depending on if the package 208 should/can be installed multiple times with different vers 209 like kernels and kernel modules, for example""" 210 211 if po.name in self.installonlypkgs: 212 return True 213 214 provides = po.provides_names 215 if filter (lambda prov: prov in self.installonlypkgs, provides): 216 return True 217 218 return False
219
220 - def add(self, txmember):
221 """add a package to the transaction""" 222 223 for oldpo in txmember.updates: 224 self.addUpdated(oldpo, txmember.po) 225 226 if txmember.pkgtup not in self.pkgdict: 227 self.pkgdict[txmember.pkgtup] = [] 228 else: 229 self.debugprint("Package: %s.%s - %s:%s-%s already in ts" % txmember.pkgtup) 230 for member in self.pkgdict[txmember.pkgtup]: 231 if member.ts_state == txmember.ts_state: 232 self.debugprint("Package in same mode, skipping.") 233 return 234 self.pkgdict[txmember.pkgtup].append(txmember) 235 self._namedict.setdefault(txmember.name, []).append(txmember) 236 self.changed = True 237 if self._isLocalPackage(txmember): 238 self.localSack.addPackage(txmember.po) 239 elif isinstance(txmember.po, YumAvailablePackageSqlite): 240 self.pkgSackPackages += 1 241 if self._inSack is not None and txmember.output_state in TS_INSTALL_STATES: 242 self._inSack.addPackage(txmember.po) 243 244 if self.conditionals.has_key(txmember.name): 245 for pkg in self.conditionals[txmember.name]: 246 if self.rpmdb.contains(po=pkg): 247 continue 248 for condtxmbr in self.install_method(po=pkg): 249 condtxmbr.setAsDep(po=txmember.po) 250 251 self._unresolvedMembers.add(txmember)
252
253 - def remove(self, pkgtup):
254 """remove a package from the transaction""" 255 if pkgtup not in self.pkgdict: 256 self.debugprint("Package: %s not in ts" %(pkgtup,)) 257 return 258 for txmbr in self.pkgdict[pkgtup]: 259 txmbr.po.state = None 260 if self._isLocalPackage(txmbr): 261 self.localSack.delPackage(txmbr.po) 262 elif isinstance(txmbr.po, YumAvailablePackageSqlite): 263 self.pkgSackPackages -= 1 264 if self._inSack is not None and txmbr.output_state in TS_INSTALL_STATES: 265 self._inSack.delPackage(txmbr.po) 266 self._namedict[txmbr.name].remove(txmbr) 267 self._unresolvedMembers.add(txmbr) 268 269 del self.pkgdict[pkgtup] 270 if not self._namedict[pkgtup[0]]: 271 del self._namedict[pkgtup[0]] 272 self.changed = True
273
274 - def exists(self, pkgtup):
275 """tells if the pkg is in the class""" 276 if self.pkgdict.has_key(pkgtup): 277 if len(self.pkgdict[pkgtup]) != 0: 278 return 1 279 280 return 0
281
282 - def isObsoleted(self, pkgtup):
283 """true if the pkgtup is marked to be obsoleted""" 284 if self.exists(pkgtup): 285 for txmbr in self.getMembers(pkgtup=pkgtup): 286 if txmbr.output_state == TS_OBSOLETED: 287 return True 288 289 return False
290
291 - def makelists(self, include_reinstall=False, include_downgrade=False):
292 """returns lists of transaction Member objects based on mode: 293 updated, installed, erased, obsoleted, depupdated, depinstalled 294 deperased""" 295 296 self.instgroups = [] 297 self.removedgroups = [] 298 self.removed = [] 299 self.installed = [] 300 self.updated = [] 301 self.obsoleted = [] 302 self.depremoved = [] 303 self.depinstalled = [] 304 self.depupdated = [] 305 self.reinstalled = [] 306 self.downgraded = [] 307 self.failed = [] 308 309 for txmbr in self.getMembers(): 310 if txmbr.output_state == TS_UPDATE: 311 if txmbr.isDep: 312 self.depupdated.append(txmbr) 313 else: 314 self.updated.append(txmbr) 315 316 elif txmbr.output_state in (TS_INSTALL, TS_TRUEINSTALL): 317 if include_reinstall and self.rpmdb.contains(po=txmbr.po): 318 txmbr.reinstall = True 319 self.reinstalled.append(txmbr) 320 continue 321 322 if include_downgrade and txmbr.downgrades: 323 self.downgraded.append(txmbr) 324 continue 325 326 if txmbr.groups: 327 for g in txmbr.groups: 328 if g not in self.instgroups: 329 self.instgroups.append(g) 330 if txmbr.isDep: 331 self.depinstalled.append(txmbr) 332 else: 333 self.installed.append(txmbr) 334 335 elif txmbr.output_state == TS_ERASE: 336 if include_downgrade and txmbr.downgraded_by: 337 continue 338 339 for g in txmbr.groups: 340 if g not in self.instgroups: 341 self.removedgroups.append(g) 342 if txmbr.isDep: 343 self.depremoved.append(txmbr) 344 else: 345 self.removed.append(txmbr) 346 347 elif txmbr.output_state == TS_OBSOLETED: 348 self.obsoleted.append(txmbr) 349 350 elif txmbr.output_state == TS_OBSOLETING: 351 self.installed.append(txmbr) 352 elif txmbr.output_state == TS_FAILED: 353 self.failed.append(txmbr) 354 355 else: 356 pass 357 358 self.updated.sort() 359 self.installed.sort() 360 self.removed.sort() 361 self.obsoleted.sort() 362 self.depupdated.sort() 363 self.depinstalled.sort() 364 self.depremoved.sort() 365 self.instgroups.sort() 366 self.removedgroups.sort() 367 self.reinstalled.sort() 368 self.downgraded.sort() 369 self.failed.sort()
370 371
372 - def addInstall(self, po):
373 """adds a package as an install but in mode 'u' to the ts 374 takes a packages object and returns a TransactionMember Object""" 375 376 if self._allowedMultipleInstalls(po): 377 return self.addTrueInstall(po) 378 379 txmbr = TransactionMember(po) 380 txmbr.current_state = TS_AVAILABLE 381 txmbr.output_state = TS_INSTALL 382 txmbr.po.state = TS_INSTALL 383 txmbr.ts_state = 'u' 384 txmbr.reason = 'user' 385 self.add(txmbr) 386 return txmbr
387
388 - def addTrueInstall(self, po):
389 """adds a package as an install 390 takes a packages object and returns a TransactionMember Object""" 391 392 txmbr = TransactionMember(po) 393 txmbr.current_state = TS_AVAILABLE 394 txmbr.output_state = TS_TRUEINSTALL 395 txmbr.po.state = TS_INSTALL 396 txmbr.ts_state = 'i' 397 txmbr.reason = 'user' 398 self.add(txmbr) 399 return txmbr
400 401
402 - def addErase(self, po):
403 """adds a package as an erasure 404 takes a packages object and returns a TransactionMember Object""" 405 406 txmbr = TransactionMember(po) 407 txmbr.current_state = TS_INSTALL 408 txmbr.output_state = TS_ERASE 409 txmbr.po.state = TS_INSTALL 410 txmbr.ts_state = 'e' 411 self.add(txmbr) 412 return txmbr
413
414 - def addUpdate(self, po, oldpo=None):
415 """adds a package as an update 416 takes a packages object and returns a TransactionMember Object""" 417 418 if self._allowedMultipleInstalls(po): 419 return self.addTrueInstall(po) 420 421 txmbr = TransactionMember(po) 422 txmbr.current_state = TS_AVAILABLE 423 txmbr.output_state = TS_UPDATE 424 txmbr.po.state = TS_UPDATE 425 txmbr.ts_state = 'u' 426 if oldpo: 427 txmbr.relatedto.append((oldpo, 'updates')) 428 txmbr.updates.append(oldpo) 429 430 self.add(txmbr) 431 return txmbr
432
433 - def addDowngrade(self, po, oldpo):
434 """adds a package as an downgrade takes a packages object and returns 435 a pair of TransactionMember Objects""" 436 437 itxmbr = self.addErase(oldpo) 438 itxmbr.relatedto.append((po, 'downgradedby')) 439 itxmbr.downgraded_by.append(po) 440 441 atxmbr = self.addInstall(po) 442 if not atxmbr: # Fail? 443 self.remove(itxmbr.pkgtup) 444 return None 445 atxmbr.relatedto.append((oldpo, 'downgrades')) 446 atxmbr.downgrades.append(oldpo) 447 448 return (itxmbr, atxmbr)
449
450 - def addUpdated(self, po, updating_po):
451 """adds a package as being updated by another pkg 452 takes a packages object and returns a TransactionMember Object""" 453 454 txmbr = TransactionMember(po) 455 txmbr.current_state = TS_INSTALL 456 txmbr.output_state = TS_UPDATED 457 txmbr.po.state = TS_UPDATED 458 txmbr.ts_state = None # FIXME: should use a real state here. 459 txmbr.relatedto.append((updating_po, 'updatedby')) 460 txmbr.updated_by.append(updating_po) 461 self.add(txmbr) 462 return txmbr
463
464 - def addObsoleting(self, po, oldpo):
465 """adds a package as an obsolete over another pkg 466 takes a packages object and returns a TransactionMember Object""" 467 468 txmbr = TransactionMember(po) 469 txmbr.current_state = TS_AVAILABLE 470 txmbr.output_state = TS_OBSOLETING 471 txmbr.po.state = TS_OBSOLETING 472 txmbr.ts_state = 'u' 473 txmbr.relatedto.append((oldpo, 'obsoletes')) 474 txmbr.obsoletes.append(oldpo) 475 self.add(txmbr) 476 return txmbr
477
478 - def addObsoleted(self, po, obsoleting_po):
479 """adds a package as being obsoleted by another pkg 480 takes a packages object and returns a TransactionMember Object""" 481 482 txmbr = TransactionMember(po) 483 txmbr.current_state = TS_INSTALL 484 txmbr.output_state = TS_OBSOLETED 485 txmbr.po.state = TS_OBSOLETED 486 txmbr.ts_state = None # FIXME: should use a real state here. 487 txmbr.relatedto.append((obsoleting_po, 'obsoletedby')) 488 txmbr.obsoleted_by.append(obsoleting_po) 489 self.add(txmbr) 490 for otxmbr in self.getMembersWithState(obsoleting_po.pkgtup, 491 [TS_OBSOLETING]): 492 if po in otxmbr.obsoletes: 493 continue 494 otxmbr.relatedto.append((po, 'obsoletes')) 495 otxmbr.obsoletes.append(po) 496 return txmbr
497 498
499 - def setDatabases(self, rpmdb, pkgSack):
500 self.rpmdb = rpmdb 501 self.pkgSack = pkgSack
502
503 - def getNewProvides(self, name, flag=None, version=(None, None, None)):
504 """return dict { packages -> list of matching provides } 505 searches in packages to be installed""" 506 result = { } 507 if not self.pkgSackPackages: 508 pass 509 elif self._inSack is None: 510 for pkg, hits in self.pkgSack.getProvides(name, flag, version).iteritems(): 511 if self.getMembersWithState(pkg.pkgtup, TS_INSTALL_STATES): 512 result[pkg] = hits 513 else: 514 for pkg, hits in self._inSack.getProvides(name, flag, version).iteritems(): 515 result[pkg] = hits 516 result.update(self.localSack.getProvides(name, flag, version)) 517 return result
518
519 - def getOldProvides(self, name, flag=None, version=(None, None, None)):
520 """return dict { packages -> list of matching provides } 521 searches in packages already installed and not going to be removed""" 522 result = { } 523 for pkg, hits in self.rpmdb.getProvides(name, flag, version).iteritems(): 524 if not self.getMembersWithState(pkg.pkgtup, TS_REMOVE_STATES): 525 result[pkg] = hits 526 return result
527
528 - def getProvides(self, name, flag=None, version=(None, None, None)):
529 """return dict { packages -> list of matching provides }""" 530 result = self.getOldProvides(name, flag, version) 531 result.update(self.getNewProvides(name, flag, version)) 532 return result
533
534 - def getNewRequires(self, name, flag=None, version=(None, None, None)):
535 """return dict { packages -> list of matching provides } 536 searches in packages to be installed""" 537 result = { } 538 if not self.pkgSackPackages: 539 pass 540 elif self._inSack is None: 541 for pkg, hits in self.pkgSack.getRequires(name, flag, version).iteritems(): 542 if self.getMembersWithState(pkg.pkgtup, TS_INSTALL_STATES): 543 result[pkg] = hits 544 else: 545 for pkg, hits in self._inSack.getRequires(name, flag, version).iteritems(): 546 result[pkg] = hits 547 548 result.update(self.localSack.getRequires(name, flag, version)) 549 return result
550 551
552 - def getOldRequires(self, name, flag=None, version=(None, None, None)):
553 """return dict { packages -> list of matching provides } 554 searches in packages already installed and not going to be removed""" 555 result = { } 556 for pkg, hits in self.rpmdb.getRequires(name, flag, version).iteritems(): 557 if not self.getMembersWithState(pkg.pkgtup, TS_REMOVE_STATES): 558 result[pkg] = hits 559 return result
560
561 - def getRequires(self, name, flag=None, version=(None, None, None)):
562 """return dict { packages -> list of matching provides }""" 563 result = self.getOldRequires(name, flag, version) 564 result.update(self.getNewRequires(name, flag, version)) 565 return result
566
567 - def futureRpmDBVersion(self):
568 """ Return a simple version for the future rpmdb. Works like 569 rpmdb.simpleVersion(main_only=True)[0], but for the state the rpmdb 570 will be in after the transaction. """ 571 pkgs = self.rpmdb.returnPackages() 572 _reinstalled_pkgtups = {} 573 for txmbr in self.getMembersWithState(None, TS_INSTALL_STATES): 574 # reinstalls have to use their "new" checksum data, in case it's 575 # different. 576 if hasattr(txmbr, 'reinstall') and txmbr.reinstall: 577 _reinstalled_pkgtups[txmbr.po.pkgtup] = txmbr.po 578 pkgs.append(txmbr.po) 579 580 self.rpmdb.preloadPackageChecksums() 581 main = PackageSackVersion() 582 pkg_checksum_tups = [] 583 for pkg in sorted(pkgs): 584 if pkg.repoid != 'installed': 585 # Paste from PackageSackBase.simpleVersion() 586 csum = pkg.returnIdSum() 587 main.update(pkg, csum) 588 pkg_checksum_tups.append((pkg.pkgtup, csum)) 589 continue 590 591 # Installed pkg, see if it's about to die 592 if self.getMembersWithState(pkg.pkgtup, TS_REMOVE_STATES): 593 continue 594 # ...or die and be risen again (Zombie!) 595 if pkg.pkgtup in _reinstalled_pkgtups: 596 continue 597 598 # Paste from rpmdb.simpleVersion() 599 ydbi = pkg.yumdb_info 600 csum = None 601 if 'checksum_type' in ydbi and 'checksum_data' in ydbi: 602 csum = (ydbi.checksum_type, ydbi.checksum_data) 603 pkg_checksum_tups.append((pkg.pkgtup, csum)) 604 main.update(pkg, csum) 605 606 self.rpmdb.transactionCachePackageChecksums(pkg_checksum_tups) 607 608 return main
609
610 -class ConditionalTransactionData(TransactionData):
611 """A transaction data implementing conditional package addition"""
612 - def __init__(self):
613 warnings.warn("ConditionalTransactionData will go away in a future " 614 "version of Yum.", Errors.YumFutureDeprecationWarning) 615 TransactionData.__init__(self)
616
617 -class SortableTransactionData(TransactionData):
618 """A transaction data implementing topological sort on it's members"""
619 - def __init__(self):
620 # Cache of sort 621 self._sorted = [] 622 # Current dependency path 623 self.path = [] 624 # List of loops 625 self.loops = [] 626 TransactionData.__init__(self)
627
628 - def _visit(self, txmbr):
629 self.path.append(txmbr.name) 630 txmbr.sortColour = TX_GREY 631 for po in txmbr.depends_on: 632 vertex = self.getMembers(pkgtup=po.pkgtup)[0] 633 if vertex.sortColour == TX_GREY: 634 self._doLoop(vertex.name) 635 if vertex.sortColour == TX_WHITE: 636 self._visit(vertex) 637 txmbr.sortColour = TX_BLACK 638 self._sorted.insert(0, txmbr.pkgtup)
639
640 - def _doLoop(self, name):
641 self.path.append(name) 642 loop = self.path[self.path.index(self.path[-1]):] 643 if len(loop) > 2: 644 self.loops.append(loop)
645
646 - def add(self, txmember):
647 txmember.sortColour = TX_WHITE 648 TransactionData.add(self, txmember) 649 self._sorted = []
650
651 - def remove(self, pkgtup):
652 TransactionData.remove(self, pkgtup) 653 self._sorted = []
654
655 - def sort(self):
656 if self._sorted: 657 return self._sorted 658 self._sorted = [] 659 # loop over all members 660 for txmbr in self.getMembers(): 661 if txmbr.sortColour == TX_WHITE: 662 self.path = [ ] 663 self._visit(txmbr) 664 self._sorted.reverse() 665 return self._sorted
666 667
668 -class TransactionMember:
669 """Class to describe a Transaction Member (a pkg to be installed/ 670 updated/erased).""" 671
672 - def __init__(self, po):
673 # holders for data 674 self.po = po # package object 675 self.current_state = None # where the package currently is (repo, installed) 676 self.ts_state = None # what state to put it into in the transaction set 677 self.output_state = None # what state to list if printing it 678 self.isDep = 0 679 self.reason = 'user' # reason for it to be in the transaction set 680 self.process = None # 681 self.relatedto = [] # ([relatedpkg, relationship)] 682 self.depends_on = [] 683 self.obsoletes = [] 684 self.obsoleted_by = [] 685 self.updates = [] 686 self.updated_by = [] 687 self.downgrades = [] 688 self.downgraded_by = [] 689 self.groups = [] # groups it's in 690 self._poattr = ['pkgtup', 'repoid', 'name', 'arch', 'epoch', 'version', 691 'release'] 692 693 for attr in self._poattr: 694 val = getattr(self.po, attr) 695 setattr(self, attr, val)
696
697 - def setAsDep(self, po=None):
698 """sets the transaction member as a dependency and maps the dep into the 699 relationship list attribute""" 700 701 self.isDep = 1 702 if po: 703 self.relatedto.append((po, 'dependson')) 704 self.depends_on.append(po)
705
706 - def __cmp__(self, other):
707 return cmp(self.po, other.po)
708
709 - def __hash__(self):
710 return object.__hash__(self)
711
712 - def __str__(self):
713 return "%s.%s %s:%s-%s - %s" % (self.name, self.arch, self.epoch, 714 self.version, self.release, self.ts_state)
715
716 - def __repr__(self):
717 return "<%s : %s (%s)>" % (self.__class__.__name__, str(self),hex(id(self)))
718 719 # This is the tricky part - how do we nicely setup all this data w/o going insane 720 # we could make the txmember object be created from a YumPackage base object 721 # we still may need to pass in 'groups', 'ts_state', 'output_state', 'reason', 'current_state' 722 # and any related packages. A world of fun that will be, you betcha 723 724 725 # definitions 726 # current and output states are defined in constants 727 # relationships are defined in constants 728 # ts states are: u, i, e 729