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