- VerIterator Ver(Cache,*I);
- PkgIterator BrokenPkg = Ver.ParentPkg();
- VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
-
- // Check if it needs to be unpacked
- if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false &&
- List->IsNow(BrokenPkg)) {
- if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) {
- // This dependancy has already been dealt with by another SmartUnPack on Pkg
- break;
- } else if (List->IsFlag(Pkg,pkgOrderList::Loop)) {
- /* Found a break, so unpack the package, but dont remove loop as already set.
- This means that there is another SmartUnPack call for this
- package and it will remove the loop flag. */
- if (Debug)
- cout << OutputInDepth(Depth) << " Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-
- SmartUnPack(BrokenPkg, false, Depth + 1);
- } else {
- List->Flag(Pkg,pkgOrderList::Loop);
- // Found a break, so unpack the package
- if (Debug)
- cout << OutputInDepth(Depth) << " Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-
- SmartUnPack(BrokenPkg, false, Depth + 1);
- List->RmFlag(Pkg,pkgOrderList::Loop);
- }
- }
-
- // Check if a package needs to be removed
- if (Cache[BrokenPkg].Delete() == true && !List->IsFlag(BrokenPkg,pkgOrderList::Configured)) {
- if (Debug)
- cout << OutputInDepth(Depth) << " Removing " << BrokenPkg.Name() << " to avoid break" << endl;
- SmartRemove(BrokenPkg);
+ std::unique_ptr<Version *[]> VList(End.AllTargets());
+ for (Version **I = VList.get(); *I != 0; ++I)
+ {
+ VerIterator Ver(Cache,*I);
+ PkgIterator ConflictPkg = Ver.ParentPkg();
+ if (ConflictPkg.CurrentVer() != Ver)
+ {
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Ignore not-installed version " << Ver.VerStr() << " of " << ConflictPkg.FullName() << " for " << End << std::endl;
+ continue;
+ }
+
+ if (List->IsNow(ConflictPkg) == false)
+ {
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Ignore already dealt-with version " << Ver.VerStr() << " of " << ConflictPkg.FullName() << " for " << End << std::endl;
+ continue;
+ }
+
+ if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == true)
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "Ignoring " << End << " as " << ConflictPkg.FullName() << "was temporarily removed" << endl;
+ continue;
+ }
+
+ if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) && PkgLoop)
+ {
+ if (End->Type == pkgCache::Dep::DpkgBreaks && End.IsMultiArchImplicit() == true)
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "Because dependency is MultiArchImplicit we ignored looping on: " << ConflictPkg << endl;
+ continue;
+ }
+ if (Debug)
+ {
+ if (End->Type == pkgCache::Dep::DpkgBreaks)
+ clog << OutputInDepth(Depth) << "Because of breaks knot, deconfigure " << ConflictPkg.FullName() << " temporarily" << endl;
+ else
+ clog << OutputInDepth(Depth) << "Because of conflict knot, removing " << ConflictPkg.FullName() << " temporarily" << endl;
+ }
+ if (EarlyRemove(ConflictPkg, &End) == false)
+ return _error->Error("Internal Error, Could not early remove %s (%d)",ConflictPkg.FullName().c_str(), 3);
+ SomethingBad = true;
+ continue;
+ }
+
+ if (Cache[ConflictPkg].Delete() == false)
+ {
+ if (Debug)
+ {
+ clog << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.FullName() << " to avoid " << End;
+ if (PkgLoop == true)
+ clog << " (Looping)";
+ clog << std::endl;
+ }
+ // we would like to avoid temporary removals and all that at best via a simple unpack
+ _error->PushToStack();
+ if (NonLoopingSmart(UNPACK, Pkg, ConflictPkg, Depth, PkgLoop, NULL, &Changed) == false)
+ {
+ // but if it fails ignore this failure and look for alternative ways of solving
+ if (Debug)
+ {
+ clog << OutputInDepth(Depth) << "Avoidance unpack of " << ConflictPkg.FullName() << " failed for " << End << " ignoring:" << std::endl;
+ _error->DumpErrors(std::clog, GlobalError::DEBUG, false);
+ }
+ _error->RevertToStack();
+ // ignorance can only happen if a) one of the offenders is already gone
+ if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == true)
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "But " << ConflictPkg.FullName() << " was temporarily removed in the meantime to satisfy " << End << endl;
+ }
+ else if (List->IsFlag(Pkg,pkgOrderList::Removed) == true)
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "But " << Pkg.FullName() << " was temporarily removed in the meantime to satisfy " << End << endl;
+ }
+ // or b) we can make one go (removal or dpkg auto-deconfigure)
+ else
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "So temprorary remove/deconfigure " << ConflictPkg.FullName() << " to satisfy " << End << endl;
+ if (EarlyRemove(ConflictPkg, &End) == false)
+ return _error->Error("Internal Error, Could not early remove %s (%d)",ConflictPkg.FullName().c_str(), 2);
+ }
+ }
+ else
+ _error->MergeWithStack();
+ }
+ else
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "Removing " << ConflictPkg.FullName() << " now to avoid " << End << endl;
+ // no earlyremove() here as user has already agreed to the permanent removal
+ if (SmartRemove(Pkg) == false)
+ return _error->Error("Internal Error, Could not early remove %s (%d)",ConflictPkg.FullName().c_str(), 1);
+ }