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