]>
git.saurik.com Git - apt.git/blob - apt-pkg/algorithms.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: algorithms.cc,v 1.4 1998/10/02 04:39:42 jgg Exp $
4 /* ######################################################################
6 Algorithms - A set of misc algorithms
8 The pkgProblemResolver class has become insanely complex and
9 very sophisticated, it handles every test case I have thrown at it
10 to my satisfaction. Understanding exactly why all the steps the class
11 does are required is difficult and changing though not very risky
12 may result in other cases not working.
14 ##################################################################### */
16 // Include Files /*{{{*/
18 #pragma implementation "apt-pkg/algorithms.h"
20 #include <apt-pkg/algorithms.h>
21 #include <apt-pkg/error.h>
22 #include <apt-pkg/configuration.h>
26 pkgProblemResolver
*pkgProblemResolver::This
= 0;
28 // Simulate::Simulate - Constructor /*{{{*/
29 // ---------------------------------------------------------------------
31 pkgSimulate::pkgSimulate(pkgDepCache
&Cache
) : pkgPackageManager(Cache
),
34 Flags
= new unsigned char[Cache
.HeaderP
->PackageCount
];
35 memset(Flags
,0,sizeof(*Flags
)*Cache
.HeaderP
->PackageCount
);
38 // Simulate::Install - Simulate unpacking of a package /*{{{*/
39 // ---------------------------------------------------------------------
41 bool pkgSimulate::Install(PkgIterator iPkg
,string
/*File*/)
44 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
47 clog
<< "Inst " << Pkg
.Name();
48 Sim
.MarkInstall(Pkg
,false);
50 // Look for broken conflicts+predepends.
51 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
53 if (Sim
[I
].InstallVer
== 0)
56 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false; D
++)
57 if (D
->Type
== pkgCache::Dep::Conflicts
|| D
->Type
== pkgCache::Dep::PreDepends
)
59 if ((Sim
[D
] & pkgDepCache::DepInstall
) == 0)
61 clog
<< " [" << I
.Name() << " on " << D
.TargetPkg().Name() << ']';
62 if (D
->Type
== pkgCache::Dep::Conflicts
)
63 _error
->Error("Fatal, conflicts violated %s",I
.Name());
68 if (Sim
.BrokenCount() != 0)
75 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
76 // ---------------------------------------------------------------------
77 /* This is not an acurate simulation of relatity, we should really not
78 install the package.. For some investigations it may be necessary
80 bool pkgSimulate::Configure(PkgIterator iPkg
)
83 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
86 // Sim.MarkInstall(Pkg,false);
87 if (Sim
[Pkg
].InstBroken() == true)
89 clog
<< "Conf " << Pkg
.Name() << " broken" << endl
;
93 // Print out each package and the failed dependencies
94 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; D
++)
96 if (Sim
.IsImportantDep(D
) == false ||
97 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
100 if (D
->Type
== pkgCache::Dep::Conflicts
)
101 clog
<< " Conflicts:" << D
.TargetPkg().Name();
103 clog
<< " Depends:" << D
.TargetPkg().Name();
107 _error
->Error("Conf Broken %s",Pkg
.Name());
110 clog
<< "Conf " << Pkg
.Name();
112 if (Sim
.BrokenCount() != 0)
120 // Simulate::Remove - Simulate the removal of a package /*{{{*/
121 // ---------------------------------------------------------------------
123 bool pkgSimulate::Remove(PkgIterator iPkg
)
125 // Adapt the iterator
126 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
130 clog
<< "Remv " << Pkg
.Name();
132 if (Sim
.BrokenCount() != 0)
140 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
141 // ---------------------------------------------------------------------
143 void pkgSimulate::ShortBreaks()
146 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
148 if (Sim
[I
].InstBroken() == true)
150 if (Flags
[I
->ID
] == 0)
151 clog
<< I
.Name() << ' ';
153 clog << I.Name() << "! ";*/
159 // ApplyStatus - Adjust for non-ok packages /*{{{*/
160 // ---------------------------------------------------------------------
161 /* We attempt to change the state of the all packages that have failed
162 installation toward their real state. The ordering code will perform
163 the necessary calculations to deal with the problems. */
164 bool pkgApplyStatus(pkgDepCache
&Cache
)
166 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
168 switch (I
->CurrentState
)
170 // This means installation failed somehow
171 case pkgCache::State::UnPacked
:
172 case pkgCache::State::HalfConfigured
:
176 // This means removal failed
177 case pkgCache::State::HalfInstalled
:
182 if (I
->InstState
!= pkgCache::State::Ok
)
183 return _error
->Error("The package %s is not ok and I "
184 "don't know how to fix it!",I
.Name());
190 // FixBroken - Fix broken packages /*{{{*/
191 // ---------------------------------------------------------------------
192 /* This autoinstalls every broken package and then runs the problem resolver
194 bool pkgFixBroken(pkgDepCache
&Cache
)
196 // Auto upgrade all broken packages
197 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
198 if (Cache
[I
].NowBroken() == true)
199 Cache
.MarkInstall(I
,true);
201 /* Fix packages that are in a NeedArchive state but don't have a
202 downloadable install version */
203 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
205 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
206 Cache
[I
].Delete() == true)
209 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
212 Cache
.MarkInstall(I
,true);
215 pkgProblemResolver
Fix(Cache
);
216 return Fix
.Resolve(true);
219 // DistUpgrade - Distribution upgrade /*{{{*/
220 // ---------------------------------------------------------------------
221 /* This autoinstalls every package and then force installs every
222 pre-existing package. This creates the initial set of conditions which
223 most likely contain problems because too many things were installed.
225 The problem resolver is used to resolve the problems.
227 bool pkgDistUpgrade(pkgDepCache
&Cache
)
229 /* Auto upgrade all installed packages, this provides the basis
230 for the installation */
231 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
232 if (I
->CurrentVer
!= 0)
233 Cache
.MarkInstall(I
,true);
235 /* Now, auto upgrade all essential packages - this ensures that
236 the essential packages are present and working */
237 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
238 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
239 Cache
.MarkInstall(I
,true);
241 /* We do it again over all previously installed packages to force
242 conflict resolution on them all. */
243 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
244 if (I
->CurrentVer
!= 0)
245 Cache
.MarkInstall(I
,false);
247 pkgProblemResolver
Fix(Cache
);
249 // Hold back held packages.
250 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
252 if (I
->SelectedState
== pkgCache::State::Hold
)
259 return Fix
.Resolve();
262 // AllUpgrade - Upgrade as many packages as possible /*{{{*/
263 // ---------------------------------------------------------------------
264 /* Right now the system must be consistent before this can be called.
265 It also will not change packages marked for install, it only tries
266 to install packages not marked for install */
267 bool pkgAllUpgrade(pkgDepCache
&Cache
)
269 pkgProblemResolver
Fix(Cache
);
271 if (Cache
.BrokenCount() != 0)
274 // Upgrade all installed packages
275 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
277 if (Cache
[I
].Install() == true)
280 if (I
->SelectedState
== pkgCache::State::Hold
)
283 if (I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0)
284 Cache
.MarkInstall(I
,false);
287 return Fix
.ResolveByKeep();
291 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
292 // ---------------------------------------------------------------------
294 pkgProblemResolver::pkgProblemResolver(pkgDepCache
&Cache
) : Cache(Cache
)
297 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
298 Scores
= new signed short[Size
];
299 Flags
= new unsigned char[Size
];
300 memset(Flags
,0,sizeof(*Flags
)*Size
);
302 // Set debug to true to see its decision logic
303 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
306 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
307 // ---------------------------------------------------------------------
309 int pkgProblemResolver::ScoreSort(const void *a
,const void *b
)
311 Package
const **A
= (Package
const **)a
;
312 Package
const **B
= (Package
const **)b
;
313 if (This
->Scores
[(*A
)->ID
] > This
->Scores
[(*B
)->ID
])
315 if (This
->Scores
[(*A
)->ID
] < This
->Scores
[(*B
)->ID
])
320 // ProblemResolver::MakeScores - Make the score table /*{{{*/
321 // ---------------------------------------------------------------------
323 void pkgProblemResolver::MakeScores()
325 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
326 memset(Scores
,0,sizeof(*Scores
)*Size
);
328 // Generate the base scores for a package based on its properties
329 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
331 if (Cache
[I
].InstallVer
== 0)
334 signed short &Score
= Scores
[I
->ID
];
336 /* This is arbitary, it should be high enough to elevate an
337 essantial package above most other packages but low enough
338 to allow an obsolete essential packages to be removed by
339 a conflicts on a powerfull normal package (ie libc6) */
340 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
343 // We transform the priority
344 // Important Required Standard Optional Extra
345 signed short PrioMap
[] = {0,3,2,1,-1,-2};
346 if (Cache
[I
].InstVerIter(Cache
)->Priority
<= 5)
347 Score
+= PrioMap
[Cache
[I
].InstVerIter(Cache
)->Priority
];
349 /* This helps to fix oddball problems with conflicting packages
350 on the same level. We enhance the score of installed packages */
351 if (I
->CurrentVer
!= 0)
355 // Now that we have the base scores we go and propogate dependencies
356 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
358 if (Cache
[I
].InstallVer
== 0)
361 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false; D
++)
363 if (D
->Type
== pkgCache::Dep::Depends
|| D
->Type
== pkgCache::Dep::PreDepends
)
364 Scores
[D
.TargetPkg()->ID
]++;
368 // Copy the scores to advoid additive looping
369 signed short *OldScores
= new signed short[Size
];
370 memcpy(OldScores
,Scores
,sizeof(*Scores
)*Size
);
372 /* Now we cause 1 level of dependency inheritance, that is we add the
373 score of the packages that depend on the target Package. This
374 fortifies high scoring packages */
375 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
377 if (Cache
[I
].InstallVer
== 0)
380 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; D
++)
382 // Only do it for the install version
383 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
384 (D
->Type
!= pkgCache::Dep::Depends
&& D
->Type
!= pkgCache::Dep::PreDepends
))
387 Scores
[I
->ID
] += abs(OldScores
[D
.ParentPkg()->ID
]);
391 /* Now we propogate along provides. This makes the packages that
392 provide important packages extremely important */
393 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
395 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; P
++)
397 // Only do it once per package
398 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
400 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
404 /* Protected things are pushed really high up. This number should put them
405 ahead of everything */
406 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
407 if ((Flags
[I
->ID
] & Protected
) != 0)
408 Scores
[I
->ID
] += 10000;
413 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
414 // ---------------------------------------------------------------------
415 /* This goes through and tries to reinstall packages to make this package
417 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
419 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
422 Flags
[Pkg
->ID
] &= ~Upgradable
;
424 bool WasKept
= Cache
[Pkg
].Keep();
425 Cache
.MarkInstall(Pkg
,false);
427 // This must be a virtual package or something like that.
428 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
431 // Isolate the problem dependency
433 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
435 // Compute a single dependency element (glob or)
436 pkgCache::DepIterator Start
= D
;
437 pkgCache::DepIterator End
= D
;
438 unsigned char State
= 0;
439 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
442 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
447 // We only worry about critical deps.
448 if (End
.IsCritical() != true)
452 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
455 // Hm, the group is broken.. I have no idea how to handle this
458 clog
<< "Note, a broken or group was found in " << Pkg
.Name() << "." << endl
;
463 // Do not change protected packages
464 PkgIterator P
= Start
.SmartTargetPkg();
465 if ((Flags
[P
->ID
] & Protected
) == Protected
)
468 clog
<< " Reinet Failed because of protected " << P
.Name() << endl
;
473 // Upgrade the package if the candidate version will fix the problem.
474 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
476 if (DoUpgrade(P
) == false)
479 clog
<< " Reinst Failed because of " << P
.Name() << endl
;
486 /* We let the algorithm deal with conflicts on its next iteration,
487 it is much smarter than us */
488 if (End
->Type
== pkgCache::Dep::Conflicts
)
492 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().Name() << endl
;
498 // Undo our operations - it might be smart to undo everything this did..
504 Cache
.MarkDelete(Pkg
);
509 clog
<< " Re-Instated " << Pkg
.Name() << endl
;
513 // ProblemResolver::Resolve - Run the resolution pass /*{{{*/
514 // ---------------------------------------------------------------------
515 /* This routines works by calculating a score for each package. The score
516 is derived by considering the package's priority and all reverse
517 dependents giving an integer that reflects the amount of breakage that
518 adjusting the package will inflict.
520 It goes from highest score to lowest and corrects all of the breaks by
521 keeping or removing the dependant packages. If that fails then it removes
522 the package itself and goes on. The routine should be able to intelligently
523 go from any broken state to a fixed state.
525 The BrokenFix flag enables a mode where the algorithm tries to
526 upgrade packages to advoid problems. */
527 bool pkgProblemResolver::Resolve(bool BrokenFix
)
529 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
531 // Record which packages are marked for install
536 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
538 if (Cache
[I
].Install() == true)
539 Flags
[I
->ID
] |= PreInstalled
;
542 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
544 Cache
.MarkInstall(I
,false);
545 if (Cache
[I
].Install() == true)
549 Flags
[I
->ID
] &= ~PreInstalled
;
551 Flags
[I
->ID
] |= Upgradable
;
554 while (Again
== true);
557 clog
<< "Starting" << endl
;
561 /* We have to order the packages so that the broken fixing pass
562 operates from highest score to lowest. This prevents problems when
563 high score packages cause the removal of lower score packages that
564 would cause the removal of even lower score packages. */
565 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
566 pkgCache::Package
**PEnd
= PList
;
567 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
570 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
572 /* for (pkgCache::Package **K = PList; K != PEnd; K++)
573 if (Scores[(*K)->ID] != 0)
575 pkgCache::PkgIterator Pkg(Cache,*K);
576 clog << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
577 ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' <<
578 Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
582 clog
<< "Starting 2" << endl
;
584 /* Now consider all broken packages. For each broken package we either
585 remove the package or fix it's problem. We do this once, it should
586 not be possible for a loop to form (that is a < b < c and fixing b by
587 changing a breaks c) */
589 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
592 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
594 pkgCache::PkgIterator
I(Cache
,*K
);
596 /* We attempt to install this and see if any breaks result,
597 this takes care of some strange cases */
598 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
599 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
600 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
601 (Flags
[I
->ID
] & Protected
) == 0 &&
602 (Flags
[I
->ID
] & ReInstateTried
) == 0)
605 clog
<< " Try to Re-Instate " << I
.Name() << endl
;
606 int OldBreaks
= Cache
.BrokenCount();
607 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
608 Flags
[I
->ID
] &= ReInstateTried
;
610 Cache
.MarkInstall(I
,false);
611 if (Cache
[I
].InstBroken() == true ||
612 OldBreaks
< Cache
.BrokenCount())
621 clog
<< "Re-Instated " << I
.Name() << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
624 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
627 // Isolate the problem dependency
628 PackageKill KillList
[100];
629 PackageKill
*LEnd
= KillList
;
630 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
632 // Compute a single dependency element (glob or)
633 pkgCache::DepIterator Start
= D
;
634 pkgCache::DepIterator End
= D
;
635 unsigned char State
= 0;
636 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
639 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
644 // We only worry about critical deps.
645 if (End
.IsCritical() != true)
649 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
652 // Hm, the group is broken.. I have no idea how to handle this
655 clog
<< "Note, a broken or group was found in " << I
.Name() << "." << endl
;
661 clog
<< "Package " << I
.Name() << " has broken dep on " << End
.TargetPkg().Name() << endl
;
663 /* Conflicts is simple, decide if we should remove this package
664 or the conflicted one */
665 pkgCache::Version
**VList
= End
.AllTargets();
667 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
669 pkgCache::VerIterator
Ver(Cache
,*V
);
670 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
673 clog
<< " Considering " << Pkg
.Name() << ' ' << (int)Scores
[Pkg
->ID
] <<
674 " as a solution to " << I
.Name() << ' ' << (int)Scores
[I
->ID
] << endl
;
675 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
676 ((Cache
[End
] & pkgDepCache::DepGNow
) == 0 &&
677 End
->Type
!= pkgCache::Dep::Conflicts
))
679 if ((Flags
[I
->ID
] & Protected
) != 0)
682 // See if a keep will do
684 if (Cache
[I
].InstBroken() == false)
687 clog
<< " Holding Back " << I
.Name() << " rather than change " << End
.TargetPkg().Name() << endl
;
691 if (BrokenFix
== false || DoUpgrade(I
) == false)
694 clog
<< " Removing " << I
.Name() << " rather than change " << End
.TargetPkg().Name() << endl
;
697 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
707 // Skip this if it is protected
708 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
715 if (End
->Type
!= pkgCache::Dep::Conflicts
)
720 // Hm, nothing can possibly satisify this dep. Nuke it.
721 if (VList
[0] == 0 && End
->Type
!= pkgCache::Dep::Conflicts
)
724 if (Cache
[I
].InstBroken() == false)
727 clog
<< " Holding Back " << I
.Name() << " because I can't find " << End
.TargetPkg().Name() << endl
;
732 clog
<< " Removing " << I
.Name() << " because I can't find " << End
.TargetPkg().Name() << endl
;
745 // Apply the kill list now
746 if (Cache
[I
].InstallVer
!= 0)
747 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
750 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
752 if (J
->Dep
->Type
== pkgCache::Dep::Conflicts
)
755 clog
<< " Fixing " << I
.Name() << " via remove of " << J
->Pkg
.Name() << endl
;
756 Cache
.MarkDelete(J
->Pkg
);
762 clog
<< " Fixing " << I
.Name() << " via keep of " << J
->Pkg
.Name() << endl
;
763 Cache
.MarkKeep(J
->Pkg
);
767 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
773 clog
<< "Done" << endl
;
778 if (Cache
.BrokenCount() != 0)
779 return _error
->Error("Internal error, pkgProblemResolver::Resolve generated breaks.");
784 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
785 // ---------------------------------------------------------------------
786 /* This is the work horse of the soft upgrade routine. It is very gental
787 in that it does not install or remove any packages. It is assumed that the
788 system was non-broken previously. */
789 bool pkgProblemResolver::ResolveByKeep()
791 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
794 clog
<< "Entering ResolveByKeep" << endl
;
798 /* We have to order the packages so that the broken fixing pass
799 operates from highest score to lowest. This prevents problems when
800 high score packages cause the removal of lower score packages that
801 would cause the removal of even lower score packages. */
802 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
803 pkgCache::Package
**PEnd
= PList
;
804 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
807 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
809 // Consider each broken package
810 pkgCache::Package
**LastStop
= 0;
811 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
813 pkgCache::PkgIterator
I(Cache
,*K
);
815 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
818 /* Keep the package. If this works then great, otherwise we have
819 to be significantly more agressive and manipulate its dependencies */
820 if ((Flags
[I
->ID
] & Protected
) == 0)
823 clog
<< "Keeping package " << I
.Name() << endl
;
825 if (Cache
[I
].InstBroken() == false)
832 // Isolate the problem dependencies
833 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
835 // Compute a single dependency element (glob or)
836 pkgCache::DepIterator Start
= D
;
837 pkgCache::DepIterator End
= D
;
838 unsigned char State
= 0;
839 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
842 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
847 // We only worry about critical deps.
848 if (End
.IsCritical() != true)
852 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
855 // Hm, the group is broken.. I have no idea how to handle this
858 clog
<< "Note, a broken or group was found in " << I
.Name() << "." << endl
;
859 if ((Flags
[I
->ID
] & Protected
) == 0)
865 clog
<< "Package " << I
.Name() << " has broken dep on " << End
.TargetPkg().Name() << endl
;
867 // Look at all the possible provides on this package
868 pkgCache::Version
**VList
= End
.AllTargets();
870 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
872 pkgCache::VerIterator
Ver(Cache
,*V
);
873 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
875 // It is not keepable
876 if (Cache
[Pkg
].InstallVer
== 0 ||
877 Pkg
->CurrentVer
== 0)
880 if ((Flags
[I
->ID
] & Protected
) == 0)
883 clog
<< " Keeping Package " << Pkg
.Name() << " due to dep" << endl
;
887 if (Cache
[I
].InstBroken() == false)
891 if (Cache
[I
].InstBroken() == false)
895 if (Cache
[I
].InstBroken() == true)
900 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I
.Name());