+ MakeScores();
+
+ /* We have to order the packages so that the broken fixing pass
+ operates from highest score to lowest. This prevents problems when
+ high score packages cause the removal of lower score packages that
+ would cause the removal of even lower score packages. */
+ pkgCache::Package **PList = new pkgCache::Package *[Size];
+ pkgCache::Package **PEnd = PList;
+ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+ *PEnd++ = I;
+ This = this;
+ qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
+
+ // Consider each broken package
+ pkgCache::Package **LastStop = 0;
+ for (pkgCache::Package **K = PList; K != PEnd; K++)
+ {
+ pkgCache::PkgIterator I(Cache,*K);
+
+ if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
+ continue;
+
+ /* Keep the package. If this works then great, otherwise we have
+ to be significantly more agressive and manipulate its dependencies */
+ if ((Flags[I->ID] & Protected) == 0)
+ {
+ if (Debug == true)
+ clog << "Keeping package " << I.Name() << endl;
+ Cache.MarkKeep(I);
+ if (Cache[I].InstBroken() == false)
+ {
+ K = PList - 1;
+ continue;
+ }
+ }
+
+ // Isolate the problem dependencies
+ for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
+ {
+ DepIterator Start;
+ DepIterator End;
+ D.GlobOr(Start,End);
+
+ // We only worry about critical deps.
+ if (End.IsCritical() != true)
+ continue;
+
+ // Dep is ok
+ if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
+ continue;
+
+ /* Hm, the group is broken.. I suppose the best thing to do is to
+ is to try every combination of keep/not-keep for the set, but thats
+ slow, and this never happens, just be conservative and assume the
+ list of ors is in preference and keep till it starts to work. */
+ while (true)
+ {
+ if (Debug == true)
+ clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
+
+ // Look at all the possible provides on this package
+ SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
+ for (pkgCache::Version **V = VList; *V != 0; V++)
+ {
+ pkgCache::VerIterator Ver(Cache,*V);
+ pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+ // It is not keepable
+ if (Cache[Pkg].InstallVer == 0 ||
+ Pkg->CurrentVer == 0)
+ continue;
+
+ if ((Flags[I->ID] & Protected) == 0)
+ {
+ if (Debug == true)
+ clog << " Keeping Package " << Pkg.Name() << " due to dep" << endl;
+ Cache.MarkKeep(Pkg);
+ }
+
+ if (Cache[I].InstBroken() == false)
+ break;
+ }
+
+ if (Cache[I].InstBroken() == false)
+ break;
+
+ if (Start == End)
+ break;
+ Start++;
+ }
+
+ if (Cache[I].InstBroken() == false)
+ break;
+ }
+
+ if (Cache[I].InstBroken() == true)
+ continue;
+
+ // Restart again.
+ if (K == LastStop)
+ return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.Name());
+ LastStop = K;
+ K = PList - 1;
+ }