]> git.saurik.com Git - apt.git/blame - apt-pkg/algorithms.cc
CDROM support
[apt.git] / apt-pkg / algorithms.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
d38b7b3d 3// $Id: algorithms.cc,v 1.12 1998/11/23 07:02:58 jgg Exp $
6c139d6e
AL
4/* ######################################################################
5
6 Algorithms - A set of misc algorithms
7
0a8e3465
AL
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.
13
6c139d6e
AL
14 ##################################################################### */
15 /*}}}*/
16// Include Files /*{{{*/
17#ifdef __GNUG__
094a497d 18#pragma implementation "apt-pkg/algorithms.h"
6c139d6e 19#endif
094a497d
AL
20#include <apt-pkg/algorithms.h>
21#include <apt-pkg/error.h>
0a8e3465 22#include <apt-pkg/configuration.h>
6c139d6e
AL
23#include <iostream.h>
24 /*}}}*/
25
26pkgProblemResolver *pkgProblemResolver::This = 0;
27
28// Simulate::Simulate - Constructor /*{{{*/
29// ---------------------------------------------------------------------
30/* */
31pkgSimulate::pkgSimulate(pkgDepCache &Cache) : pkgPackageManager(Cache),
b518cca6 32 Sim(Cache)
6c139d6e
AL
33{
34 Flags = new unsigned char[Cache.HeaderP->PackageCount];
35 memset(Flags,0,sizeof(*Flags)*Cache.HeaderP->PackageCount);
36}
37 /*}}}*/
38// Simulate::Install - Simulate unpacking of a package /*{{{*/
39// ---------------------------------------------------------------------
40/* */
41bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
42{
43 // Adapt the iterator
44 PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
45 Flags[Pkg->ID] = 1;
46
0a8e3465 47 clog << "Inst " << Pkg.Name();
6c139d6e
AL
48 Sim.MarkInstall(Pkg,false);
49
50 // Look for broken conflicts+predepends.
51 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
52 {
53 if (Sim[I].InstallVer == 0)
54 continue;
55
56 for (DepIterator D = Sim[I].InstVerIter(Sim).DependsList(); D.end() == false; D++)
b518cca6 57 if (D->Type == pkgCache::Dep::Conflicts || D->Type == pkgCache::Dep::PreDepends)
6c139d6e
AL
58 {
59 if ((Sim[D] & pkgDepCache::DepInstall) == 0)
60 {
0a8e3465 61 clog << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']';
b518cca6 62 if (D->Type == pkgCache::Dep::Conflicts)
6c139d6e
AL
63 _error->Error("Fatal, conflicts violated %s",I.Name());
64 }
65 }
66 }
67
68 if (Sim.BrokenCount() != 0)
69 ShortBreaks();
70 else
0a8e3465 71 clog << endl;
6c139d6e
AL
72 return true;
73}
74 /*}}}*/
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
79 however. */
80bool pkgSimulate::Configure(PkgIterator iPkg)
81{
82 // Adapt the iterator
83 PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
84
85 Flags[Pkg->ID] = 2;
86// Sim.MarkInstall(Pkg,false);
87 if (Sim[Pkg].InstBroken() == true)
88 {
0a8e3465 89 clog << "Conf " << Pkg.Name() << " broken" << endl;
6c139d6e
AL
90
91 Sim.Update();
92
93 // Print out each package and the failed dependencies
94 for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++)
95 {
96 if (Sim.IsImportantDep(D) == false ||
97 (Sim[D] & pkgDepCache::DepInstall) != 0)
98 continue;
99
b518cca6 100 if (D->Type == pkgCache::Dep::Conflicts)
0a8e3465 101 clog << " Conflicts:" << D.TargetPkg().Name();
6c139d6e 102 else
0a8e3465 103 clog << " Depends:" << D.TargetPkg().Name();
6c139d6e 104 }
0a8e3465 105 clog << endl;
6c139d6e
AL
106
107 _error->Error("Conf Broken %s",Pkg.Name());
108 }
109 else
0a8e3465 110 clog << "Conf " << Pkg.Name();
6c139d6e
AL
111
112 if (Sim.BrokenCount() != 0)
113 ShortBreaks();
114 else
0a8e3465 115 clog << endl;
6c139d6e
AL
116
117 return true;
118}
119 /*}}}*/
120// Simulate::Remove - Simulate the removal of a package /*{{{*/
121// ---------------------------------------------------------------------
122/* */
123bool pkgSimulate::Remove(PkgIterator iPkg)
124{
125 // Adapt the iterator
126 PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
127
128 Flags[Pkg->ID] = 3;
129 Sim.MarkDelete(Pkg);
0a8e3465 130 clog << "Remv " << Pkg.Name();
6c139d6e
AL
131
132 if (Sim.BrokenCount() != 0)
133 ShortBreaks();
134 else
0a8e3465 135 clog << endl;
6c139d6e
AL
136
137 return true;
138}
139 /*}}}*/
140// Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
141// ---------------------------------------------------------------------
142/* */
143void pkgSimulate::ShortBreaks()
144{
0a8e3465 145 clog << " [";
6c139d6e
AL
146 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
147 {
148 if (Sim[I].InstBroken() == true)
149 {
150 if (Flags[I->ID] == 0)
0a8e3465 151 clog << I.Name() << ' ';
6c139d6e 152/* else
0a8e3465 153 clog << I.Name() << "! ";*/
6c139d6e
AL
154 }
155 }
0a8e3465 156 clog << ']' << endl;
6c139d6e
AL
157}
158 /*}}}*/
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. */
164bool pkgApplyStatus(pkgDepCache &Cache)
165{
166 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
167 {
d38b7b3d
AL
168 // Only choice for a ReInstReq package is to reinstall
169 if (I->InstState == pkgCache::State::ReInstReq ||
170 I->InstState == pkgCache::State::HoldReInstReq)
171 {
172 Cache.MarkKeep(I);
173 continue;
174 }
175
6c139d6e
AL
176 switch (I->CurrentState)
177 {
178 // This means installation failed somehow
b518cca6
AL
179 case pkgCache::State::UnPacked:
180 case pkgCache::State::HalfConfigured:
6c139d6e
AL
181 Cache.MarkKeep(I);
182 break;
183
184 // This means removal failed
b518cca6 185 case pkgCache::State::HalfInstalled:
6c139d6e
AL
186 Cache.MarkDelete(I);
187 break;
188
189 default:
b518cca6 190 if (I->InstState != pkgCache::State::Ok)
6c139d6e
AL
191 return _error->Error("The package %s is not ok and I "
192 "don't know how to fix it!",I.Name());
193 }
194 }
195 return true;
196}
197 /*}}}*/
198// FixBroken - Fix broken packages /*{{{*/
199// ---------------------------------------------------------------------
0a8e3465
AL
200/* This autoinstalls every broken package and then runs the problem resolver
201 on the result. */
6c139d6e
AL
202bool pkgFixBroken(pkgDepCache &Cache)
203{
204 // Auto upgrade all broken packages
205 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
206 if (Cache[I].NowBroken() == true)
207 Cache.MarkInstall(I,true);
7e798dd7 208
6c139d6e
AL
209 /* Fix packages that are in a NeedArchive state but don't have a
210 downloadable install version */
211 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
212 {
213 if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
214 Cache[I].Delete() == true)
215 continue;
216
b518cca6 217 if (Cache[I].InstVerIter(Cache).Downloadable() == false)
6c139d6e
AL
218 continue;
219
7e798dd7 220 Cache.MarkInstall(I,true);
6c139d6e
AL
221 }
222
223 pkgProblemResolver Fix(Cache);
224 return Fix.Resolve(true);
225}
226 /*}}}*/
227// DistUpgrade - Distribution upgrade /*{{{*/
228// ---------------------------------------------------------------------
229/* This autoinstalls every package and then force installs every
230 pre-existing package. This creates the initial set of conditions which
231 most likely contain problems because too many things were installed.
232
0a8e3465 233 The problem resolver is used to resolve the problems.
6c139d6e
AL
234 */
235bool pkgDistUpgrade(pkgDepCache &Cache)
236{
237 /* Auto upgrade all installed packages, this provides the basis
238 for the installation */
239 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
240 if (I->CurrentVer != 0)
241 Cache.MarkInstall(I,true);
242
243 /* Now, auto upgrade all essential packages - this ensures that
244 the essential packages are present and working */
245 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
b518cca6 246 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
6c139d6e
AL
247 Cache.MarkInstall(I,true);
248
249 /* We do it again over all previously installed packages to force
250 conflict resolution on them all. */
251 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
252 if (I->CurrentVer != 0)
253 Cache.MarkInstall(I,false);
254
255 pkgProblemResolver Fix(Cache);
c88edf1d 256
6c139d6e 257 // Hold back held packages.
c88edf1d 258 if (_config->FindB("APT::Ingore-Hold",false) == false)
6c139d6e 259 {
c88edf1d 260 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
6c139d6e 261 {
c88edf1d
AL
262 if (I->SelectedState == pkgCache::State::Hold)
263 {
264 Fix.Protect(I);
265 Cache.MarkKeep(I);
266 }
6c139d6e
AL
267 }
268 }
269
270 return Fix.Resolve();
271}
272 /*}}}*/
0a8e3465
AL
273// AllUpgrade - Upgrade as many packages as possible /*{{{*/
274// ---------------------------------------------------------------------
275/* Right now the system must be consistent before this can be called.
276 It also will not change packages marked for install, it only tries
277 to install packages not marked for install */
278bool pkgAllUpgrade(pkgDepCache &Cache)
279{
280 pkgProblemResolver Fix(Cache);
281
282 if (Cache.BrokenCount() != 0)
283 return false;
284
285 // Upgrade all installed packages
286 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
287 {
288 if (Cache[I].Install() == true)
289 Fix.Protect(I);
290
c88edf1d
AL
291 if (_config->FindB("APT::Ingore-Hold",false) == false)
292 if (I->SelectedState == pkgCache::State::Hold)
293 continue;
0a8e3465
AL
294
295 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
296 Cache.MarkInstall(I,false);
297 }
298
299 return Fix.ResolveByKeep();
300}
301 /*}}}*/
7e798dd7
AL
302// MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
303// ---------------------------------------------------------------------
304/* This simply goes over the entire set of packages and tries to keep
305 each package marked for upgrade. If a conflict is generated then
306 the package is restored. */
307bool pkgMinimizeUpgrade(pkgDepCache &Cache)
308{
309 if (Cache.BrokenCount() != 0)
310 return false;
311
312 // We loop indefinately to get the minimal set size.
313 bool Change = false;
314 do
315 {
316 Change = false;
317 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
318 {
319 // Not interesting
320 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
321 continue;
322
323 // Keep it and see if that is OK
324 Cache.MarkKeep(I);
325 if (Cache.BrokenCount() != 0)
326 Cache.MarkInstall(I,false);
327 else
328 Change = true;
329 }
330 }
331 while (Change == true);
332
333 if (Cache.BrokenCount() != 0)
334 return _error->Error("Internal Error in pkgMinimizeUpgrade");
335
336 return true;
337}
338 /*}}}*/
6c139d6e
AL
339
340// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
341// ---------------------------------------------------------------------
342/* */
343pkgProblemResolver::pkgProblemResolver(pkgDepCache &Cache) : Cache(Cache)
344{
345 // Allocate memory
346 unsigned long Size = Cache.HeaderP->PackageCount;
347 Scores = new signed short[Size];
348 Flags = new unsigned char[Size];
349 memset(Flags,0,sizeof(*Flags)*Size);
350
351 // Set debug to true to see its decision logic
0a8e3465 352 Debug = _config->FindB("Debug::pkgProblemResolver",false);
6c139d6e
AL
353}
354 /*}}}*/
355// ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
356// ---------------------------------------------------------------------
357/* */
358int pkgProblemResolver::ScoreSort(const void *a,const void *b)
359{
360 Package const **A = (Package const **)a;
361 Package const **B = (Package const **)b;
362 if (This->Scores[(*A)->ID] > This->Scores[(*B)->ID])
363 return -1;
364 if (This->Scores[(*A)->ID] < This->Scores[(*B)->ID])
365 return 1;
366 return 0;
367}
368 /*}}}*/
369// ProblemResolver::MakeScores - Make the score table /*{{{*/
370// ---------------------------------------------------------------------
371/* */
372void pkgProblemResolver::MakeScores()
373{
374 unsigned long Size = Cache.HeaderP->PackageCount;
375 memset(Scores,0,sizeof(*Scores)*Size);
376
377 // Generate the base scores for a package based on its properties
378 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
379 {
380 if (Cache[I].InstallVer == 0)
381 continue;
382
383 signed short &Score = Scores[I->ID];
384
385 /* This is arbitary, it should be high enough to elevate an
386 essantial package above most other packages but low enough
387 to allow an obsolete essential packages to be removed by
388 a conflicts on a powerfull normal package (ie libc6) */
b518cca6 389 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
6c139d6e
AL
390 Score += 100;
391
392 // We transform the priority
393 // Important Required Standard Optional Extra
394 signed short PrioMap[] = {0,3,2,1,-1,-2};
395 if (Cache[I].InstVerIter(Cache)->Priority <= 5)
396 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
397
398 /* This helps to fix oddball problems with conflicting packages
399 on the same level. We enhance the score of installed packages */
400 if (I->CurrentVer != 0)
401 Score += 1;
402 }
403
404 // Now that we have the base scores we go and propogate dependencies
405 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
406 {
407 if (Cache[I].InstallVer == 0)
408 continue;
409
410 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
411 {
b518cca6 412 if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
6c139d6e
AL
413 Scores[D.TargetPkg()->ID]++;
414 }
415 }
416
417 // Copy the scores to advoid additive looping
418 signed short *OldScores = new signed short[Size];
419 memcpy(OldScores,Scores,sizeof(*Scores)*Size);
420
421 /* Now we cause 1 level of dependency inheritance, that is we add the
422 score of the packages that depend on the target Package. This
423 fortifies high scoring packages */
424 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
425 {
426 if (Cache[I].InstallVer == 0)
427 continue;
428
429 for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
430 {
431 // Only do it for the install version
432 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
b518cca6 433 (D->Type != pkgCache::Dep::Depends && D->Type != pkgCache::Dep::PreDepends))
6c139d6e
AL
434 continue;
435
436 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
437 }
438 }
439
440 /* Now we propogate along provides. This makes the packages that
441 provide important packages extremely important */
442 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
443 {
444 for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
445 {
446 // Only do it once per package
447 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
448 continue;
449 Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
450 }
451 }
452
453 /* Protected things are pushed really high up. This number should put them
454 ahead of everything */
455 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
456 if ((Flags[I->ID] & Protected) != 0)
457 Scores[I->ID] += 10000;
458
459 delete [] OldScores;
460}
461 /*}}}*/
462// ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
463// ---------------------------------------------------------------------
464/* This goes through and tries to reinstall packages to make this package
465 installable */
466bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
467{
468 if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
469 return false;
0a8e3465 470
6c139d6e
AL
471 Flags[Pkg->ID] &= ~Upgradable;
472
473 bool WasKept = Cache[Pkg].Keep();
474 Cache.MarkInstall(Pkg,false);
475
0a8e3465
AL
476 // This must be a virtual package or something like that.
477 if (Cache[Pkg].InstVerIter(Cache).end() == true)
478 return false;
479
6c139d6e
AL
480 // Isolate the problem dependency
481 bool Fail = false;
482 for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
483 {
484 // Compute a single dependency element (glob or)
485 pkgCache::DepIterator Start = D;
486 pkgCache::DepIterator End = D;
487 unsigned char State = 0;
488 for (bool LastOR = true; D.end() == false && LastOR == true; D++)
489 {
490 State |= Cache[D];
b518cca6 491 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
6c139d6e
AL
492 if (LastOR == true)
493 End = D;
494 }
495
496 // We only worry about critical deps.
497 if (End.IsCritical() != true)
498 continue;
499
500 // Dep is ok
501 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
502 continue;
503
504 // Hm, the group is broken.. I have no idea how to handle this
505 if (Start != End)
506 {
0a8e3465 507 clog << "Note, a broken or group was found in " << Pkg.Name() << "." << endl;
6c139d6e
AL
508 Fail = true;
509 break;
510 }
0a8e3465
AL
511
512 // Do not change protected packages
513 PkgIterator P = Start.SmartTargetPkg();
514 if ((Flags[P->ID] & Protected) == Protected)
515 {
516 if (Debug == true)
517 clog << " Reinet Failed because of protected " << P.Name() << endl;
518 Fail = true;
519 break;
520 }
521
6c139d6e
AL
522 // Upgrade the package if the candidate version will fix the problem.
523 if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
524 {
6c139d6e
AL
525 if (DoUpgrade(P) == false)
526 {
527 if (Debug == true)
0a8e3465 528 clog << " Reinst Failed because of " << P.Name() << endl;
6c139d6e
AL
529 Fail = true;
530 break;
531 }
532 }
533 else
534 {
535 /* We let the algorithm deal with conflicts on its next iteration,
536 it is much smarter than us */
b518cca6 537 if (End->Type == pkgCache::Dep::Conflicts)
6c139d6e
AL
538 continue;
539
540 if (Debug == true)
0a8e3465 541 clog << " Reinst Failed early because of " << Start.TargetPkg().Name() << endl;
6c139d6e
AL
542 Fail = true;
543 break;
544 }
545 }
546
547 // Undo our operations - it might be smart to undo everything this did..
548 if (Fail == true)
549 {
550 if (WasKept == true)
551 Cache.MarkKeep(Pkg);
552 else
553 Cache.MarkDelete(Pkg);
554 return false;
555 }
556
557 if (Debug == true)
0a8e3465 558 clog << " Re-Instated " << Pkg.Name() << endl;
6c139d6e
AL
559 return true;
560}
561 /*}}}*/
562// ProblemResolver::Resolve - Run the resolution pass /*{{{*/
563// ---------------------------------------------------------------------
564/* This routines works by calculating a score for each package. The score
565 is derived by considering the package's priority and all reverse
566 dependents giving an integer that reflects the amount of breakage that
567 adjusting the package will inflict.
568
569 It goes from highest score to lowest and corrects all of the breaks by
570 keeping or removing the dependant packages. If that fails then it removes
571 the package itself and goes on. The routine should be able to intelligently
572 go from any broken state to a fixed state.
573
574 The BrokenFix flag enables a mode where the algorithm tries to
575 upgrade packages to advoid problems. */
576bool pkgProblemResolver::Resolve(bool BrokenFix)
577{
0a8e3465 578 unsigned long Size = Cache.HeaderP->PackageCount;
6c139d6e
AL
579
580 // Record which packages are marked for install
581 bool Again = false;
582 do
583 {
584 Again = false;
585 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
586 {
587 if (Cache[I].Install() == true)
588 Flags[I->ID] |= PreInstalled;
589 else
590 {
591 if (Cache[I].InstBroken() == true && BrokenFix == true)
592 {
593 Cache.MarkInstall(I,false);
594 if (Cache[I].Install() == true)
595 Again = true;
596 }
597
598 Flags[I->ID] &= ~PreInstalled;
599 }
600 Flags[I->ID] |= Upgradable;
601 }
602 }
603 while (Again == true);
604
605 if (Debug == true)
0a8e3465 606 clog << "Starting" << endl;
6c139d6e
AL
607
608 MakeScores();
609
610 /* We have to order the packages so that the broken fixing pass
611 operates from highest score to lowest. This prevents problems when
612 high score packages cause the removal of lower score packages that
613 would cause the removal of even lower score packages. */
614 pkgCache::Package **PList = new pkgCache::Package *[Size];
615 pkgCache::Package **PEnd = PList;
616 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
617 *PEnd++ = I;
618 This = this;
619 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
620
621/* for (pkgCache::Package **K = PList; K != PEnd; K++)
622 if (Scores[(*K)->ID] != 0)
623 {
624 pkgCache::PkgIterator Pkg(Cache,*K);
0a8e3465 625 clog << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
6c139d6e
AL
626 ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' <<
627 Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
628 } */
629
630 if (Debug == true)
0a8e3465 631 clog << "Starting 2" << endl;
6c139d6e
AL
632
633 /* Now consider all broken packages. For each broken package we either
634 remove the package or fix it's problem. We do this once, it should
635 not be possible for a loop to form (that is a < b < c and fixing b by
636 changing a breaks c) */
637 bool Change = true;
638 for (int Counter = 0; Counter != 10 && Change == true; Counter++)
639 {
640 Change = false;
641 for (pkgCache::Package **K = PList; K != PEnd; K++)
642 {
643 pkgCache::PkgIterator I(Cache,*K);
644
645 /* We attempt to install this and see if any breaks result,
646 this takes care of some strange cases */
647 if (Cache[I].CandidateVer != Cache[I].InstallVer &&
648 I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
649 (Flags[I->ID] & PreInstalled) != 0 &&
0a8e3465
AL
650 (Flags[I->ID] & Protected) == 0 &&
651 (Flags[I->ID] & ReInstateTried) == 0)
6c139d6e
AL
652 {
653 if (Debug == true)
0a8e3465 654 clog << " Try to Re-Instate " << I.Name() << endl;
a6568219 655 unsigned long OldBreaks = Cache.BrokenCount();
6c139d6e 656 pkgCache::Version *OldVer = Cache[I].InstallVer;
0a8e3465
AL
657 Flags[I->ID] &= ReInstateTried;
658
6c139d6e
AL
659 Cache.MarkInstall(I,false);
660 if (Cache[I].InstBroken() == true ||
661 OldBreaks < Cache.BrokenCount())
662 {
663 if (OldVer == 0)
664 Cache.MarkDelete(I);
665 else
666 Cache.MarkKeep(I);
667 }
668 else
669 if (Debug == true)
0a8e3465 670 clog << "Re-Instated " << I.Name() << " (" << OldBreaks << " vs " << Cache.BrokenCount() << ')' << endl;
6c139d6e
AL
671 }
672
673 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
674 continue;
675
676 // Isolate the problem dependency
677 PackageKill KillList[100];
678 PackageKill *LEnd = KillList;
679 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
680 {
681 // Compute a single dependency element (glob or)
43d017d6
AL
682 pkgCache::DepIterator Start;
683 pkgCache::DepIterator End;
684 D.GlobOr(Start,End);
6c139d6e
AL
685
686 // We only worry about critical deps.
687 if (End.IsCritical() != true)
688 continue;
689
690 // Dep is ok
691 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
692 continue;
693
694 // Hm, the group is broken.. I have no idea how to handle this
695 if (Start != End)
696 {
0a8e3465 697 clog << "Note, a broken or group was found in " << I.Name() << "." << endl;
6c139d6e
AL
698 Cache.MarkDelete(I);
699 break;
700 }
701
702 if (Debug == true)
0a8e3465 703 clog << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
fcf85120
AL
704
705 /* Look across the version list. If there are no possible
706 targets then we keep the package and bail. This is necessary
707 if a package has a dep on another package that cant be found */
6c139d6e 708 pkgCache::Version **VList = End.AllTargets();
fcf85120
AL
709 if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
710 End->Type != pkgCache::Dep::Conflicts &&
711 Cache[I].NowBroken() == false)
712 {
713 Change = true;
714 Cache.MarkKeep(I);
715 break;
716 }
717
6c139d6e
AL
718 bool Done = false;
719 for (pkgCache::Version **V = VList; *V != 0; V++)
720 {
721 pkgCache::VerIterator Ver(Cache,*V);
722 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
723
724 if (Debug == true)
0a8e3465 725 clog << " Considering " << Pkg.Name() << ' ' << (int)Scores[Pkg->ID] <<
6c139d6e
AL
726 " as a solution to " << I.Name() << ' ' << (int)Scores[I->ID] << endl;
727 if (Scores[I->ID] <= Scores[Pkg->ID] ||
728 ((Cache[End] & pkgDepCache::DepGNow) == 0 &&
b518cca6 729 End->Type != pkgCache::Dep::Conflicts))
6c139d6e 730 {
3b5421b4 731 if ((Flags[I->ID] & Protected) == Protected)
6c139d6e 732 continue;
0a8e3465 733
6c139d6e
AL
734 // See if a keep will do
735 Cache.MarkKeep(I);
736 if (Cache[I].InstBroken() == false)
737 {
738 if (Debug == true)
0a8e3465 739 clog << " Holding Back " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl;
6c139d6e
AL
740 }
741 else
742 {
743 if (BrokenFix == false || DoUpgrade(I) == false)
744 {
745 if (Debug == true)
0a8e3465 746 clog << " Removing " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl;
6c139d6e
AL
747 Cache.MarkDelete(I);
748 if (Counter > 1)
749 Scores[I->ID] = Scores[Pkg->ID];
0a8e3465 750 }
6c139d6e
AL
751 }
752
753 Change = true;
754 Done = true;
755 break;
756 }
757 else
758 {
759 // Skip this if it is protected
760 if ((Flags[Pkg->ID] & Protected) != 0)
761 continue;
762
763 LEnd->Pkg = Pkg;
764 LEnd->Dep = End;
765 LEnd++;
0a8e3465 766
b518cca6 767 if (End->Type != pkgCache::Dep::Conflicts)
6c139d6e
AL
768 break;
769 }
770 }
771
772 // Hm, nothing can possibly satisify this dep. Nuke it.
3b5421b4
AL
773 if (VList[0] == 0 && End->Type != pkgCache::Dep::Conflicts &&
774 (Flags[I->ID] & Protected) != Protected)
6c139d6e
AL
775 {
776 Cache.MarkKeep(I);
777 if (Cache[I].InstBroken() == false)
778 {
779 if (Debug == true)
0a8e3465 780 clog << " Holding Back " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl;
6c139d6e
AL
781 }
782 else
783 {
784 if (Debug == true)
0a8e3465 785 clog << " Removing " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl;
6c139d6e
AL
786 Cache.MarkDelete(I);
787 }
788
789 Change = true;
790 Done = true;
791 }
792
793 delete [] VList;
794 if (Done == true)
795 break;
796 }
797
798 // Apply the kill list now
799 if (Cache[I].InstallVer != 0)
800 for (PackageKill *J = KillList; J != LEnd; J++)
801 {
802 Change = true;
803 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
804 {
b518cca6 805 if (J->Dep->Type == pkgCache::Dep::Conflicts)
6c139d6e
AL
806 {
807 if (Debug == true)
0a8e3465 808 clog << " Fixing " << I.Name() << " via remove of " << J->Pkg.Name() << endl;
6c139d6e
AL
809 Cache.MarkDelete(J->Pkg);
810 }
811 }
812 else
813 {
814 if (Debug == true)
0a8e3465 815 clog << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
6c139d6e
AL
816 Cache.MarkKeep(J->Pkg);
817 }
818
819 if (Counter > 1)
820 Scores[J->Pkg->ID] = Scores[I->ID];
821 }
822 }
823 }
824
825 if (Debug == true)
0a8e3465 826 clog << "Done" << endl;
6c139d6e
AL
827
828 delete [] Scores;
829 delete [] PList;
830
831 if (Cache.BrokenCount() != 0)
0a8e3465
AL
832 return _error->Error("Internal error, pkgProblemResolver::Resolve generated breaks.");
833
834 return true;
835}
836 /*}}}*/
837// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
838// ---------------------------------------------------------------------
839/* This is the work horse of the soft upgrade routine. It is very gental
840 in that it does not install or remove any packages. It is assumed that the
841 system was non-broken previously. */
842bool pkgProblemResolver::ResolveByKeep()
843{
844 unsigned long Size = Cache.HeaderP->PackageCount;
845
846 if (Debug == true)
847 clog << "Entering ResolveByKeep" << endl;
848
849 MakeScores();
850
851 /* We have to order the packages so that the broken fixing pass
852 operates from highest score to lowest. This prevents problems when
853 high score packages cause the removal of lower score packages that
854 would cause the removal of even lower score packages. */
855 pkgCache::Package **PList = new pkgCache::Package *[Size];
856 pkgCache::Package **PEnd = PList;
857 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
858 *PEnd++ = I;
859 This = this;
860 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
861
862 // Consider each broken package
863 pkgCache::Package **LastStop = 0;
864 for (pkgCache::Package **K = PList; K != PEnd; K++)
865 {
866 pkgCache::PkgIterator I(Cache,*K);
867
868 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
869 continue;
870
871 /* Keep the package. If this works then great, otherwise we have
872 to be significantly more agressive and manipulate its dependencies */
873 if ((Flags[I->ID] & Protected) == 0)
874 {
875 if (Debug == true)
876 clog << "Keeping package " << I.Name() << endl;
877 Cache.MarkKeep(I);
878 if (Cache[I].InstBroken() == false)
879 {
880 K = PList;
881 continue;
882 }
883 }
884
885 // Isolate the problem dependencies
886 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
887 {
888 // Compute a single dependency element (glob or)
889 pkgCache::DepIterator Start = D;
890 pkgCache::DepIterator End = D;
891 unsigned char State = 0;
892 for (bool LastOR = true; D.end() == false && LastOR == true; D++)
893 {
894 State |= Cache[D];
895 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
896 if (LastOR == true)
897 End = D;
898 }
899
900 // We only worry about critical deps.
901 if (End.IsCritical() != true)
902 continue;
903
904 // Dep is ok
905 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
906 continue;
907
908 // Hm, the group is broken.. I have no idea how to handle this
909 if (Start != End)
910 {
911 clog << "Note, a broken or group was found in " << I.Name() << "." << endl;
912 if ((Flags[I->ID] & Protected) == 0)
913 Cache.MarkKeep(I);
914 break;
915 }
916
917 if (Debug == true)
918 clog << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
919
920 // Look at all the possible provides on this package
921 pkgCache::Version **VList = End.AllTargets();
0a8e3465
AL
922 for (pkgCache::Version **V = VList; *V != 0; V++)
923 {
924 pkgCache::VerIterator Ver(Cache,*V);
925 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
926
927 // It is not keepable
928 if (Cache[Pkg].InstallVer == 0 ||
929 Pkg->CurrentVer == 0)
930 continue;
931
932 if ((Flags[I->ID] & Protected) == 0)
933 {
934 if (Debug == true)
935 clog << " Keeping Package " << Pkg.Name() << " due to dep" << endl;
936 Cache.MarkKeep(Pkg);
937 }
938
939 if (Cache[I].InstBroken() == false)
940 break;
941 }
942
943 if (Cache[I].InstBroken() == false)
944 break;
945 }
946
947 if (Cache[I].InstBroken() == true)
948 continue;
949
950 // Restart again.
951 if (K == LastStop)
952 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.Name());
953 LastStop = K;
954 K = PList;
955 }
6c139d6e
AL
956
957 return true;
958}
959 /*}}}*/
3b5421b4
AL
960// ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
961// ---------------------------------------------------------------------
962/* This is used to make sure protected packages are installed */
963void pkgProblemResolver::InstallProtect()
964{
965 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
966 {
967 if ((Flags[I->ID] & Protected) == Protected)
968 {
969 if ((Flags[I->ID] & ToRemove) == ToRemove)
970 Cache.MarkDelete(I);
971 else
972 Cache.MarkInstall(I,false);
973 }
974 }
975}
976 /*}}}*/