00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <map>
00023 #include <sstream>
00024
00025 #include "zypp/solver/detail/Resolver.h"
00026 #include "zypp/Resolver.h"
00027 #include "zypp/solver/detail/ResolverContext.h"
00028 #include "zypp/ResolverProblem.h"
00029 #include "zypp/solver/detail/ProblemSolutionIgnore.h"
00030 #include "zypp/solver/detail/ProblemSolutionInstall.h"
00031 #include "zypp/solver/detail/ProblemSolutionUninstall.h"
00032 #include "zypp/solver/detail/ProblemSolutionUnlock.h"
00033 #include "zypp/solver/detail/ProblemSolutionKeep.h"
00034 #include "zypp/solver/detail/ProblemSolutionAllBranches.h"
00035 #include "zypp/solver/detail/ProblemSolutionDoubleTimeout.h"
00036
00037 #include "zypp/solver/detail/ResolverInfoChildOf.h"
00038 #include "zypp/solver/detail/ResolverInfoConflictsWith.h"
00039 #include "zypp/solver/detail/ResolverInfoContainer.h"
00040 #include "zypp/solver/detail/ResolverInfoDependsOn.h"
00041 #include "zypp/solver/detail/ResolverInfoMisc.h"
00042 #include "zypp/solver/detail/ResolverInfoMissingReq.h"
00043 #include "zypp/solver/detail/ResolverInfoNeededBy.h"
00044 #include "zypp/solver/detail/ResolverInfoObsoletes.h"
00045
00046 #include "zypp/base/String.h"
00047 #include "zypp/base/Logger.h"
00048 #include "zypp/base/Gettext.h"
00049
00050 #include "zypp/base/Algorithm.h"
00051 #include "zypp/ResPool.h"
00052 #include "zypp/ResFilters.h"
00053 #include "zypp/CapFilters.h"
00054
00055
00057 namespace zypp
00058 {
00059
00060 namespace solver
00061 {
00062
00063 namespace detail
00064 {
00065
00066 using namespace std;
00067
00068
00069 typedef multimap<PoolItem_Ref, ResolverInfo_Ptr> ProblemMap;
00070 typedef multimap<PoolItem_Ref, Capability> ItemCapabilityMap;
00071 typedef multimap<PoolItem_Ref, PoolItem_Ref> ConflictMap;
00072
00073 #define MAXPROBLEMS 20
00074 #define TAB " "
00075
00076
00077 template <class K, class V>
00078 class cap_equals {
00079 private:
00080 V value;
00081 public:
00082 cap_equals (const V& v)
00083 : value(v) {
00084 }
00085
00086 bool operator() (pair<const K, V> elem) {
00087 return value.matches (elem.second) == CapMatch::yes;
00088 }
00089 };
00090
00091
00092 template <class K, class V>
00093 class conflict_equals {
00094 private:
00095 V value;
00096 public:
00097 conflict_equals (const V& v)
00098 : value(v) {
00099 }
00100
00101 bool operator() (pair<const K, V> elem) {
00102 return value = elem.second;
00103 }
00104 };
00105
00106
00107
00108 typedef struct {
00109
00110 ProblemMap problems;
00111
00112 ProblemMap additionalInfo;
00113
00114
00115 ItemCapabilityMap provideAndDeleteMap;
00116
00117
00118 ItemCapabilityMap provideAndKeptMap;
00119
00120 ItemCapabilityMap provideAndLockMap;
00121
00122 ItemCapabilityMap provideAndOtherArchMap;
00123
00124 ItemCapabilityMap provideAndOtherVendorMap;
00125
00126 ConflictMap conflictMap;
00127 } ResItemCollector;
00128
00129
00130 static void
00131 collector_cb (ResolverInfo_Ptr info, void *data)
00132 {
00133 ResItemCollector *collector = (ResItemCollector *)data;
00134 PoolItem_Ref item = info->affected();
00135 if (info->error()) {
00136 collector->problems.insert (make_pair( item, info));
00137 } else {
00138 collector->additionalInfo.insert (make_pair( item, info));
00139
00140 if (info->type()==RESOLVER_INFO_TYPE_NEEDED_BY) {
00141 ResolverInfoNeededBy_constPtr needed_by = dynamic_pointer_cast<const ResolverInfoNeededBy>(info);
00142 PoolItemList itemList = needed_by->items();
00143 for (PoolItemList::const_iterator iter = itemList.begin();
00144 iter != itemList.end(); ++iter)
00145 {
00146 collector->additionalInfo.insert (make_pair( *iter, info));
00147 }
00148 }
00149 }
00150
00151
00152
00153 if (info->type() == RESOLVER_INFO_TYPE_UNINSTALL_PROVIDER) {
00154 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00155
00156 ItemCapabilityMap::iterator pos = find_if (collector->provideAndDeleteMap.begin(),
00157 collector->provideAndDeleteMap.end(),
00158 cap_equals<PoolItem_Ref, Capability>(misc_info->capability()));
00159
00160 if (pos == collector->provideAndDeleteMap.end()) {
00161 _XDEBUG ("Inserting " << misc_info->capability() << "/" << misc_info->other()
00162 << " into provideAndDelete map");
00163 collector->provideAndDeleteMap.insert (make_pair( misc_info->other(), misc_info->capability()));
00164 }
00165 }
00166
00167
00168 if (info->type() == RESOLVER_INFO_TYPE_KEEP_PROVIDER) {
00169 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00170
00171 ItemCapabilityMap::iterator pos = find_if (collector->provideAndKeptMap.begin(),
00172 collector->provideAndKeptMap.end(),
00173 cap_equals<PoolItem_Ref, Capability>(misc_info->capability()));
00174
00175 if (pos == collector->provideAndKeptMap.end()) {
00176 _XDEBUG ("Inserting " << misc_info->capability() << "/" << misc_info->other()
00177 << " into provideAndKeptMap map");
00178 collector->provideAndKeptMap.insert (make_pair( misc_info->other(), misc_info->capability()));
00179 }
00180 }
00181
00182
00183 if (info->type() == RESOLVER_INFO_TYPE_LOCKED_PROVIDER) {
00184 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00185
00186 ItemCapabilityMap::iterator pos = find_if (collector->provideAndLockMap.begin(),
00187 collector->provideAndLockMap.end(),
00188 cap_equals<PoolItem_Ref, Capability>(misc_info->capability()));
00189
00190 if (pos == collector->provideAndLockMap.end()) {
00191 _XDEBUG ("Inserting " << misc_info->capability() << "/" << misc_info->other()
00192 << " into provideAndLockMap map");
00193 collector->provideAndLockMap.insert (make_pair( misc_info->other(), misc_info->capability()));
00194 }
00195 }
00196
00197
00198 if (info->type() == RESOLVER_INFO_TYPE_OTHER_ARCH_PROVIDER) {
00199 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00200
00201 ItemCapabilityMap::iterator pos = find_if (collector->provideAndOtherArchMap.begin(),
00202 collector->provideAndOtherArchMap.end(),
00203 cap_equals<PoolItem_Ref, Capability>(misc_info->capability()));
00204
00205 if (pos == collector->provideAndOtherArchMap.end()) {
00206 _XDEBUG ("Inserting " << misc_info->capability() << "/" << misc_info->other()
00207 << " into provideAndOtherArchMap map");
00208 collector->provideAndOtherArchMap.insert (make_pair( misc_info->other(), misc_info->capability()));
00209 }
00210 }
00211
00212
00213 if (info->type() == RESOLVER_INFO_TYPE_OTHER_VENDOR_PROVIDER) {
00214 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00215
00216 ItemCapabilityMap::iterator pos = find_if (collector->provideAndOtherVendorMap.begin(),
00217 collector->provideAndOtherVendorMap.end(),
00218 cap_equals<PoolItem_Ref, Capability>(misc_info->capability()));
00219
00220 if (pos == collector->provideAndOtherVendorMap.end()) {
00221 _XDEBUG ("Inserting " << misc_info->capability() << "/" << misc_info->other()
00222 << " into provideAndOtherVendorMap map");
00223 collector->provideAndOtherVendorMap.insert (make_pair( misc_info->other(), misc_info->capability()));
00224 }
00225 }
00226
00227 if (info->type() == RESOLVER_INFO_TYPE_CONFLICT_UNINSTALLABLE
00228 || info->type() == RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL) {
00229 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00230
00231
00232 ConflictMap::iterator pos = find_if (collector->conflictMap.lower_bound(misc_info->other()),
00233 collector->conflictMap.upper_bound(misc_info->other()),
00234 conflict_equals<PoolItem_Ref, PoolItem_Ref>(misc_info->affected()));
00235 if (pos == collector->conflictMap.end()) {
00236 _XDEBUG ("Inserting " << misc_info->affected() << "/" << misc_info->other()
00237 << " into conflictMap map");
00238 collector->conflictMap.insert (make_pair(misc_info->affected(), misc_info->other()));
00239 collector->conflictMap.insert (make_pair(misc_info->other(), misc_info->affected()));
00240 }
00241 }
00242
00243 }
00244
00245 struct AllRequires
00246 {
00247 PoolItemList requirers;
00248
00249 bool operator()( const CapAndItem & cai )
00250 {
00251 _XDEBUG (cai.item << " requires " << cai.cap);
00252 requirers.push_back( cai.item );
00253
00254 return true;
00255 }
00256 };
00257
00258 std::string logAdditionalInfo ( const ProblemMap &additionalInfo, const PoolItem_Ref item)
00259 {
00260 string infoStr = "";
00261 for (ProblemMap::const_iterator iter = additionalInfo.find(item); iter != additionalInfo.end();) {
00262 ResolverInfo_Ptr info = iter->second;
00263 PoolItem_Ref iterItem = iter->first;
00264
00265 if (iter == additionalInfo.find(item)) {
00266 string who = ResolverInfo::toString( item );
00267 infoStr = "=== " + who + " ===\n";
00268
00269 ResStatus status = iterItem.status();
00270 if (status.isToBeUninstalled()) {
00271 if (status.isByUser())
00272
00273 infoStr += TAB + str::form (_("%s will be deleted by the user.\n"),
00274 who.c_str());
00275 if (status.isByApplHigh()
00276 || status.isByApplLow())
00277
00278 infoStr += TAB + str::form (_("%s will be deleted by another application. (ApplLow/ApplHigh)\n"),
00279 who.c_str());
00280 }
00281 if (status.isToBeInstalled()) {
00282 if (status.isByUser())
00283
00284 infoStr += TAB + str::form (_("%s will be installed by the user.\n"),
00285 who.c_str());
00286 if (status.isByApplHigh()
00287 || status.isByApplLow())
00288
00289 infoStr += TAB + str::form (_("%s will be installed by another application. (ApplLow/ApplHigh)\n"),
00290 who.c_str());
00291 }
00292 }
00293 if (iterItem == item) {
00294
00295 if (info->type() != RESOLVER_INFO_TYPE_INSTALLING
00296 && info->type() != RESOLVER_INFO_TYPE_ESTABLISHING
00297 && info->type() != RESOLVER_INFO_TYPE_UPDATING
00298 && info->type() != RESOLVER_INFO_TYPE_SKIPPING
00299 && info->type() != RESOLVER_INFO_TYPE_UNINSTALLABLE
00300 && info->type() != RESOLVER_INFO_TYPE_CONFLICT_UNINSTALLABLE) {
00301 infoStr += TAB +info->message();
00302 infoStr += "\n";
00303 }
00304 iter++;
00305 } else {
00306
00307 iter = additionalInfo.end();
00308 }
00309 }
00310 return infoStr;
00311 }
00312
00313
00314 static void
00315 moreDetailsCb( ResolverInfo_Ptr info, void *data )
00316 {
00317 if (info->important()
00318 && info->priority() >= RESOLVER_INFO_PRIORITY_USER) {
00319 std::list<std::string> *details = (std::list<std::string> *)data;
00320 details->push_back( info->message() );
00321 }
00322
00323 }
00324
00325 static string
00326 moreDetails( ResolverContext_Ptr context, PoolItem_Ref item )
00327 {
00328 MIL << "moreDetails for " << item << endl;
00329 std::list<std::string> details;
00330 context->foreachInfo( item, RESOLVER_INFO_PRIORITY_USER, moreDetailsCb, &details, true, true );
00331 string result;
00332 std::list<std::string>::iterator it;
00333 for (it = details.begin(); it != details.end(); ++it)
00334 {
00335 result += " ";
00336 result += *it;
00337 result += "\n";
00338 }
00339
00340 return result;
00341 }
00342
00343
00344
00345 ResolverProblemList
00346 Resolver::problems (const bool ignoreValidSolution) const
00347 {
00348 ResolverProblemList problems;
00349
00350 MIL << "Resolver::problems(" << (ignoreValidSolution ? "ignoreValidSolution": "") << ")" << endl;
00351
00352 if (_best_context && !ignoreValidSolution) {
00353 MIL << "Valid solution found, no problems" << endl;
00354 return problems;
00355 }
00356
00357
00358 ResolverQueueList invalid = invalidQueues();
00359 MIL << invalid.size() << " invalid queues" << endl;
00360
00361 if (invalid.empty()) {
00362 WAR << "No solver problems, but there is also no valid solution." << endl;
00363 if (!_best_context
00364 && timeout() > 0) {
00365
00366 string what = str::form (_("No valid solution found within %d seconds"), timeout());
00367 string details = _("The solver has reached a defined timout");
00368 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00369 problem->addSolution (new ProblemSolutionDoubleTimeout (problem));
00370 if (tryAllPossibilities())
00371 problem->addSolution (new ProblemSolutionAllBranches (problem,false));
00372 problems.push_back (problem);
00373 }
00374
00375 return problems;
00376 }
00377
00378 bool skippedPossibilities = false;
00379
00380 for (ResolverQueueList::iterator iter = invalid.begin();
00381 iter != invalid.end(); iter++) {
00382
00383 ResolverQueue_Ptr invalidQ = *iter;
00384 if (invalidQ->context()->skippedPossibilities()) {
00385 skippedPossibilities = true;
00386 break;
00387 }
00388 }
00389
00390 if (!_tryAllPossibilities
00391 && skippedPossibilities) {
00392
00393 string what = _("No valid solution found with just resolvables of best architecture.");
00394 string details = _("With this run only resolvables with the best architecture have been regarded.\n");
00395 details = details + _("Regarding all possible resolvables takes time, but can come to a valid result.");
00396 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00397 problem->addSolution (new ProblemSolutionAllBranches (problem));
00398 problems.push_back (problem);
00399 }
00400
00401 ResolverContext_Ptr context = invalid.front()->context();
00402 ResItemCollector collector;
00403 context->foreachInfo (PoolItem(), RESOLVER_INFO_PRIORITY_VERBOSE, collector_cb, &collector);
00404
00405 for (ProblemMap::const_iterator iter = collector.problems.begin(); iter != collector.problems.end(); ++iter) {
00406 PoolItem_Ref item = iter->first;
00407 ResolverInfo_Ptr info = iter->second;
00408
00409 bool problem_created = false;
00410
00411 MIL << "Problem: " << *info;
00412 XXX << "; Evaluate solutions..." << endl;
00413 string what;
00414 string details;
00415
00416 if (item) {
00417 string who = ResolverInfo::toString( item );
00418 string whoShort = ResolverInfo::toString( item, true );
00419 switch (info->type()) {
00420 case RESOLVER_INFO_TYPE_INVALID: {
00421 what = _("Invalid information");
00422 }
00423 break;
00424 case RESOLVER_INFO_TYPE_NEEDED_BY: {
00425 ResolverInfoNeededBy_constPtr needed_by = dynamic_pointer_cast<const ResolverInfoNeededBy>(info);
00426 if (needed_by->items().size() >= 1)
00427
00428 what = str::form (_("%s is needed by other resolvables"), whoShort.c_str());
00429 else
00430
00431 what = str::form (_("%s is needed by %s"), whoShort.c_str(), needed_by->itemsToString(true).c_str());
00432 details = str::form (_("%s is needed by:\n%s"), who.c_str(), needed_by->itemsToString(false).c_str());
00433 }
00434 break;
00435 case RESOLVER_INFO_TYPE_CONFLICTS_WITH: {
00436 ResolverInfoConflictsWith_constPtr conflicts_with = dynamic_pointer_cast<const ResolverInfoConflictsWith>(info);
00437 if (conflicts_with->items().size() >= 1)
00438
00439 what = str::form (_("%s conflicts with other resolvables"), whoShort.c_str() );
00440 else
00441
00442 what = str::form (_("%s conflicts with %s"), whoShort.c_str(), conflicts_with->itemsToString(true).c_str());
00443
00444 details = str::form (_("%s conflicts with:\n%s"), who.c_str(), conflicts_with->itemsToString(false).c_str()) + "\n";
00445 details += logAdditionalInfo(collector.additionalInfo, item);
00446 PoolItemList item_list = conflicts_with->items();
00447 for (PoolItemList::const_iterator it = item_list.begin(); it != item_list.end(); ++it) {
00448 details += logAdditionalInfo(collector.additionalInfo, *it);
00449 }
00450
00451 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00452
00453 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00454 if (conflicts_with->items().size() == 1) {
00455
00456 problem->addSolution (new ProblemSolutionUninstall (problem, *(conflicts_with->items().begin())));
00457 } else {
00458
00459 PoolItemList conflict_items = conflicts_with->items();
00460 problem->addSolution (new ProblemSolutionUninstall (problem, conflict_items));
00461 }
00462
00463 problem->addSolution (new ProblemSolutionIgnoreConflicts (problem, item, conflicts_with->capability(),
00464 conflicts_with->items()));
00465 problems.push_back (problem);
00466 problem_created = true;
00467 }
00468 break;
00469 case RESOLVER_INFO_TYPE_OBSOLETES: {
00470 ResolverInfoObsoletes_constPtr obsoletes = dynamic_pointer_cast<const ResolverInfoObsoletes>(info);
00471 if (obsoletes->items().size() >= 1)
00472
00473 what = str::form (_("%s obsoletes other resolvables"), whoShort.c_str());
00474 else
00475
00476 what = str::form (_("%s obsoletes %s"), whoShort.c_str(), obsoletes->itemsToString(true).c_str());
00477
00478 details = str::form (_("%s obsoletes:%s"), who.c_str(), obsoletes->itemsToString(false).c_str());
00479 details += _("\nThese resolvables will be deleted from the system.");
00480 details += "\n" + logAdditionalInfo(collector.additionalInfo, item);
00481 }
00482 break;
00483 case RESOLVER_INFO_TYPE_DEPENDS_ON: {
00484 ResolverInfoDependsOn_constPtr depends_on = dynamic_pointer_cast<const ResolverInfoDependsOn>(info);
00485 if (depends_on->items().size() >= 1)
00486
00487 what = str::form (_("%s depends on other resolvables"), whoShort.c_str(),
00488 depends_on->itemsToString(true).c_str());
00489 else
00490
00491 what = str::form (_("%s depends on %s"), whoShort.c_str(),
00492 depends_on->itemsToString(true).c_str());
00493
00494 details = str::form (_("%s depends on:%s"), who.c_str(), depends_on->itemsToString(false).c_str());
00495 }
00496 break;
00497 case RESOLVER_INFO_TYPE_CHILD_OF: {
00498 ResolverInfoChildOf_constPtr child_of = dynamic_pointer_cast<const ResolverInfoChildOf>(info);
00499
00500 what = _("Child of");
00501 }
00502 break;
00503 case RESOLVER_INFO_TYPE_MISSING_REQ: {
00504 ResolverInfoMissingReq_constPtr missing_req = dynamic_pointer_cast<const ResolverInfoMissingReq>(info);
00505
00506 what = str::form (_("Cannot install %s"), whoShort.c_str());
00507
00508 details = str::form (_("None provides %s"), missing_req->capability().asString().c_str());
00509 details += _("\nThere is no resource available which supports this requirement.");
00510 }
00511 break;
00512
00513
00514 case RESOLVER_INFO_TYPE_INVALID_SOLUTION: {
00515 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00516 what = misc_info->message();
00517 details = _("Due to the problems described above/below, this resolution will not solve all dependencies");
00518
00519 }
00520 break;
00521 case RESOLVER_INFO_TYPE_UNINSTALLABLE: {
00522 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00523
00524
00525 for (ConflictMap::const_iterator it = collector.conflictMap.begin();
00526 it != collector.conflictMap.end(); ++it) {
00527 if (it->first == item) {
00528 what = str::form (_("Cannot install %s, because it is conflicting with %s"),
00529 whoShort.c_str(),
00530 it->second->name().c_str()) + "\n";
00531 details = logAdditionalInfo(collector.additionalInfo, item);
00532 details += logAdditionalInfo(collector.additionalInfo, it->second);
00533 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00534
00535 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00536
00537 problem->addSolution (new ProblemSolutionUninstall (problem, it->second));
00538 problems.push_back (problem);
00539 problem_created = true;
00540 }
00541 }
00542 if (!problem_created) {
00543
00544 what = misc_info->message();
00545
00546 details = str::form (_("%s is not installed and has been marked as uninstallable"), who.c_str()) + "\n";
00547 details += logAdditionalInfo(collector.additionalInfo, item);
00548 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00549 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00550 problems.push_back (problem);
00551 problem_created = true;
00552 }
00553 }
00554 break;
00555 case RESOLVER_INFO_TYPE_REJECT_INSTALL: {
00556 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00557
00558 what = str::form (_("Cannot install %s due to dependency problems"), whoShort.c_str());
00559 details = misc_info->message() + "\n";
00560 details += logAdditionalInfo(collector.additionalInfo, item);
00561 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00562
00563 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00564
00565 problems.push_back (problem);
00566 problem_created = true;
00567 }
00568 break;
00569 case RESOLVER_INFO_TYPE_INSTALL_TO_BE_UNINSTALLED: {
00570 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00571
00572 what = misc_info->message() + "\n";
00573 details = logAdditionalInfo(collector.additionalInfo, item);
00574 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00575 problem->addSolution (new ProblemSolutionInstall (problem, item));
00576 problems.push_back (problem);
00577 problem_created = true;
00578 }
00579 break;
00580 case RESOLVER_INFO_TYPE_INSTALL_UNNEEDED: {
00581 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00582
00583 what = misc_info->message();
00584
00585 }
00586 break;
00587 case RESOLVER_INFO_TYPE_INSTALL_PARALLEL: {
00588 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00589
00590 what = str::form (_("Cannot install %s"), whoShort.c_str());
00591 details = misc_info->message() + "\n";
00592 details += logAdditionalInfo(collector.additionalInfo, item);
00593 details += logAdditionalInfo(collector.additionalInfo, misc_info->other());
00594 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00595
00596 ResStatus status = item.status();
00597 string description = "";
00598 if (status.isInstalled())
00599
00600 description = str::form (_("delete %s"), ResolverInfo::toString (item).c_str());
00601 else
00602
00603 description = str::form (_("do not install %s"), ResolverInfo::toString (item).c_str());
00604 problem->addSolution (new ProblemSolutionUninstall (problem, item, description, ""));
00605
00606
00607 status = misc_info->other().status();
00608 if (status.isInstalled())
00609
00610 description = str::form (_("delete %s"), ResolverInfo::toString (misc_info->other()).c_str());
00611 else
00612
00613 description = str::form (_("do not install %s"), ResolverInfo::toString (misc_info->other()).c_str());
00614 problem->addSolution (new ProblemSolutionUninstall (problem, misc_info->other(), description, ""));
00615
00616
00617 problem->addSolution (new ProblemSolutionIgnoreInstalled (problem, item, misc_info->other()));
00618 problems.push_back (problem);
00619 problem_created = true;
00620 }
00621 break;
00622 case RESOLVER_INFO_TYPE_INCOMPLETES: {
00623 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00624 what = misc_info->message();
00625
00626 details = str::form (_("%s has unfulfilled requirements"), who.c_str())+ "\n";
00627 details += logAdditionalInfo(collector.additionalInfo, item);
00628 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00629
00630 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00631 problems.push_back (problem);
00632 problem_created = true;
00633 }
00634 break;
00635
00636 case RESOLVER_INFO_TYPE_ESTABLISHING: {
00637 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00638 what = misc_info->message();
00639
00640 }
00641 break;
00642
00643 case RESOLVER_INFO_TYPE_INSTALLING: {
00644 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00645 what = misc_info->message();
00646
00647 }
00648 break;
00649 case RESOLVER_INFO_TYPE_UPDATING: {
00650 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00651 what = misc_info->message();
00652
00653 }
00654 break;
00655 case RESOLVER_INFO_TYPE_SKIPPING: {
00656 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00657 what = misc_info->message();
00658
00659 }
00660 break;
00661
00662 case RESOLVER_INFO_TYPE_NO_OTHER_PROVIDER: {
00663 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00664
00665 what = str::form (_("%s has missing dependencies"), whoShort.c_str());
00666 details = misc_info->message() + "\n";
00667 details += logAdditionalInfo(collector.additionalInfo, item);
00668 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00669
00670
00671 for (ItemCapabilityMap::const_iterator it = collector.provideAndDeleteMap.begin();
00672 it != collector.provideAndDeleteMap.end(); ++it) {
00673 if (it->second.matches (misc_info->capability()) == CapMatch::yes) {
00674
00675 problem->addSolution (new ProblemSolutionKeep (problem, it->first));
00676 }
00677 }
00678
00679
00680 for (ItemCapabilityMap::const_iterator it = collector.provideAndKeptMap.begin();
00681 it != collector.provideAndKeptMap.end(); ++it) {
00682 if (it->second.matches (misc_info->capability()) == CapMatch::yes) {
00683
00684 problem->addSolution (new ProblemSolutionInstall (problem, it->first));
00685 }
00686 }
00687
00688
00689 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00690
00691
00692 problem->addSolution (new ProblemSolutionIgnoreRequires (problem, item, misc_info->capability()));
00693
00694
00695
00696 AllRequires info;
00697 Dep dep( Dep::REQUIRES );
00698
00699 invokeOnEach( _pool.byCapabilityIndexBegin( misc_info->capability().index(), dep ),
00700 _pool.byCapabilityIndexEnd( misc_info->capability().index(), dep ),
00701 resfilter::ByCapMatch( misc_info->capability() ),
00702 functor::functorRef<bool,CapAndItem>(info) );
00703 if (info.requirers.size() > 1)
00704 problem->addSolution (new ProblemSolutionIgnoreRequires (problem, info.requirers, misc_info->capability()));
00705
00706 problems.push_back (problem);
00707 problem_created = true;
00708 }
00709 break;
00710 case RESOLVER_INFO_TYPE_NO_PROVIDER: {
00711 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00712 if (item.status().isInstalled()) {
00713
00714 what = str::form (_("%s has missing dependencies"), whoShort.c_str());
00715 } else {
00716
00717 what = str::form (_("%s cannot be installed due to missing dependencies"), whoShort.c_str());
00718 }
00719 details = misc_info->message() + "\n";
00720 details += logAdditionalInfo(collector.additionalInfo, item);
00721 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00722
00723
00724 for (ItemCapabilityMap::const_iterator it = collector.provideAndLockMap.begin();
00725 it != collector.provideAndLockMap.end(); ++it) {
00726 if (it->second.matches (misc_info->capability()) == CapMatch::yes) {
00727
00728 problem->addSolution (new ProblemSolutionUnlock (problem, it->first));
00729
00730 problem->addSolution (new ProblemSolutionUnlock (problem, pool()));
00731 }
00732 }
00733
00734 for (ItemCapabilityMap::const_iterator it = collector.provideAndOtherArchMap.begin();
00735 it != collector.provideAndOtherArchMap.end(); ++it) {
00736 if (it->second.matches (misc_info->capability()) == CapMatch::yes) {
00737
00738 problem->addSolution (new ProblemSolutionIgnoreArchitecture (problem, it->first));
00739 }
00740 }
00741
00742 for (ItemCapabilityMap::const_iterator it = collector.provideAndOtherVendorMap.begin();
00743 it != collector.provideAndOtherVendorMap.end(); ++it) {
00744 if (it->second.matches (misc_info->capability()) == CapMatch::yes) {
00745
00746 problem->addSolution (new ProblemSolutionIgnoreVendor (problem, it->first));
00747 }
00748 }
00749
00750 for (ItemCapabilityMap::const_iterator it = collector.provideAndKeptMap.begin();
00751 it != collector.provideAndKeptMap.end(); ++it) {
00752 if (it->second.matches (misc_info->capability()) == CapMatch::yes) {
00753
00754 problem->addSolution (new ProblemSolutionInstall (problem, it->first));
00755 }
00756 }
00757
00758
00759 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00760
00761 problem->addSolution (new ProblemSolutionIgnoreRequires (problem, item, misc_info->capability()));
00762 problems.push_back (problem);
00763 problem_created = true;
00764 }
00765 break;
00766 case RESOLVER_INFO_TYPE_NO_UPGRADE: {
00767 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00768 what = misc_info->message();
00769
00770 }
00771 break;
00772 case RESOLVER_INFO_TYPE_UNINSTALL_PROVIDER: {
00773 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00774
00775 what =str::form (_("%s fulfills dependencies of %s but will be uninstalled"),
00776 misc_info->other()->name().c_str(),
00777 whoShort.c_str());
00778 details = misc_info->message();
00779
00780 }
00781 break;
00782 case RESOLVER_INFO_TYPE_KEEP_PROVIDER: {
00783 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00784
00785 what =str::form (_("%s fulfills dependencies of %s but will be kept on your system"),
00786 misc_info->other()->name().c_str(),
00787 whoShort.c_str());
00788 details = misc_info->message();
00789
00790 }
00791 break;
00792 case RESOLVER_INFO_TYPE_PARALLEL_PROVIDER: {
00793 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00794
00795 what = str::form (_("No need to install %s"), misc_info->other()->name().c_str());
00796 details = misc_info->message();
00797
00798 }
00799 break;
00800 case RESOLVER_INFO_TYPE_NOT_INSTALLABLE_PROVIDER: {
00801 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00802
00803 what = str::form (_("Cannot install %s to fulfill the dependencies of %s"),
00804 misc_info->other()->name().c_str(),
00805 whoShort.c_str());
00806 details = misc_info->message();
00807
00808 }
00809 case RESOLVER_INFO_TYPE_OTHER_ARCH_PROVIDER: {
00810 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00811 what = misc_info->message();
00812
00813 }
00814 break;
00815 case RESOLVER_INFO_TYPE_LOCKED_PROVIDER: {
00816 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00817
00818 what = str::form (_("Cannot install %s to fulfil the dependencies of %s"),
00819 misc_info->other()->name().c_str(),
00820 whoShort.c_str());
00821 what = misc_info->message();
00822
00823 }
00824 break;
00825 case RESOLVER_INFO_TYPE_CANT_SATISFY: {
00826 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00827 what = misc_info->message() + "\n";
00828 details = logAdditionalInfo(collector.additionalInfo, item);
00829 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00830
00831 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00832
00833
00834 problem->addSolution (new ProblemSolutionIgnoreRequires (problem, item, misc_info->capability()));
00835
00836
00837
00838 AllRequires info;
00839 Dep dep( Dep::REQUIRES );
00840
00841 invokeOnEach( _pool.byCapabilityIndexBegin( misc_info->capability().index(), dep ),
00842 _pool.byCapabilityIndexEnd( misc_info->capability().index(), dep ),
00843 resfilter::ByCapMatch( misc_info->capability() ),
00844 functor::functorRef<bool,CapAndItem>(info) );
00845 if (info.requirers.size() > 1)
00846 problem->addSolution (new ProblemSolutionIgnoreRequires (problem, info.requirers, misc_info->capability()));
00847
00848 problems.push_back (problem);
00849 problem_created = true;
00850 }
00851 break;
00852
00853 case RESOLVER_INFO_TYPE_UNINSTALL_TO_BE_INSTALLED: {
00854 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00855
00856 what = str::form (_("%s will not be uninstalled, because it is still required"), whoShort.c_str());
00857 details = misc_info->message();
00858
00859 }
00860 break;
00861 case RESOLVER_INFO_TYPE_UNINSTALL_INSTALLED: {
00862 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00863
00864 what = str::form (_("%s will not be uninstalled, because it is still required"), whoShort.c_str());
00865 details = misc_info->message() + "\n";
00866 details += logAdditionalInfo(collector.additionalInfo, item);
00867
00868 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00869 if (item.status().isInstalled()) {
00870
00871 problem->addSolution (new ProblemSolutionKeep (problem, item));
00872 } else {
00873
00874 problem->addSolution (new ProblemSolutionInstall (problem, item));
00875 }
00876 problems.push_back (problem);
00877 problem_created = true;
00878
00879 }
00880 break;
00881 case RESOLVER_INFO_TYPE_UNINSTALL_LOCKED: {
00882 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00883 what = misc_info->message();
00884
00885 if (misc_info->trigger() == ResolverInfoMisc::OBSOLETE) {
00886
00887 details = str::form (_("%s obsoletes %s. But %s cannot be deleted, because it is locked."),
00888 misc_info->other()->name().c_str(),
00889 who.c_str(), who.c_str()) + "\n";
00890 details += logAdditionalInfo(collector.additionalInfo, item);
00891 }
00892
00893 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00894 problem->addSolution (new ProblemSolutionUnlock (problem, item));
00895
00896 problem->addSolution (new ProblemSolutionUnlock (problem, pool()));
00897 if (misc_info->trigger() == ResolverInfoMisc::OBSOLETE) {
00898
00899 problem->addSolution (new ProblemSolutionIgnoreObsoletes (problem, item, misc_info->capability(),
00900 misc_info->other()));
00901 } else {
00902
00903
00904 problem->addSolution (new ProblemSolutionKeep (problem, item));
00905 }
00906 problems.push_back (problem);
00907 problem_created = true;
00908 }
00909 break;
00910
00911 case RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL: {
00912 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00913
00914 if (misc_info->other())
00915 what = str::form (_("Cannot install %s, because it is conflicting with %s"),
00916 whoShort.c_str(),
00917 misc_info->other()->name().c_str());
00918 else
00919 what = str::form (_("Cannot install %s, because it is conflicting"),
00920 whoShort.c_str());
00921 details = misc_info->message() + "\n";
00922 details += logAdditionalInfo(collector.additionalInfo, item);
00923 if (misc_info->other())
00924 details += logAdditionalInfo(collector.additionalInfo, misc_info->other());
00925 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00926
00927 problem->addSolution (new ProblemSolutionUninstall (problem, item));
00928 if (misc_info->other())
00929
00930 problem->addSolution (new ProblemSolutionUninstall (problem, misc_info->other()));
00931
00932 problem->addSolution (new ProblemSolutionIgnoreConflicts (problem, item, misc_info->other_capability(),
00933 misc_info->other()));
00934 problems.push_back (problem);
00935 problem_created = true;
00936 }
00937 break;
00938 case RESOLVER_INFO_TYPE_CONFLICT_UNINSTALLABLE: {
00939 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00940
00941 what = str::form (_("%s is uninstallable due to conflicts with %s"),
00942 whoShort.c_str(),
00943 misc_info->other()->name().c_str());
00944 details = misc_info->message();
00945
00946 }
00947 break;
00948 }
00949 } else {
00950
00951 switch (info->type()) {
00952 case RESOLVER_INFO_TYPE_NO_PROVIDER: {
00953 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00954
00955 what = str::form (_("Requirememt %s cannot be fulfilled."), misc_info->capability().asString().c_str());
00956 details = misc_info->message() + "\n";
00957 PoolItem_Ref item = misc_info->affected();
00958 if (!item)
00959 {
00960
00961 string more_details = moreDetails( context, item );
00962 details += more_details;
00963 }
00964 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00965
00966 problem->addSolution (new ProblemSolutionIgnoreRequires (problem, PoolItem_Ref(), misc_info->capability()));
00967 problems.push_back (problem);
00968 problem_created = true;
00969 }
00970 break;
00971 default:
00972 ERR << "No item available for error:" << info << endl;
00973
00974 problem_created = true;
00975 }
00976 }
00977 if (!problem_created) {
00978 ResolverProblem_Ptr problem = new ResolverProblem (what, details);
00979 problems.push_back (problem);
00980 }
00981
00982 if (problems.size() >= MAXPROBLEMS) {
00983 MIL << "Max problems reached: " << MAXPROBLEMS << ". Do not regarding the rest." << endl;
00984 break;
00985 }
00986
00987 }
00988 if (problems.empty()) {
00989 context->spewInfo();
00990 }
00991 return problems;
00992 }
00993
00994 void
00995 Resolver::applySolutions (const ProblemSolutionList & solutions)
00996 {
00997 for (ProblemSolutionList::const_iterator iter = solutions.begin();
00998 iter != solutions.end(); ++iter) {
00999 ProblemSolution_Ptr solution = *iter;
01000 if (!solution->apply (*this))
01001 break;
01002 }
01003 }
01004
01006 };
01009 };
01012 };
01014