1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 Dependency resolution module for yum.
19 """
20
21 import os.path
22 import types
23 import logging
24
25 import rpmUtils.transaction
26 import rpmUtils.miscutils
27 from rpmUtils.arch import archDifference, canCoinstall
28 import misc
29 from misc import unique, version_tuple_to_string
30 import rpm
31
32 from packageSack import ListPackageSack
33 from constants import *
34 import packages
35 import logginglevels
36 import Errors
37 import warnings
38 warnings.simplefilter("ignore", Errors.YumFutureDeprecationWarning)
39
40 from yum import _
41
42 try:
43 assert max(2, 4) == 4
44 except:
45
46 - def min(x, *args):
47 for y in args:
48 if x > y: x = y
49 return x
51 for y in args:
52 if x < y: x = y
53 return x
54 flags = {"GT": rpm.RPMSENSE_GREATER,
55 "GE": rpm.RPMSENSE_EQUAL | rpm.RPMSENSE_GREATER,
56 "LT": rpm.RPMSENSE_LESS,
57 "LE": rpm.RPMSENSE_LESS | rpm.RPMSENSE_EQUAL,
58 "EQ": rpm.RPMSENSE_EQUAL,
59 None: 0 }
62
63 """
64 Dependency resolving class.
65 """
66
68 packages.base = self
69 self._ts = None
70 self._tsInfo = None
71 self.dsCallback = None
72 self.logger = logging.getLogger("yum.Depsolve")
73 self.verbose_logger = logging.getLogger("yum.verbose.Depsolve")
74
75 self.path = []
76 self.loops = []
77
78 self.installedFileRequires = None
79 self.installedUnresolvedFileRequires = None
80
85
86 - def _getTs(self, remove_only=False):
87 """setup all the transaction set storage items we'll need
88 This can't happen in __init__ b/c we don't know our installroot
89 yet"""
90
91 if self._tsInfo != None and self._ts != None:
92 if not remove_only and self._tsInfo.pkgSack is None:
93 self._tsInfo.setDatabases(self.rpmdb, self.pkgSack)
94 return
95
96 if not self.conf.installroot:
97 raise Errors.YumBaseError, _('Setting up TransactionSets before config class is up')
98
99 self._getTsInfo(remove_only)
100 self.initActionTs()
101
118
121
124
126 if not self._ts:
127 self.initActionTs()
128 return self._ts
129
130
132 """sets up the ts we'll use for all the work"""
133
134 self._ts = rpmUtils.transaction.TransactionWrapper(self.conf.installroot)
135 ts_flags_to_rpm = { 'noscripts': rpm.RPMTRANS_FLAG_NOSCRIPTS,
136 'notriggers': rpm.RPMTRANS_FLAG_NOTRIGGERS,
137 'nodocs': rpm.RPMTRANS_FLAG_NODOCS,
138 'test': rpm.RPMTRANS_FLAG_TEST,
139 'justdb': rpm.RPMTRANS_FLAG_JUSTDB,
140 'repackage': rpm.RPMTRANS_FLAG_REPACKAGE}
141
142 self._ts.setFlags(0)
143
144 for flag in self.conf.tsflags:
145 if flag in ts_flags_to_rpm:
146 self._ts.addTsFlag(ts_flags_to_rpm[flag])
147 else:
148 self.logger.critical(_('Invalid tsflag in config file: %s'), flag)
149
150 probfilter = 0
151 for flag in self.tsInfo.probFilterFlags:
152 probfilter |= flag
153 self._ts.setProbFilter(probfilter)
154
163
165 """takes a packageObject, returns 1 or 0 depending on if the package
166 should/can be installed multiple times with different vers
167 like kernels and kernel modules, for example"""
168
169 iopkgs = set(self.conf.installonlypkgs)
170 if po.name in iopkgs:
171 return True
172
173 for prov in po.provides_names:
174 if prov in iopkgs:
175 return True
176
177 return False
178
180 """take transactionData class and populate transaction set"""
181
182 if self.dsCallback: self.dsCallback.transactionPopulation()
183 ts_elem = {}
184
185 if self.ts.ts is None:
186 self.initActionTs()
187
188 if keepold:
189 for te in self.ts:
190 epoch = te.E()
191 if epoch is None:
192 epoch = '0'
193 pkginfo = (te.N(), te.A(), epoch, te.V(), te.R())
194 if te.Type() == 1:
195 mode = 'i'
196 elif te.Type() == 2:
197 mode = 'e'
198
199 ts_elem[(pkginfo, mode)] = 1
200
201 for txmbr in self.tsInfo.getMembers():
202 self.verbose_logger.log(logginglevels.DEBUG_3, _('Member: %s'), txmbr)
203 if txmbr.ts_state in ['u', 'i']:
204 if (txmbr.pkgtup, 'i') in ts_elem:
205 continue
206 rpmfile = txmbr.po.localPkg()
207 if os.path.exists(rpmfile):
208 hdr = txmbr.po.returnHeaderFromPackage()
209 else:
210 self.downloadHeader(txmbr.po)
211 hdr = txmbr.po.returnLocalHeader()
212
213 if txmbr.ts_state == 'u':
214 if self.allowedMultipleInstalls(txmbr.po):
215 self.verbose_logger.log(logginglevels.DEBUG_2,
216 _('%s converted to install'), txmbr.po)
217 txmbr.ts_state = 'i'
218 txmbr.output_state = TS_INSTALL
219
220
221 self.ts.addInstall(hdr, (hdr, rpmfile), txmbr.ts_state)
222 self.verbose_logger.log(logginglevels.DEBUG_1,
223 _('Adding Package %s in mode %s'), txmbr.po, txmbr.ts_state)
224 if self.dsCallback:
225 self.dsCallback.pkgAdded(txmbr.pkgtup, txmbr.ts_state)
226
227 elif txmbr.ts_state in ['e']:
228 if (txmbr.pkgtup, txmbr.ts_state) in ts_elem:
229 continue
230 self.ts.addErase(txmbr.po.idx)
231 if self.dsCallback: self.dsCallback.pkgAdded(txmbr.pkgtup, 'e')
232 self.verbose_logger.log(logginglevels.DEBUG_1,
233 _('Removing Package %s'), txmbr.po)
234
236 """ Call the callback for processing requires, call the nicest one
237 available. """
238 if not self.dsCallback:
239 return
240
241 if hasattr(self.dsCallback, 'procReqPo'):
242 self.dsCallback.procReqPo(po, niceformatneed)
243 else:
244 self.dsCallback.procReq(po.name, niceformatneed)
245
247 """processes a Requires dep from the resolveDeps functions, returns a tuple
248 of (CheckDeps, missingdep, conflicts, errors) the last item is an array
249 of error messages"""
250
251 errormsgs = []
252
253 needname, flags, needversion = requirement
254 niceformatneed = rpmUtils.miscutils.formatRequire(needname, needversion, flags)
255 self.verbose_logger.log(logginglevels.DEBUG_1, _('%s requires: %s'), po, niceformatneed)
256 self._dscb_procReq(po, niceformatneed)
257
258 try:
259 if po.repo.id != "installed":
260 CheckDeps, missingdep = self._requiringFromTransaction(po, requirement, errormsgs)
261 else:
262 CheckDeps, missingdep = self._requiringFromInstalled(po, requirement, errormsgs)
263
264
265 if missingdep:
266 self.po_with_problems.add((po,self._working_po,errormsgs[-1]))
267
268
269 except Errors.DepError,e:
270
271
272
273
274
275 self.po_with_problems.add((po,self._working_po,str(e)))
276 CheckDeps = 1
277 missingdep = 0
278
279 return (CheckDeps, missingdep, errormsgs)
280
281 @staticmethod
284
287
289 if hasattr(self.dsCallback, 'format_missing_requires'):
290 msg = self.dsCallback.format_missing_requires(reqPo, reqTup)
291 if msg is not None:
292 return self.dsCallback.format_missing_requires(reqPo, reqTup)
293 (needname, needflags, needversion) = reqTup
294 ui_req = rpmUtils.miscutils.formatRequire(needname, needversion,
295 needflags)
296 return _('%s requires %s') % (reqPo, ui_req)
297
299 """processes the dependency resolution for a dep where the requiring
300 package is installed"""
301
302 checkdeps = 0
303 missingdep = 0
304
305 if self.tsInfo.getMembersWithState(requiringPo.pkgtup, TS_REMOVE_STATES):
306 return checkdeps, missingdep
307
308 name, arch, epoch, ver, rel = requiringPo.pkgtup
309
310 needname, needflags, needversion = requirement
311 niceformatneed = rpmUtils.miscutils.formatRequire(needname, needversion, needflags)
312
313
314
315
316
317
318 needmode = None
319 needpo = None
320 providers = []
321
322 if (needname, needflags, needversion) in self.cheaterlookup:
323 self.verbose_logger.log(logginglevels.DEBUG_2, _('Needed Require has already been looked up, cheating'))
324 cheater_po = self.cheaterlookup[(needname, needflags, needversion)]
325 providers = [cheater_po]
326
327 elif self.rpmdb.contains(name=needname):
328 txmbrs = self.tsInfo.matchNaevr(name=needname)
329 for txmbr in txmbrs:
330 providers.append(txmbr.po)
331
332 else:
333 self.verbose_logger.log(logginglevels.DEBUG_2, _('Needed Require is not a package name. Looking up: %s'), niceformatneed)
334 providers = self.rpmdb.getProvides(needname, needflags, needversion)
335
336 for inst_po in providers:
337 inst_str = '%s.%s %s:%s-%s' % inst_po.pkgtup
338 (i_n, i_a, i_e, i_v, i_r) = inst_po.pkgtup
339 self.verbose_logger.log(logginglevels.DEBUG_2,
340 _('Potential Provider: %s'), inst_str)
341 thismode = self.tsInfo.getMode(name=i_n, arch=i_a,
342 epoch=i_e, ver=i_v, rel=i_r)
343
344 if thismode is None and i_n in self.conf.exactarchlist:
345
346 thismode = self.tsInfo.getMode(name=i_n, arch=i_a)
347
348 if thismode is None and i_n not in self.conf.exactarchlist:
349
350 thismode = self.tsInfo.getMode(name=i_n)
351
352
353
354 if thismode is None:
355 if filter(lambda x: x.obsoleted_by,
356 self.tsInfo.matchNaevr(i_n, i_a, i_e, i_v, i_r)):
357 thismode = 'u'
358
359 if thismode is not None:
360 needmode = thismode
361
362 self.cheaterlookup[(needname, needflags, needversion)] = inst_po
363 self.verbose_logger.log(logginglevels.DEBUG_2, _('Mode is %s for provider of %s: %s'),
364 needmode, niceformatneed, inst_str)
365 break
366
367 self.verbose_logger.log(logginglevels.DEBUG_2, _('Mode for pkg providing %s: %s'),
368 niceformatneed, needmode)
369
370 if needmode in ['e']:
371 self.verbose_logger.log(logginglevels.DEBUG_2, _('TSINFO: %s package requiring %s marked as erase'),
372 requiringPo, needname)
373 txmbr = self.tsInfo.addErase(requiringPo)
374 txmbr.setAsDep(po=inst_po)
375 checkdeps = 1
376
377 if needmode in ['i', 'u']:
378 length = len(self.tsInfo)
379 self.update(name=name, epoch=epoch, version=ver, release=rel,
380 requiringPo=requiringPo)
381 txmbrs = self.tsInfo.getMembersWithState(requiringPo.pkgtup, TS_REMOVE_STATES)
382 if len(self.tsInfo) != length and txmbrs:
383 if txmbrs[0].output_state == TS_OBSOLETED:
384 self.verbose_logger.log(logginglevels.DEBUG_2, _('TSINFO: Obsoleting %s with %s to resolve dep.'),
385 requiringPo, txmbrs[0].obsoleted_by[0])
386 else:
387 self.verbose_logger.log(logginglevels.DEBUG_2, _('TSINFO: Updating %s to resolve dep.'), requiringPo)
388
389
390 for pkg in txmbrs[0].updated_by:
391 if requirement in map(self._prco_req2req, pkg.returnPrco('requires')):
392 return True, missingdep + self._requiringFromTransaction(pkg, requirement, errorlist)[1]
393 checkdeps = True
394 return checkdeps, missingdep
395 self.verbose_logger.log(logginglevels.DEBUG_2, _('Cannot find an update path for dep for: %s'), niceformatneed)
396 return self._requiringFromTransaction(requiringPo, requirement, errorlist)
397
398
399 if needmode is None:
400 reqpkg = (name, ver, rel, None)
401 if self.pkgSack is None:
402 return self._requiringFromTransaction(requiringPo, requirement, errorlist)
403 else:
404 msg = self._err_missing_requires(requiringPo, requirement)
405 self.verbose_logger.log(logginglevels.DEBUG_2, msg)
406 checkdeps = 0
407 missingdep = 1
408 errorlist.append(msg)
409
410 return checkdeps, missingdep
411
413 if self._last_req is None:
414 return False
415
416 if flags == 0:
417 flags = None
418 if type(version) in (types.StringType, types.NoneType, types.UnicodeType):
419 (r_e, r_v, r_r) = rpmUtils.miscutils.stringToVersion(version)
420 elif type(version) in (types.TupleType, types.ListType):
421 (r_e, r_v, r_r) = version
422
423
424 po = self._last_req
425 if po.checkPrco('provides', (name, flags, (r_e, r_v, r_r))):
426 self.verbose_logger.debug(_('Quick matched %s to require for %s'), po, name)
427 return True
428 return False
429
431 """processes the dependency resolution for a dep where requiring
432 package is in the transaction set"""
433
434 (name, arch, epoch, version, release) = requiringPo.pkgtup
435 (needname, needflags, needversion) = requirement
436 checkdeps = 0
437 missingdep = 0
438 upgraded = {}
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460 if self._quickWhatProvides(needname, needflags, needversion):
461 return checkdeps, missingdep
462
463 provSack = self.whatProvides(needname, needflags, needversion)
464
465
466 for pkg in provSack.returnPackages():
467 if self.rpmdb.contains(po=pkg):
468 self.verbose_logger.log(logginglevels.DEBUG_2, _('%s is in providing packages but it is already installed, removing.'), pkg)
469 provSack.delPackage(pkg)
470 continue
471
472
473
474
475
476
477 tspkgs = []
478 if not self.allowedMultipleInstalls(pkg):
479
480 tspkgs = self.tsInfo.matchNaevr(name=pkg.name)
481 for tspkg in tspkgs:
482 if not canCoinstall(pkg.arch, tspkg.po.arch):
483 if tspkg.po.verGT(pkg):
484 msg = _('Potential resolving package %s has newer instance in ts.') % pkg
485 self.verbose_logger.log(logginglevels.DEBUG_2, msg)
486 provSack.delPackage(pkg)
487 continue
488 elif tspkg.po.verLT(pkg):
489 upgraded.setdefault(pkg.pkgtup, []).append(tspkg.pkgtup)
490
491
492 dbpkgs = self.rpmdb.searchNevra(name=pkg.name)
493 for dbpkg in dbpkgs:
494 if dbpkg.verGT(pkg) and not canCoinstall(pkg.arch, dbpkg.arch):
495 msg = _('Potential resolving package %s has newer instance installed.') % pkg
496 self.verbose_logger.log(logginglevels.DEBUG_2, msg)
497 provSack.delPackage(pkg)
498 continue
499
500 if len(provSack) == 0:
501 missingdep = 1
502 msg = self._err_missing_requires(requiringPo, requirement)
503 errorlist.append(msg)
504 return checkdeps, missingdep
505
506
507
508 for pkg in provSack.returnPackages():
509 (n,a,e,v,r) = pkg.pkgtup
510 pkgmode = self.tsInfo.getMode(name=n, arch=a, epoch=e, ver=v, rel=r)
511 if pkgmode in ['i', 'u']:
512 self.verbose_logger.log(logginglevels.DEBUG_2,
513 _('%s already in ts, skipping this one'), pkg)
514
515
516 self._last_req = pkg
517 return checkdeps, missingdep
518
519
520
521
522 for pkg in provSack.returnNewestByName():
523 results = self.update(requiringPo=requiringPo, name=pkg.name,
524 epoch=pkg.epoch, version=pkg.version,
525 rel=pkg.rel)
526 for txmbr in results:
527 if pkg == txmbr.po:
528 checkdeps = True
529 self._last_req = pkg
530 return checkdeps, missingdep
531
532 pkgs = provSack.returnPackages()
533 if len(pkgs) == 1:
534 best = pkgs[0]
535 else:
536
537
538
539 pkgresults = self._compare_providers(pkgs, requiringPo)
540 best = pkgresults[0][0]
541
542 if self.rpmdb.contains(po=best):
543 missingdep = 1
544 checkdeps = 0
545 msg = self._err_missing_requires(requiringPo, requirement)
546 errorlist.append(msg)
547 return checkdeps, missingdep
548
549
550
551
552
553 inst = self.rpmdb.searchNevra(name=best.name, arch=best.arch)
554 if len(inst) > 0:
555 self.verbose_logger.debug(_('TSINFO: Marking %s as update for %s') %(best,
556 requiringPo))
557
558 txmbr = self.tsInfo.addUpdate(best, inst[0])
559 txmbr.setAsDep(po=requiringPo)
560 txmbr.reason = "dep"
561 self._last_req = best
562 else:
563 self.verbose_logger.debug(_('TSINFO: Marking %s as install for %s'), best,
564 requiringPo)
565
566 txmbr = self.tsInfo.addInstall(best)
567 txmbr.setAsDep(po=requiringPo)
568 txmbr.reason = "dep"
569 self._last_req = best
570
571
572
573
574 if best.pkgtup in upgraded:
575 map(self.tsInfo.remove, upgraded[best.pkgtup])
576
577 checkdeps = 1
578
579 return checkdeps, missingdep
580
582 """ Call the callback for processing requires, call the nicest one
583 available. """
584 if not self.dsCallback:
585 return
586
587 if hasattr(self.dsCallback, 'procConflictPo'):
588 self.dsCallback.procConflictPo(po, niceformatneed)
589 else:
590 self.dsCallback.procConflict(po.name, niceformatneed)
591
593 """processes a Conflict dep from the resolveDeps() method"""
594
595 CheckDeps = True
596 errormsgs = []
597
598 needname, flags, needversion = conflict
599 (name, arch, epoch, ver, rel) = po.pkgtup
600
601 niceformatneed = rpmUtils.miscutils.formatRequire(needname, needversion, flags)
602 self._dscb_procConflict(po, niceformatneed)
603
604 length = len(self.tsInfo)
605 if flags & rpm.RPMSENSE_LESS:
606 self.update(name=conflicting_po.name)
607 txmbrs = self.tsInfo.getMembersWithState(conflicting_po.pkgtup, TS_REMOVE_STATES)
608 if len(self.tsInfo) != length and txmbrs:
609 return CheckDeps, errormsgs
610 elif flags & rpm.RPMSENSE_GREATER:
611 self.update(name=name)
612 txmbrs = self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES)
613 if len(self.tsInfo) != length and txmbrs:
614 return CheckDeps, errormsgs
615
616 self.update(name=conflicting_po.name)
617 txmbrs = self.tsInfo.getMembersWithState(conflicting_po.pkgtup, TS_REMOVE_STATES)
618 if len(self.tsInfo) != length and txmbrs:
619 return CheckDeps, errormsgs
620 self.update(name=name)
621 txmbrs = self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES)
622 if len(self.tsInfo) != length and txmbrs:
623 return CheckDeps, errormsgs
624
625 msg = '%s conflicts with %s' % (name, conflicting_po.name)
626 errormsgs.append(msg)
627 self.verbose_logger.log(logginglevels.DEBUG_1, msg)
628 CheckDeps = False
629 self.po_with_problems.add((po,None,errormsgs[-1]))
630 return CheckDeps, errormsgs
631
633
634 for txmbr in self.tsInfo:
635 if txmbr.isDep:
636 self.tsInfo.remove(txmbr.pkgtup)
637
639 fn = "anaconda.prof.0"
640 import hotshot, hotshot.stats
641 prof = hotshot.Profile(fn)
642 rc = prof.runcall(self.resolveDeps)
643 prof.close()
644 print "done running depcheck"
645 stats = hotshot.stats.load(fn)
646 stats.strip_dirs()
647 stats.sort_stats('time', 'calls')
648 stats.print_stats(20)
649 return rc
650
652 import cProfile, pstats
653 prof = cProfile.Profile()
654 rc = prof.runcall(self.resolveDeps)
655 prof.dump_stats("yumprof")
656 print "done running depcheck"
657
658 p = pstats.Stats('yumprof')
659 p.strip_dirs()
660 p.sort_stats('time')
661 p.print_stats(20)
662 return rc
663
665
666 if not len(self.tsInfo):
667 return (0, [_('Success - empty transaction')])
668
669 self.po_with_problems = set()
670 self._working_po = None
671 self._last_req = None
672 self.tsInfo.resetResolved(hard=False)
673
674 CheckDeps = True
675 CheckRemoves = full_check
676 CheckInstalls = full_check
677
678 missingdep = 0
679 errors = []
680
681 if self.dsCallback: self.dsCallback.start()
682
683 while True:
684
685 CheckDeps = True
686
687
688 while CheckDeps:
689 self.cheaterlookup = {}
690 if self.dsCallback: self.dsCallback.tscheck()
691 CheckDeps, checkinstalls, checkremoves, missing = self._resolveRequires(errors)
692 CheckInstalls |= checkinstalls
693 CheckRemoves |= checkremoves
694
695
696
697 if CheckRemoves:
698 CheckRemoves = False
699 for po, dep in self._checkFileRequires():
700 (checkdep, missing, errormsgs) = self._processReq(po, dep)
701 CheckDeps |= checkdep
702 errors += errormsgs
703
704 if CheckDeps:
705 if self.dsCallback: self.dsCallback.restartLoop()
706 self.verbose_logger.log(logginglevels.DEBUG_1, _('Restarting Loop'))
707 continue
708
709
710 if CheckInstalls:
711 CheckInstalls = False
712 for conflict in self._checkConflicts():
713 (checkdep, errormsgs) = self._processConflict(*conflict)
714 CheckDeps |= checkdep
715 errors += errormsgs
716 if checkdep:
717 break
718
719 if CheckDeps:
720 if self.dsCallback: self.dsCallback.restartLoop()
721 self.verbose_logger.log(logginglevels.DEBUG_1, _('Restarting Loop'))
722 continue
723
724 break
725
726
727 for txmbr in self.tsInfo.getMembers():
728 if self.allowedMultipleInstalls(txmbr.po) and \
729 txmbr.ts_state == 'u':
730 self.verbose_logger.log(logginglevels.DEBUG_2,
731 _('%s converted to install'),
732 txmbr.po)
733 txmbr.ts_state = 'i'
734 txmbr.output_state = TS_INSTALL
735
736 if self.dsCallback: self.dsCallback.end()
737 self.verbose_logger.log(logginglevels.DEBUG_1, _('Dependency Process ending'))
738
739 self.tsInfo.changed = False
740 if len(errors) > 0:
741 errors = unique(errors)
742
743
744
745 done = set()
746 for po,wpo,err in self.po_with_problems:
747 if (po,err) in done:
748 continue
749 done.add((po, err))
750 self.verbose_logger.log(logginglevels.DEBUG_4,
751 _("%s from %s has depsolving problems") % (po, po.repoid))
752 err = err.replace('\n', '\n --> ')
753 self.verbose_logger.log(logginglevels.DEBUG_4," --> %s" % err)
754 return (1, errors)
755
756 if len(self.tsInfo) > 0:
757 if not len(self.tsInfo):
758 return (0, [_('Success - empty transaction')])
759 return (2, [_('Success - deps resolved')])
760
762 any_missing = False
763 CheckDeps = False
764 CheckInstalls = False
765 CheckRemoves = False
766
767
768 for txmbr in self.tsInfo.getUnresolvedMembers():
769
770 if self.dsCallback and txmbr.ts_state:
771 self.dsCallback.pkgAdded(txmbr.pkgtup, txmbr.ts_state)
772 self.verbose_logger.log(logginglevels.DEBUG_2,
773 _("Checking deps for %s") %(txmbr,))
774
775
776
777
778
779 if not txmbr.updates and txmbr.relatedto:
780 self._working_po = txmbr.relatedto[0][0]
781 else:
782 self._working_po = txmbr.po
783
784 if (txmbr.output_state in TS_INSTALL_STATES) == (txmbr.po.state != None):
785 thisneeds = self._checkInstall(txmbr)
786 CheckInstalls = True
787 else:
788 thisneeds = self._checkRemove(txmbr)
789 CheckRemoves = True
790
791 missing_in_pkg = False
792 for po, dep in thisneeds:
793 (checkdep, missing, errormsgs) = self._processReq(po, dep)
794 CheckDeps |= checkdep
795 errors += errormsgs
796 missing_in_pkg |= missing
797
798 if not missing_in_pkg:
799 self.tsInfo.markAsResolved(txmbr)
800
801 any_missing |= missing_in_pkg
802
803 return CheckDeps, CheckInstalls, CheckRemoves, any_missing
804
805 @staticmethod
807 """ Get a sort key for a package requires from most "narrow" to least,
808 this tries to ensure that if we have two reqs like
809 "libfoo = 1.2.3-4" and "foo-api" (which is also provided by
810 libxyz-foo) that we'll get just libfoo.
811 There are other similar cases this "handles"."""
812
813 mapper = {'EQ' : 1, 'LT' : 2, 'LE' : 3, 'GT' : 4, 'GE' : 5, None : 99}
814 flagscore = mapper.get(pkgtup[1], 10)
815
816
817
818
819
820
821
822
823
824
825
826
827 namescore = 0
828 if pkgtup[0].startswith("lib") and \
829 (pkgtup[0].endswith("()") or pkgtup[0].endswith("()(64bit)")):
830 namescore = 99
831
832 return (flagscore, namescore)
833
866
868 po = txmbr.po
869 provs = po.returnPrco('provides')
870
871
872
873 newpoprovs = {}
874 for newpo in txmbr.updated_by + txmbr.obsoleted_by:
875 for p in newpo.provides:
876 newpoprovs[p] = 1
877 ret = []
878
879
880
881 for prov in provs:
882 if prov[0].startswith('rpmlib('):
883 continue
884 if newpoprovs.has_key(prov):
885 continue
886
887
888 for pkg, hits in self.tsInfo.getRequires(*prov).iteritems():
889 for hit in hits:
890
891 found = False
892 for newpo in txmbr.updated_by:
893 if newpo.checkPrco('provides', hit):
894 found = True
895 break
896 if found: continue
897 for newpo in txmbr.obsoleted_by:
898 if newpo.checkPrco('provides', hit):
899 found = True
900 break
901 if found: continue
902
903
904 rn, rf, rv = hit
905 if not self.tsInfo.getProvides(rn, rf, rv):
906 ret.append( (pkg, self._prco_req_nfv2req(rn, rf, rv)) )
907 return ret
908
910 fileRequires = set()
911 nfileRequires = set()
912 reverselookup = {}
913 ret = []
914
915
916 if self.installedFileRequires is None:
917 self.installedFileRequires, \
918 self.installedUnresolvedFileRequires, \
919 self.installedFileProviders = self.rpmdb.fileRequiresData()
920
921
922 todel = []
923 for pkgtup, files in self.installedFileRequires.iteritems():
924 if self._tsInfo.getMembersWithState(pkgtup, output_states=TS_REMOVE_STATES):
925 todel.append(pkgtup)
926 else:
927 fileRequires.update(files)
928 for filename in files:
929 reverselookup.setdefault(filename, []).append(pkgtup)
930 for pkgtup in todel:
931 del self.installedFileRequires[pkgtup]
932
933 fileRequires -= self.installedUnresolvedFileRequires
934
935
936 for txmbr in self._tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES):
937 for name, flag, evr in txmbr.po.requires:
938 if name.startswith('/'):
939 pt = txmbr.po.pkgtup
940 self.installedFileRequires.setdefault(pt, []).append(name)
941
942 if name in self.installedUnresolvedFileRequires:
943 already_broken = False
944 for oldpo in txmbr.updates:
945 if oldpo.checkPrco('requires', (name, None, (None, None, None))):
946 already_broken = True
947 break
948 if already_broken:
949 continue
950 if name not in fileRequires:
951 nfileRequires.add(name)
952 fileRequires.add(name)
953 reverselookup.setdefault(name, []).append(txmbr.po.pkgtup)
954
955 todel = []
956 for fname in self.installedFileProviders:
957 niFP_fname = []
958 for pkgtup in self.installedFileProviders[fname]:
959 if self._tsInfo.getMembersWithState(pkgtup, output_states=TS_REMOVE_STATES):
960 continue
961 niFP_fname.append(pkgtup)
962
963 if not niFP_fname:
964 todel.append(fname)
965 continue
966
967 self.installedFileProviders[fname] = niFP_fname
968 for fname in todel:
969 del self.installedFileProviders[fname]
970
971
972 iFP = self.installedFileProviders
973 for filename in fileRequires:
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988 if filename in self.installedFileProviders:
989 continue
990
991 oprov = self.tsInfo.getOldProvides(filename)
992 if oprov:
993 iFP.setdefault(filename, []).extend([po.pkgtup for po in oprov])
994 continue
995
996 nprov = self.tsInfo.getNewProvides(filename)
997 if nprov:
998 iFP.setdefault(filename, []).extend([po.pkgtup for po in nprov])
999 continue
1000
1001 for pkgtup in reverselookup[filename]:
1002 po = self.tsInfo.getMembersWithState(pkgtup, TS_INSTALL_STATES)
1003 if po:
1004 po = po[0].po
1005 else:
1006 po = self.getInstalledPackageObject(pkgtup)
1007 ret.append( (po, (filename, 0, '')) )
1008
1009 self.rpmdb.transactionCacheFileRequires(self.installedFileRequires,
1010 self.installedUnresolvedFileRequires,
1011 self.installedFileProviders,
1012 ret)
1013
1014 return ret
1015
1017 ret = [ ]
1018 cpkgs = []
1019 for po in self.rpmdb.returnConflictPackages():
1020 if self.tsInfo.getMembersWithState(po.pkgtup, output_states=TS_REMOVE_STATES):
1021 continue
1022 cpkgs.append(po)
1023 for conflict in po.returnPrco('conflicts'):
1024 (r, f, v) = conflict
1025 for conflicting_po in self.tsInfo.getNewProvides(r, f, v):
1026 if conflicting_po.pkgtup[0] == po.pkgtup[0] and conflicting_po.pkgtup[2:] == po.pkgtup[2:]:
1027 continue
1028 ret.append( (po, self._prco_req_nfv2req(r, f, v),
1029 conflicting_po) )
1030 for txmbr in self.tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES):
1031 po = txmbr.po
1032 done = False
1033 for conflict in txmbr.po.returnPrco('conflicts'):
1034 if not done:
1035 cpkgs.append(txmbr.po)
1036 done = True
1037 (r, f, v) = conflict
1038 for conflicting_po in self.tsInfo.getProvides(r, f, v):
1039 if conflicting_po.pkgtup[0] == po.pkgtup[0] and conflicting_po.pkgtup[2:] == po.pkgtup[2:]:
1040 continue
1041 ret.append( (po, self._prco_req_nfv2req(r, f, v),
1042 conflicting_po) )
1043 self.rpmdb.transactionCacheConflictPackages(cpkgs)
1044 return ret
1045
1047 lst = self.tsInfo.matchNaevr(name = pkgname)
1048 for txmbr in lst:
1049 if txmbr.output_state in TS_INSTALL_STATES:
1050 return True
1051
1052 if len(lst) > 0:
1053
1054
1055 return False
1056
1057 if not self.rpmdb.contains(name=pkgname):
1058 return False
1059
1060 return True
1061 _isPackageInstalled = isPackageInstalled
1062
1064 """take the list of pkgs and score them based on the requesting package
1065 return a dictionary of po=score"""
1066 self.verbose_logger.log(logginglevels.DEBUG_4,
1067 _("Running compare_providers() for %s") %(str(pkgs)))
1068
1069 def _common_prefix_len(x, y, minlen=2):
1070 num = min(len(x), len(y))
1071 for off in range(num):
1072 if x[off] != y[off]:
1073 return max(off, minlen)
1074 return max(num, minlen)
1075
1076 def _common_sourcerpm(x, y):
1077 if not hasattr(x, 'sourcerpm'):
1078 return False
1079 if not hasattr(y, 'sourcerpm'):
1080 return False
1081 return x.sourcerpm == y.sourcerpm
1082
1083 def _compare_arch_distance(x, y, req_compare_arch):
1084
1085
1086
1087
1088
1089
1090 x_dist = archDifference(req_compare_arch, x.arch)
1091 if self.arch.multilib:
1092 if x_dist == 0:
1093 self.verbose_logger.log(logginglevels.DEBUG_4,
1094 _("better arch in po %s") %(y))
1095 return y
1096
1097 y_dist = archDifference(req_compare_arch, y.arch)
1098 if y_dist > 0 and x_dist > y_dist:
1099 self.verbose_logger.log(logginglevels.DEBUG_4,
1100 _("better arch in po %s") %(y))
1101
1102 return y
1103 if y_dist == x_dist:
1104 return None
1105 return x
1106
1107
1108
1109
1110 unique_nevra_pkgs = {}
1111 for pkg in pkgs:
1112 if (pkg.pkgtup in unique_nevra_pkgs and
1113 unique_nevra_pkgs[pkg.pkgtup].repo <= pkg.repo):
1114 continue
1115 unique_nevra_pkgs[pkg.pkgtup] = pkg
1116 pkgs = unique_nevra_pkgs.values()
1117
1118 pkgresults = {}
1119 ipkgresults = {}
1120
1121 for pkg in pkgs:
1122 pkgresults[pkg] = 0
1123
1124 rpmdbpkgs = self.rpmdb.searchNevra(name=pkg.name)
1125 if rpmdbpkgs:
1126
1127
1128
1129
1130 newest = sorted(rpmdbpkgs)[-1]
1131 if newest.verLT(pkg):
1132
1133
1134
1135
1136
1137 ipkgresults[pkg] = 5
1138 else:
1139
1140
1141 ipkgresults[pkg] = 0
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151 if ipkgresults:
1152 pkgresults = ipkgresults
1153 pkgs = ipkgresults.keys()
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173 lpos = {}
1174 for po in pkgs:
1175 for nextpo in pkgs:
1176 if po == nextpo:
1177 continue
1178
1179
1180
1181
1182
1183 if po.name not in lpos:
1184 lpos[po.name] = self.pkgSack.returnNewestByName(po.name)[:1]
1185 if not lpos[po.name] or not po.verEQ(lpos[po.name][0]):
1186 pkgresults[po] -= 1024
1187
1188 obsoleted = False
1189 poprovtup = (po.name, 'EQ', (po.epoch, po.ver, po.release))
1190 if nextpo.inPrcoRange('obsoletes', poprovtup):
1191 obsoleted = True
1192 pkgresults[po] -= 1024
1193
1194 self.verbose_logger.log(logginglevels.DEBUG_4,
1195 _("%s obsoletes %s") % (nextpo, po))
1196
1197 if reqpo:
1198 arches = (reqpo.arch, self.arch.bestarch)
1199 else:
1200 arches = (self.arch.bestarch,)
1201
1202 for thisarch in arches:
1203 res = _compare_arch_distance(po, nextpo, thisarch)
1204 if not res:
1205 continue
1206 self.verbose_logger.log(logginglevels.DEBUG_4,
1207 _('archdist compared %s to %s on %s\n Winner: %s' % (po, nextpo, thisarch, res)))
1208
1209 if res == po:
1210 pkgresults[po] += 5
1211
1212 if _common_sourcerpm(po, reqpo):
1213 self.verbose_logger.log(logginglevels.DEBUG_4,
1214 _('common sourcerpm %s and %s' % (po, reqpo)))
1215 pkgresults[po] += 20
1216 if self.isPackageInstalled(po.base_package_name):
1217 self.verbose_logger.log(logginglevels.DEBUG_4,
1218 _('base package %s is installed for %s' % (po.base_package_name, po)))
1219 pkgresults[po] += 5
1220 if reqpo:
1221 cpl = _common_prefix_len(po.name, reqpo.name)
1222 if cpl > 2:
1223 self.verbose_logger.log(logginglevels.DEBUG_4,
1224 _('common prefix of %s between %s and %s' % (cpl, po, reqpo)))
1225
1226 pkgresults[po] += cpl*2
1227
1228 pkgresults[po] += (len(po.name)*-1)
1229
1230 bestorder = sorted(pkgresults.items(),
1231 key=lambda x: (x[1], x[0]), reverse=True)
1232 self.verbose_logger.log(logginglevels.DEBUG_4,
1233 _('Best Order: %s' % str(bestorder)))
1234
1235 return bestorder
1236
1241 """object that YumDepsolver uses to see what things are needed to close
1242 the transaction set. attributes: requires, conflicts are a list of
1243 requires are conflicts in the current transaction set. Each item in the
1244 lists are a requires or conflicts object"""
1248
1250
1251 reqobj = Requires(po, req_tuple_list)
1252 self.requires.append(reqobj)
1253
1255 confobj = Conflicts(conflict_po_list, conflict_item)
1256 self.conflicts.append(confobj)
1257
1259
1260 """
1261 A pure data class for holding a package and the list of things it
1262 requires.
1263 """
1264
1268
1271
1272 """
1273 A pure data class for holding a package and the list of things it
1274 conflicts.
1275 """
1276
1277 - def __init__(self, pkglist, conflict):
1280