]> git.saurik.com Git - apt.git/blame - apt-pkg/algorithms.cc
* fix segfault in the pkgRecords destructor
[apt.git] / apt-pkg / algorithms.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b8c0f9b7 3// $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 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>
0a57c0f0 23#include <apt-pkg/version.h>
b2e465d6 24#include <apt-pkg/sptr.h>
0a57c0f0 25
b2e465d6
AL
26
27#include <apti18n.h>
22dcc318 28#include <sys/types.h>
90f057fd 29#include <iostream>
6c139d6e 30 /*}}}*/
584e4558 31using namespace std;
6c139d6e
AL
32
33pkgProblemResolver *pkgProblemResolver::This = 0;
34
35// Simulate::Simulate - Constructor /*{{{*/
36// ---------------------------------------------------------------------
b2e465d6
AL
37/* The legacy translations here of input Pkg iterators is obsolete,
38 this is not necessary since the pkgCaches are fully shared now. */
39pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache),
40 iPolicy(Cache),
41 Sim(&Cache->GetCache(),&iPolicy)
6c139d6e 42{
b2e465d6
AL
43 Sim.Init(0);
44 Flags = new unsigned char[Cache->Head().PackageCount];
45 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
281daf46
AL
46
47 // Fake a filename so as not to activate the media swapping
48 string Jnk = "SIMULATE";
b2e465d6 49 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
281daf46 50 FileNames[I] = Jnk;
6c139d6e
AL
51}
52 /*}}}*/
b2e465d6
AL
53// Simulate::Describe - Describe a package /*{{{*/
54// ---------------------------------------------------------------------
3826564e
MZ
55/* Parameter Current == true displays the current package version,
56 Parameter Candidate == true displays the candidate package version */
57void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candidate)
b2e465d6
AL
58{
59 VerIterator Ver(Sim);
e59458f7
AL
60
61 out << Pkg.Name();
62
3826564e 63 if (Current == true)
e59458f7 64 {
b2e465d6 65 Ver = Pkg.CurrentVer();
e59458f7
AL
66 if (Ver.end() == false)
67 out << " [" << Ver.VerStr() << ']';
68 }
b2e465d6 69
3826564e
MZ
70 if (Candidate == true)
71 {
72 Ver = Sim[Pkg].CandidateVerIter(Sim);
73 if (Ver.end() == true)
74 return;
b2e465d6 75
3826564e
MZ
76 out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
77 }
b2e465d6
AL
78}
79 /*}}}*/
6c139d6e
AL
80// Simulate::Install - Simulate unpacking of a package /*{{{*/
81// ---------------------------------------------------------------------
82/* */
83bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
84{
85 // Adapt the iterator
86 PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
87 Flags[Pkg->ID] = 1;
88
b2e465d6 89 cout << "Inst ";
3826564e 90 Describe(Pkg,cout,true,true);
6c139d6e
AL
91 Sim.MarkInstall(Pkg,false);
92
93 // Look for broken conflicts+predepends.
94 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
95 {
96 if (Sim[I].InstallVer == 0)
97 continue;
98
b2e465d6
AL
99 for (DepIterator D = Sim[I].InstVerIter(Sim).DependsList(); D.end() == false;)
100 {
101 DepIterator Start;
102 DepIterator End;
103 D.GlobOr(Start,End);
104 if (Start->Type == pkgCache::Dep::Conflicts ||
308c7d30 105 Start->Type == pkgCache::Dep::DpkgBreaks ||
b2e465d6
AL
106 Start->Type == pkgCache::Dep::Obsoletes ||
107 End->Type == pkgCache::Dep::PreDepends)
6c139d6e 108 {
b2e465d6 109 if ((Sim[End] & pkgDepCache::DepGInstall) == 0)
6c139d6e 110 {
b2e465d6
AL
111 cout << " [" << I.Name() << " on " << Start.TargetPkg().Name() << ']';
112 if (Start->Type == pkgCache::Dep::Conflicts)
6c139d6e
AL
113 _error->Error("Fatal, conflicts violated %s",I.Name());
114 }
b2e465d6
AL
115 }
116 }
6c139d6e
AL
117 }
118
119 if (Sim.BrokenCount() != 0)
120 ShortBreaks();
121 else
04aa15a8 122 cout << endl;
6c139d6e
AL
123 return true;
124}
125 /*}}}*/
126// Simulate::Configure - Simulate configuration of a Package /*{{{*/
127// ---------------------------------------------------------------------
128/* This is not an acurate simulation of relatity, we should really not
129 install the package.. For some investigations it may be necessary
130 however. */
131bool pkgSimulate::Configure(PkgIterator iPkg)
132{
133 // Adapt the iterator
134 PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
135
136 Flags[Pkg->ID] = 2;
137// Sim.MarkInstall(Pkg,false);
138 if (Sim[Pkg].InstBroken() == true)
139 {
04aa15a8 140 cout << "Conf " << Pkg.Name() << " broken" << endl;
6c139d6e
AL
141
142 Sim.Update();
143
144 // Print out each package and the failed dependencies
145 for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++)
146 {
147 if (Sim.IsImportantDep(D) == false ||
148 (Sim[D] & pkgDepCache::DepInstall) != 0)
149 continue;
150
b2e465d6
AL
151 if (D->Type == pkgCache::Dep::Obsoletes)
152 cout << " Obsoletes:" << D.TargetPkg().Name();
153 else if (D->Type == pkgCache::Dep::Conflicts)
04aa15a8 154 cout << " Conflicts:" << D.TargetPkg().Name();
308c7d30
IJ
155 else if (D->Type == pkgCache::Dep::DpkgBreaks)
156 cout << " Breaks:" << D.TargetPkg().Name();
6c139d6e 157 else
04aa15a8 158 cout << " Depends:" << D.TargetPkg().Name();
6c139d6e 159 }
04aa15a8 160 cout << endl;
6c139d6e
AL
161
162 _error->Error("Conf Broken %s",Pkg.Name());
163 }
164 else
b2e465d6
AL
165 {
166 cout << "Conf ";
3826564e 167 Describe(Pkg,cout,false,true);
b2e465d6 168 }
6c139d6e
AL
169
170 if (Sim.BrokenCount() != 0)
171 ShortBreaks();
172 else
04aa15a8 173 cout << endl;
6c139d6e
AL
174
175 return true;
176}
177 /*}}}*/
178// Simulate::Remove - Simulate the removal of a package /*{{{*/
179// ---------------------------------------------------------------------
180/* */
fc4b5c9f 181bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
6c139d6e
AL
182{
183 // Adapt the iterator
184 PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
185
186 Flags[Pkg->ID] = 3;
187 Sim.MarkDelete(Pkg);
fc4b5c9f 188 if (Purge == true)
b2e465d6 189 cout << "Purg ";
fc4b5c9f 190 else
b2e465d6 191 cout << "Remv ";
3826564e 192 Describe(Pkg,cout,true,false);
6c139d6e
AL
193
194 if (Sim.BrokenCount() != 0)
195 ShortBreaks();
196 else
04aa15a8 197 cout << endl;
6c139d6e
AL
198
199 return true;
200}
201 /*}}}*/
202// Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
203// ---------------------------------------------------------------------
204/* */
205void pkgSimulate::ShortBreaks()
206{
04aa15a8 207 cout << " [";
6c139d6e
AL
208 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
209 {
210 if (Sim[I].InstBroken() == true)
211 {
212 if (Flags[I->ID] == 0)
04aa15a8 213 cout << I.Name() << ' ';
6c139d6e 214/* else
04aa15a8 215 cout << I.Name() << "! ";*/
6c139d6e
AL
216 }
217 }
04aa15a8 218 cout << ']' << endl;
6c139d6e
AL
219}
220 /*}}}*/
221// ApplyStatus - Adjust for non-ok packages /*{{{*/
222// ---------------------------------------------------------------------
223/* We attempt to change the state of the all packages that have failed
224 installation toward their real state. The ordering code will perform
225 the necessary calculations to deal with the problems. */
226bool pkgApplyStatus(pkgDepCache &Cache)
227{
74a05226
MV
228 pkgDepCache::ActionGroup group(Cache);
229
6c139d6e
AL
230 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
231 {
e481d5b0
AL
232 if (I->VersionList == 0)
233 continue;
234
d38b7b3d
AL
235 // Only choice for a ReInstReq package is to reinstall
236 if (I->InstState == pkgCache::State::ReInstReq ||
237 I->InstState == pkgCache::State::HoldReInstReq)
238 {
5871718b 239 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
74a05226 240 Cache.MarkKeep(I, false, false);
813c8eea
AL
241 else
242 {
243 // Is this right? Will dpkg choke on an upgrade?
2a3f3893
AL
244 if (Cache[I].CandidateVer != 0 &&
245 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 246 Cache.MarkInstall(I, false, 0, false);
813c8eea 247 else
b2e465d6
AL
248 return _error->Error(_("The package %s needs to be reinstalled, "
249 "but I can't find an archive for it."),I.Name());
813c8eea
AL
250 }
251
d38b7b3d
AL
252 continue;
253 }
254
6c139d6e
AL
255 switch (I->CurrentState)
256 {
813c8eea
AL
257 /* This means installation failed somehow - it does not need to be
258 re-unpacked (probably) */
b518cca6
AL
259 case pkgCache::State::UnPacked:
260 case pkgCache::State::HalfConfigured:
5871718b 261 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
813c8eea 262 I.State() != pkgCache::PkgIterator::NeedsUnpack)
74a05226 263 Cache.MarkKeep(I, false, false);
813c8eea
AL
264 else
265 {
2a3f3893
AL
266 if (Cache[I].CandidateVer != 0 &&
267 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 268 Cache.MarkInstall(I, true, 0, false);
813c8eea
AL
269 else
270 Cache.MarkDelete(I);
271 }
6c139d6e
AL
272 break;
273
274 // This means removal failed
b518cca6 275 case pkgCache::State::HalfInstalled:
6c139d6e
AL
276 Cache.MarkDelete(I);
277 break;
278
279 default:
b518cca6 280 if (I->InstState != pkgCache::State::Ok)
6c139d6e
AL
281 return _error->Error("The package %s is not ok and I "
282 "don't know how to fix it!",I.Name());
283 }
284 }
285 return true;
286}
287 /*}}}*/
288// FixBroken - Fix broken packages /*{{{*/
289// ---------------------------------------------------------------------
0a8e3465
AL
290/* This autoinstalls every broken package and then runs the problem resolver
291 on the result. */
6c139d6e
AL
292bool pkgFixBroken(pkgDepCache &Cache)
293{
74a05226
MV
294 pkgDepCache::ActionGroup group(Cache);
295
6c139d6e
AL
296 // Auto upgrade all broken packages
297 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
298 if (Cache[I].NowBroken() == true)
74a05226 299 Cache.MarkInstall(I, true, 0, false);
7e798dd7 300
6c139d6e
AL
301 /* Fix packages that are in a NeedArchive state but don't have a
302 downloadable install version */
303 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
304 {
305 if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
306 Cache[I].Delete() == true)
307 continue;
308
b518cca6 309 if (Cache[I].InstVerIter(Cache).Downloadable() == false)
6c139d6e
AL
310 continue;
311
74a05226 312 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
313 }
314
b2e465d6 315 pkgProblemResolver Fix(&Cache);
6c139d6e
AL
316 return Fix.Resolve(true);
317}
318 /*}}}*/
319// DistUpgrade - Distribution upgrade /*{{{*/
320// ---------------------------------------------------------------------
321/* This autoinstalls every package and then force installs every
322 pre-existing package. This creates the initial set of conditions which
323 most likely contain problems because too many things were installed.
324
0a8e3465 325 The problem resolver is used to resolve the problems.
6c139d6e
AL
326 */
327bool pkgDistUpgrade(pkgDepCache &Cache)
328{
74a05226
MV
329 pkgDepCache::ActionGroup group(Cache);
330
6c139d6e
AL
331 /* Auto upgrade all installed packages, this provides the basis
332 for the installation */
333 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
334 if (I->CurrentVer != 0)
74a05226 335 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
336
337 /* Now, auto upgrade all essential packages - this ensures that
338 the essential packages are present and working */
339 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
b518cca6 340 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
74a05226 341 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
342
343 /* We do it again over all previously installed packages to force
344 conflict resolution on them all. */
345 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
346 if (I->CurrentVer != 0)
74a05226 347 Cache.MarkInstall(I, false, 0, false);
6c139d6e 348
b2e465d6 349 pkgProblemResolver Fix(&Cache);
c88edf1d 350
6c139d6e 351 // Hold back held packages.
4490f2de 352 if (_config->FindB("APT::Ignore-Hold",false) == false)
6c139d6e 353 {
c88edf1d 354 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
6c139d6e 355 {
c88edf1d
AL
356 if (I->SelectedState == pkgCache::State::Hold)
357 {
358 Fix.Protect(I);
74a05226 359 Cache.MarkKeep(I, false, false);
c88edf1d 360 }
6c139d6e
AL
361 }
362 }
363
364 return Fix.Resolve();
365}
366 /*}}}*/
0a8e3465
AL
367// AllUpgrade - Upgrade as many packages as possible /*{{{*/
368// ---------------------------------------------------------------------
369/* Right now the system must be consistent before this can be called.
370 It also will not change packages marked for install, it only tries
371 to install packages not marked for install */
372bool pkgAllUpgrade(pkgDepCache &Cache)
373{
74a05226
MV
374 pkgDepCache::ActionGroup group(Cache);
375
b2e465d6 376 pkgProblemResolver Fix(&Cache);
0a8e3465
AL
377
378 if (Cache.BrokenCount() != 0)
379 return false;
380
381 // Upgrade all installed packages
382 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
383 {
384 if (Cache[I].Install() == true)
385 Fix.Protect(I);
386
b2e465d6 387 if (_config->FindB("APT::Ignore-Hold",false) == false)
c88edf1d
AL
388 if (I->SelectedState == pkgCache::State::Hold)
389 continue;
0a8e3465
AL
390
391 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
74a05226 392 Cache.MarkInstall(I, false, 0, false);
0a8e3465
AL
393 }
394
395 return Fix.ResolveByKeep();
396}
397 /*}}}*/
7e798dd7
AL
398// MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
399// ---------------------------------------------------------------------
400/* This simply goes over the entire set of packages and tries to keep
401 each package marked for upgrade. If a conflict is generated then
402 the package is restored. */
403bool pkgMinimizeUpgrade(pkgDepCache &Cache)
404{
74a05226
MV
405 pkgDepCache::ActionGroup group(Cache);
406
7e798dd7
AL
407 if (Cache.BrokenCount() != 0)
408 return false;
409
abc8419e 410 // We loop for 10 tries to get the minimal set size.
7e798dd7 411 bool Change = false;
a005475e 412 unsigned int Count = 0;
7e798dd7
AL
413 do
414 {
415 Change = false;
416 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
417 {
418 // Not interesting
419 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
420 continue;
a005475e 421
7e798dd7 422 // Keep it and see if that is OK
74a05226 423 Cache.MarkKeep(I, false, false);
7e798dd7 424 if (Cache.BrokenCount() != 0)
74a05226 425 Cache.MarkInstall(I, false, 0, false);
7e798dd7 426 else
a005475e
AL
427 {
428 // If keep didnt actually do anything then there was no change..
429 if (Cache[I].Upgrade() == false)
430 Change = true;
431 }
7e798dd7 432 }
a005475e 433 Count++;
7e798dd7 434 }
a005475e 435 while (Change == true && Count < 10);
7e798dd7
AL
436
437 if (Cache.BrokenCount() != 0)
438 return _error->Error("Internal Error in pkgMinimizeUpgrade");
439
440 return true;
441}
442 /*}}}*/
6c139d6e
AL
443
444// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
445// ---------------------------------------------------------------------
446/* */
b2e465d6 447pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
6c139d6e
AL
448{
449 // Allocate memory
b2e465d6 450 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
451 Scores = new signed short[Size];
452 Flags = new unsigned char[Size];
453 memset(Flags,0,sizeof(*Flags)*Size);
454
455 // Set debug to true to see its decision logic
0a8e3465 456 Debug = _config->FindB("Debug::pkgProblemResolver",false);
6c139d6e
AL
457}
458 /*}}}*/
b2e465d6
AL
459// ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
460// ---------------------------------------------------------------------
461/* */
462pkgProblemResolver::~pkgProblemResolver()
463{
464 delete [] Scores;
465 delete [] Flags;
466}
467 /*}}}*/
6c139d6e
AL
468// ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
469// ---------------------------------------------------------------------
470/* */
471int pkgProblemResolver::ScoreSort(const void *a,const void *b)
472{
473 Package const **A = (Package const **)a;
474 Package const **B = (Package const **)b;
475 if (This->Scores[(*A)->ID] > This->Scores[(*B)->ID])
476 return -1;
477 if (This->Scores[(*A)->ID] < This->Scores[(*B)->ID])
478 return 1;
479 return 0;
480}
481 /*}}}*/
482// ProblemResolver::MakeScores - Make the score table /*{{{*/
483// ---------------------------------------------------------------------
484/* */
485void pkgProblemResolver::MakeScores()
486{
b2e465d6 487 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
488 memset(Scores,0,sizeof(*Scores)*Size);
489
490 // Generate the base scores for a package based on its properties
491 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
492 {
493 if (Cache[I].InstallVer == 0)
494 continue;
495
496 signed short &Score = Scores[I->ID];
497
498 /* This is arbitary, it should be high enough to elevate an
499 essantial package above most other packages but low enough
500 to allow an obsolete essential packages to be removed by
501 a conflicts on a powerfull normal package (ie libc6) */
b518cca6 502 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
6c139d6e
AL
503 Score += 100;
504
505 // We transform the priority
506 // Important Required Standard Optional Extra
507 signed short PrioMap[] = {0,3,2,1,-1,-2};
508 if (Cache[I].InstVerIter(Cache)->Priority <= 5)
509 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
510
511 /* This helps to fix oddball problems with conflicting packages
4172c784
MV
512 on the same level. We enhance the score of installed packages
513 if those are not obsolete
514 */
020daa7b 515 if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
6c139d6e
AL
516 Score += 1;
517 }
518
519 // Now that we have the base scores we go and propogate dependencies
520 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
521 {
522 if (Cache[I].InstallVer == 0)
523 continue;
524
525 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
526 {
b518cca6 527 if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
6c139d6e
AL
528 Scores[D.TargetPkg()->ID]++;
529 }
530 }
531
532 // Copy the scores to advoid additive looping
b2e465d6 533 SPtrArray<signed short> OldScores = new signed short[Size];
6c139d6e
AL
534 memcpy(OldScores,Scores,sizeof(*Scores)*Size);
535
536 /* Now we cause 1 level of dependency inheritance, that is we add the
537 score of the packages that depend on the target Package. This
538 fortifies high scoring packages */
539 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
540 {
541 if (Cache[I].InstallVer == 0)
542 continue;
543
544 for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
545 {
546 // Only do it for the install version
547 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
b518cca6 548 (D->Type != pkgCache::Dep::Depends && D->Type != pkgCache::Dep::PreDepends))
6c139d6e
AL
549 continue;
550
551 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
552 }
553 }
554
555 /* Now we propogate along provides. This makes the packages that
556 provide important packages extremely important */
557 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
558 {
559 for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
560 {
561 // Only do it once per package
562 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
563 continue;
564 Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
565 }
566 }
567
568 /* Protected things are pushed really high up. This number should put them
569 ahead of everything */
570 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
d2685fd6 571 {
6c139d6e
AL
572 if ((Flags[I->ID] & Protected) != 0)
573 Scores[I->ID] += 10000;
d2685fd6
AL
574 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
575 Scores[I->ID] += 5000;
b2e465d6 576 }
6c139d6e
AL
577}
578 /*}}}*/
579// ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
580// ---------------------------------------------------------------------
581/* This goes through and tries to reinstall packages to make this package
582 installable */
583bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
584{
74a05226
MV
585 pkgDepCache::ActionGroup group(Cache);
586
6c139d6e
AL
587 if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
588 return false;
3a486305
AL
589 if ((Flags[Pkg->ID] & Protected) == Protected)
590 return false;
0a8e3465 591
6c139d6e
AL
592 Flags[Pkg->ID] &= ~Upgradable;
593
594 bool WasKept = Cache[Pkg].Keep();
74a05226 595 Cache.MarkInstall(Pkg, false, 0, false);
6c139d6e 596
0a8e3465
AL
597 // This must be a virtual package or something like that.
598 if (Cache[Pkg].InstVerIter(Cache).end() == true)
599 return false;
600
6c139d6e
AL
601 // Isolate the problem dependency
602 bool Fail = false;
603 for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
604 {
605 // Compute a single dependency element (glob or)
606 pkgCache::DepIterator Start = D;
607 pkgCache::DepIterator End = D;
608 unsigned char State = 0;
4b1b89c5 609 for (bool LastOR = true; D.end() == false && LastOR == true;)
6c139d6e
AL
610 {
611 State |= Cache[D];
b518cca6 612 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
4b1b89c5 613 D++;
6c139d6e
AL
614 if (LastOR == true)
615 End = D;
616 }
617
618 // We only worry about critical deps.
619 if (End.IsCritical() != true)
620 continue;
4b1b89c5
AL
621
622 // Iterate over all the members in the or group
623 while (1)
0a8e3465 624 {
4b1b89c5
AL
625 // Dep is ok now
626 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
627 break;
628
629 // Do not change protected packages
630 PkgIterator P = Start.SmartTargetPkg();
631 if ((Flags[P->ID] & Protected) == Protected)
632 {
633 if (Debug == true)
648e3cb4 634 clog << " Reinst Failed because of protected " << P.Name() << endl;
4b1b89c5 635 Fail = true;
4b1b89c5 636 }
648e3cb4 637 else
6c139d6e 638 {
648e3cb4
AL
639 // Upgrade the package if the candidate version will fix the problem.
640 if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
641 {
642 if (DoUpgrade(P) == false)
643 {
644 if (Debug == true)
645 clog << " Reinst Failed because of " << P.Name() << endl;
646 Fail = true;
647 }
648 else
649 {
650 Fail = false;
651 break;
652 }
653 }
654 else
4b1b89c5 655 {
648e3cb4
AL
656 /* We let the algorithm deal with conflicts on its next iteration,
657 it is much smarter than us */
b2e465d6 658 if (Start->Type == pkgCache::Dep::Conflicts ||
308c7d30 659 Start->Type == pkgCache::Dep::DpkgBreaks ||
b2e465d6
AL
660 Start->Type == pkgCache::Dep::Obsoletes)
661 break;
648e3cb4 662
4b1b89c5 663 if (Debug == true)
648e3cb4 664 clog << " Reinst Failed early because of " << Start.TargetPkg().Name() << endl;
4b1b89c5 665 Fail = true;
648e3cb4 666 }
4b1b89c5 667 }
6c139d6e 668
4b1b89c5
AL
669 if (Start == End)
670 break;
671 Start++;
672 }
673 if (Fail == true)
6c139d6e 674 break;
6c139d6e
AL
675 }
676
677 // Undo our operations - it might be smart to undo everything this did..
678 if (Fail == true)
679 {
680 if (WasKept == true)
74a05226 681 Cache.MarkKeep(Pkg, false, false);
6c139d6e
AL
682 else
683 Cache.MarkDelete(Pkg);
684 return false;
685 }
686
687 if (Debug == true)
0a8e3465 688 clog << " Re-Instated " << Pkg.Name() << endl;
6c139d6e
AL
689 return true;
690}
691 /*}}}*/
692// ProblemResolver::Resolve - Run the resolution pass /*{{{*/
693// ---------------------------------------------------------------------
694/* This routines works by calculating a score for each package. The score
695 is derived by considering the package's priority and all reverse
696 dependents giving an integer that reflects the amount of breakage that
697 adjusting the package will inflict.
698
699 It goes from highest score to lowest and corrects all of the breaks by
700 keeping or removing the dependant packages. If that fails then it removes
701 the package itself and goes on. The routine should be able to intelligently
702 go from any broken state to a fixed state.
703
704 The BrokenFix flag enables a mode where the algorithm tries to
705 upgrade packages to advoid problems. */
706bool pkgProblemResolver::Resolve(bool BrokenFix)
707{
74a05226
MV
708 pkgDepCache::ActionGroup group(Cache);
709
b2e465d6 710 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
711
712 // Record which packages are marked for install
713 bool Again = false;
714 do
715 {
716 Again = false;
717 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
718 {
719 if (Cache[I].Install() == true)
720 Flags[I->ID] |= PreInstalled;
721 else
722 {
723 if (Cache[I].InstBroken() == true && BrokenFix == true)
724 {
74a05226 725 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
726 if (Cache[I].Install() == true)
727 Again = true;
728 }
729
730 Flags[I->ID] &= ~PreInstalled;
731 }
732 Flags[I->ID] |= Upgradable;
733 }
734 }
735 while (Again == true);
736
737 if (Debug == true)
0a8e3465 738 clog << "Starting" << endl;
6c139d6e
AL
739
740 MakeScores();
741
742 /* We have to order the packages so that the broken fixing pass
743 operates from highest score to lowest. This prevents problems when
744 high score packages cause the removal of lower score packages that
745 would cause the removal of even lower score packages. */
b2e465d6 746 SPtrArray<pkgCache::Package *> PList = new pkgCache::Package *[Size];
6c139d6e
AL
747 pkgCache::Package **PEnd = PList;
748 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
749 *PEnd++ = I;
750 This = this;
751 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
752
753/* for (pkgCache::Package **K = PList; K != PEnd; K++)
754 if (Scores[(*K)->ID] != 0)
755 {
756 pkgCache::PkgIterator Pkg(Cache,*K);
0a8e3465 757 clog << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
6c139d6e
AL
758 ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' <<
759 Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
760 } */
761
762 if (Debug == true)
0a8e3465 763 clog << "Starting 2" << endl;
6c139d6e
AL
764
765 /* Now consider all broken packages. For each broken package we either
766 remove the package or fix it's problem. We do this once, it should
767 not be possible for a loop to form (that is a < b < c and fixing b by
768 changing a breaks c) */
769 bool Change = true;
770 for (int Counter = 0; Counter != 10 && Change == true; Counter++)
771 {
772 Change = false;
773 for (pkgCache::Package **K = PList; K != PEnd; K++)
774 {
775 pkgCache::PkgIterator I(Cache,*K);
776
777 /* We attempt to install this and see if any breaks result,
778 this takes care of some strange cases */
779 if (Cache[I].CandidateVer != Cache[I].InstallVer &&
780 I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
781 (Flags[I->ID] & PreInstalled) != 0 &&
0a8e3465
AL
782 (Flags[I->ID] & Protected) == 0 &&
783 (Flags[I->ID] & ReInstateTried) == 0)
6c139d6e
AL
784 {
785 if (Debug == true)
0a8e3465 786 clog << " Try to Re-Instate " << I.Name() << endl;
a6568219 787 unsigned long OldBreaks = Cache.BrokenCount();
6c139d6e 788 pkgCache::Version *OldVer = Cache[I].InstallVer;
0a8e3465
AL
789 Flags[I->ID] &= ReInstateTried;
790
74a05226 791 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
792 if (Cache[I].InstBroken() == true ||
793 OldBreaks < Cache.BrokenCount())
794 {
795 if (OldVer == 0)
796 Cache.MarkDelete(I);
797 else
74a05226 798 Cache.MarkKeep(I, false, false);
6c139d6e
AL
799 }
800 else
801 if (Debug == true)
0a8e3465 802 clog << "Re-Instated " << I.Name() << " (" << OldBreaks << " vs " << Cache.BrokenCount() << ')' << endl;
6c139d6e
AL
803 }
804
805 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
806 continue;
807
00b47c98 808 if (Debug == true)
d2de5a76 809 clog << "Investigating " << I.Name() << endl;
00b47c98 810
6c139d6e
AL
811 // Isolate the problem dependency
812 PackageKill KillList[100];
813 PackageKill *LEnd = KillList;
421c8d10
AL
814 bool InOr = false;
815 pkgCache::DepIterator Start;
816 pkgCache::DepIterator End;
b2e465d6 817 PackageKill *OldEnd = LEnd;
648e3cb4
AL
818
819 enum {OrRemove,OrKeep} OrOp = OrRemove;
421c8d10
AL
820 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
821 D.end() == false || InOr == true;)
6c139d6e
AL
822 {
823 // Compute a single dependency element (glob or)
648e3cb4
AL
824 if (Start == End)
825 {
826 // Decide what to do
827 if (InOr == true)
828 {
829 if (OldEnd == LEnd && OrOp == OrRemove)
70777d4b
AL
830 {
831 if ((Flags[I->ID] & Protected) != Protected)
00b47c98
AL
832 {
833 if (Debug == true)
834 clog << " Or group remove for " << I.Name() << endl;
70777d4b 835 Cache.MarkDelete(I);
cd14eaf2 836 Change = true;
00b47c98 837 }
70777d4b 838 }
648e3cb4 839 if (OldEnd == LEnd && OrOp == OrKeep)
00b47c98
AL
840 {
841 if (Debug == true)
842 clog << " Or group keep for " << I.Name() << endl;
74a05226 843 Cache.MarkKeep(I, false, false);
cd14eaf2 844 Change = true;
b2e465d6 845 }
648e3cb4
AL
846 }
847
b2e465d6
AL
848 /* We do an extra loop (as above) to finalize the or group
849 processing */
850 InOr = false;
648e3cb4 851 OrOp = OrRemove;
421c8d10 852 D.GlobOr(Start,End);
b2e465d6
AL
853 if (Start.end() == true)
854 break;
cd14eaf2 855
b2e465d6
AL
856 // We only worry about critical deps.
857 if (End.IsCritical() != true)
858 continue;
cd14eaf2 859
648e3cb4
AL
860 InOr = Start != End;
861 OldEnd = LEnd;
cd14eaf2 862 }
421c8d10 863 else
4cc152f9 864 {
421c8d10 865 Start++;
4cc152f9
MV
866 // We only worry about critical deps.
867 if (Start.IsCritical() != true)
868 continue;
869 }
cd14eaf2 870
6c139d6e
AL
871 // Dep is ok
872 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
cd14eaf2
AL
873 {
874 InOr = false;
6c139d6e 875 continue;
cd14eaf2
AL
876 }
877
6c139d6e 878 if (Debug == true)
421c8d10 879 clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
fcf85120
AL
880
881 /* Look across the version list. If there are no possible
882 targets then we keep the package and bail. This is necessary
883 if a package has a dep on another package that cant be found */
b2e465d6 884 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
fcf85120 885 if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
648e3cb4 886 Start->Type != pkgCache::Dep::Conflicts &&
308c7d30 887 Start->Type != pkgCache::Dep::DpkgBreaks &&
b2e465d6 888 Start->Type != pkgCache::Dep::Obsoletes &&
fcf85120 889 Cache[I].NowBroken() == false)
648e3cb4
AL
890 {
891 if (InOr == true)
892 {
893 /* No keep choice because the keep being OK could be the
894 result of another element in the OR group! */
895 continue;
896 }
897
fcf85120 898 Change = true;
74a05226 899 Cache.MarkKeep(I, false, false);
fcf85120
AL
900 break;
901 }
902
6c139d6e
AL
903 bool Done = false;
904 for (pkgCache::Version **V = VList; *V != 0; V++)
905 {
906 pkgCache::VerIterator Ver(Cache,*V);
907 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
a6bfe583 908
6c139d6e 909 if (Debug == true)
421c8d10 910 clog << " Considering " << Pkg.Name() << ' ' << (int)Scores[Pkg->ID] <<
6c139d6e 911 " as a solution to " << I.Name() << ' ' << (int)Scores[I->ID] << endl;
a6bfe583
AL
912
913 /* Try to fix the package under consideration rather than
914 fiddle with the VList package */
6c139d6e 915 if (Scores[I->ID] <= Scores[Pkg->ID] ||
421c8d10 916 ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
b2e465d6 917 End->Type != pkgCache::Dep::Conflicts &&
308c7d30 918 End->Type != pkgCache::Dep::DpkgBreaks &&
b2e465d6 919 End->Type != pkgCache::Dep::Obsoletes))
6c139d6e 920 {
200f8c52 921 // Try a little harder to fix protected packages..
3b5421b4 922 if ((Flags[I->ID] & Protected) == Protected)
200f8c52
AL
923 {
924 if (DoUpgrade(Pkg) == true)
0296c633 925 {
b2e465d6
AL
926 if (Scores[Pkg->ID] > Scores[I->ID])
927 Scores[Pkg->ID] = Scores[I->ID];
0296c633
AL
928 break;
929 }
930
6c139d6e 931 continue;
200f8c52
AL
932 }
933
934 /* See if a keep will do, unless the package is protected,
648e3cb4
AL
935 then installing it will be necessary */
936 bool Installed = Cache[I].Install();
74a05226 937 Cache.MarkKeep(I, false, false);
6c139d6e
AL
938 if (Cache[I].InstBroken() == false)
939 {
648e3cb4
AL
940 // Unwind operation will be keep now
941 if (OrOp == OrRemove)
942 OrOp = OrKeep;
943
944 // Restore
945 if (InOr == true && Installed == true)
74a05226 946 Cache.MarkInstall(I, false, 0, false);
648e3cb4 947
6c139d6e 948 if (Debug == true)
421c8d10 949 clog << " Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
6c139d6e
AL
950 }
951 else
421c8d10 952 {
6c139d6e
AL
953 if (BrokenFix == false || DoUpgrade(I) == false)
954 {
421c8d10
AL
955 // Consider other options
956 if (InOr == false)
957 {
958 if (Debug == true)
959 clog << " Removing " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
960 Cache.MarkDelete(I);
961 if (Counter > 1)
b2e465d6
AL
962 {
963 if (Scores[Pkg->ID] > Scores[I->ID])
964 Scores[I->ID] = Scores[Pkg->ID];
965 }
421c8d10 966 }
0a8e3465 967 }
6c139d6e 968 }
b5dc9785 969
6c139d6e
AL
970 Change = true;
971 Done = true;
972 break;
973 }
974 else
975 {
a6bfe583
AL
976 /* This is a conflicts, and the version we are looking
977 at is not the currently selected version of the
978 package, which means it is not necessary to
979 remove/keep */
980 if (Cache[Pkg].InstallVer != Ver &&
981 (Start->Type == pkgCache::Dep::Conflicts ||
982 Start->Type == pkgCache::Dep::Obsoletes))
983 continue;
308c7d30
IJ
984
985 if (Start->Type == pkgCache::Dep::DpkgBreaks)
986 {
987 /* Would it help if we upgraded? */
988 if (Cache[End] & pkgDepCache::DepGCVer) {
989 if (Debug)
990 clog << " Upgrading " << Pkg.Name() << " due to Breaks field in " << I.Name() << endl;
991 Cache.MarkInstall(Pkg, false, 0, false);
992 continue;
993 }
994 if (Debug)
995 clog << " Will not break " << Pkg.Name() << " as stated in Breaks field in " << I.Name() <<endl;
09ddf81f 996 Cache.MarkKeep(I, false, false);
308c7d30
IJ
997 continue;
998 }
999
648e3cb4 1000 // Skip adding to the kill list if it is protected
6c139d6e
AL
1001 if ((Flags[Pkg->ID] & Protected) != 0)
1002 continue;
a6bfe583
AL
1003
1004 if (Debug == true)
1005 clog << " Added " << Pkg.Name() << " to the remove list" << endl;
6c139d6e
AL
1006
1007 LEnd->Pkg = Pkg;
1008 LEnd->Dep = End;
1009 LEnd++;
0a8e3465 1010
b2e465d6
AL
1011 if (Start->Type != pkgCache::Dep::Conflicts &&
1012 Start->Type != pkgCache::Dep::Obsoletes)
6c139d6e
AL
1013 break;
1014 }
1015 }
1016
1017 // Hm, nothing can possibly satisify this dep. Nuke it.
b2e465d6
AL
1018 if (VList[0] == 0 &&
1019 Start->Type != pkgCache::Dep::Conflicts &&
308c7d30 1020 Start->Type != pkgCache::Dep::DpkgBreaks &&
b2e465d6 1021 Start->Type != pkgCache::Dep::Obsoletes &&
648e3cb4 1022 (Flags[I->ID] & Protected) != Protected)
6c139d6e 1023 {
648e3cb4 1024 bool Installed = Cache[I].Install();
6c139d6e
AL
1025 Cache.MarkKeep(I);
1026 if (Cache[I].InstBroken() == false)
1027 {
648e3cb4
AL
1028 // Unwind operation will be keep now
1029 if (OrOp == OrRemove)
1030 OrOp = OrKeep;
1031
1032 // Restore
1033 if (InOr == true && Installed == true)
74a05226 1034 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1035
6c139d6e 1036 if (Debug == true)
421c8d10 1037 clog << " Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
6c139d6e
AL
1038 }
1039 else
1040 {
1041 if (Debug == true)
421c8d10 1042 clog << " Removing " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
648e3cb4
AL
1043 if (InOr == false)
1044 Cache.MarkDelete(I);
6c139d6e
AL
1045 }
1046
1047 Change = true;
1048 Done = true;
1049 }
1050
421c8d10
AL
1051 // Try some more
1052 if (InOr == true)
1053 continue;
1054
6c139d6e
AL
1055 if (Done == true)
1056 break;
1057 }
1058
1059 // Apply the kill list now
1060 if (Cache[I].InstallVer != 0)
648e3cb4 1061 {
6c139d6e 1062 for (PackageKill *J = KillList; J != LEnd; J++)
6c139d6e 1063 {
648e3cb4
AL
1064 Change = true;
1065 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
1066 {
b2e465d6
AL
1067 if (J->Dep->Type == pkgCache::Dep::Conflicts ||
1068 J->Dep->Type == pkgCache::Dep::Obsoletes)
648e3cb4
AL
1069 {
1070 if (Debug == true)
1071 clog << " Fixing " << I.Name() << " via remove of " << J->Pkg.Name() << endl;
1072 Cache.MarkDelete(J->Pkg);
1073 }
1074 }
1075 else
6c139d6e
AL
1076 {
1077 if (Debug == true)
648e3cb4 1078 clog << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
74a05226 1079 Cache.MarkKeep(J->Pkg, false, false);
6c139d6e 1080 }
b2e465d6 1081
648e3cb4 1082 if (Counter > 1)
b2e465d6
AL
1083 {
1084 if (Scores[I->ID] > Scores[J->Pkg->ID])
1085 Scores[J->Pkg->ID] = Scores[I->ID];
1086 }
648e3cb4
AL
1087 }
1088 }
1089 }
6c139d6e
AL
1090 }
1091
1092 if (Debug == true)
0a8e3465 1093 clog << "Done" << endl;
b2e465d6 1094
6c139d6e 1095 if (Cache.BrokenCount() != 0)
b5dc9785
AL
1096 {
1097 // See if this is the result of a hold
1098 pkgCache::PkgIterator I = Cache.PkgBegin();
1099 for (;I.end() != true; I++)
1100 {
1101 if (Cache[I].InstBroken() == false)
1102 continue;
1103 if ((Flags[I->ID] & Protected) != Protected)
b2e465d6 1104 return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
b5dc9785 1105 }
b2e465d6 1106 return _error->Error(_("Unable to correct problems, you have held broken packages."));
b5dc9785
AL
1107 }
1108
80fa0d8a
MV
1109 // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
1110 // I didn't managed
1111 pkgCache::PkgIterator I = Cache.PkgBegin();
1112 for (;I.end() != true; I++) {
1113 if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
120365ce
MV
1114 if(_config->FindI("Debug::pkgAutoRemove",false)) {
1115 std::clog << "Resolve installed new pkg: " << I.Name()
1116 << " (now marking it as auto)" << std::endl;
1117 }
80fa0d8a
MV
1118 Cache[I].Flags |= pkgCache::Flag::Auto;
1119 }
1120 }
1121
1122
0a8e3465
AL
1123 return true;
1124}
1125 /*}}}*/
1126// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1127// ---------------------------------------------------------------------
1128/* This is the work horse of the soft upgrade routine. It is very gental
1129 in that it does not install or remove any packages. It is assumed that the
1130 system was non-broken previously. */
1131bool pkgProblemResolver::ResolveByKeep()
1132{
74a05226
MV
1133 pkgDepCache::ActionGroup group(Cache);
1134
b2e465d6 1135 unsigned long Size = Cache.Head().PackageCount;
0a8e3465
AL
1136
1137 if (Debug == true)
1138 clog << "Entering ResolveByKeep" << endl;
1139
1140 MakeScores();
1141
1142 /* We have to order the packages so that the broken fixing pass
1143 operates from highest score to lowest. This prevents problems when
1144 high score packages cause the removal of lower score packages that
1145 would cause the removal of even lower score packages. */
1146 pkgCache::Package **PList = new pkgCache::Package *[Size];
1147 pkgCache::Package **PEnd = PList;
1148 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1149 *PEnd++ = I;
1150 This = this;
1151 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
1152
1153 // Consider each broken package
1154 pkgCache::Package **LastStop = 0;
1155 for (pkgCache::Package **K = PList; K != PEnd; K++)
1156 {
1157 pkgCache::PkgIterator I(Cache,*K);
1158
1159 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
1160 continue;
1161
1162 /* Keep the package. If this works then great, otherwise we have
b2e465d6 1163 to be significantly more agressive and manipulate its dependencies */
0a8e3465
AL
1164 if ((Flags[I->ID] & Protected) == 0)
1165 {
1166 if (Debug == true)
1167 clog << "Keeping package " << I.Name() << endl;
74a05226 1168 Cache.MarkKeep(I, false, false);
0a8e3465
AL
1169 if (Cache[I].InstBroken() == false)
1170 {
b2e465d6 1171 K = PList - 1;
0a8e3465
AL
1172 continue;
1173 }
1174 }
1175
1176 // Isolate the problem dependencies
1177 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
1178 {
c5532863
AL
1179 DepIterator Start;
1180 DepIterator End;
1181 D.GlobOr(Start,End);
1182
0a8e3465
AL
1183 // We only worry about critical deps.
1184 if (End.IsCritical() != true)
1185 continue;
1186
1187 // Dep is ok
1188 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
1189 continue;
c5532863
AL
1190
1191 /* Hm, the group is broken.. I suppose the best thing to do is to
1192 is to try every combination of keep/not-keep for the set, but thats
1193 slow, and this never happens, just be conservative and assume the
1194 list of ors is in preference and keep till it starts to work. */
1195 while (true)
0a8e3465 1196 {
c5532863
AL
1197 if (Debug == true)
1198 clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
0a8e3465 1199
c5532863
AL
1200 // Look at all the possible provides on this package
1201 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
1202 for (pkgCache::Version **V = VList; *V != 0; V++)
0a8e3465 1203 {
c5532863
AL
1204 pkgCache::VerIterator Ver(Cache,*V);
1205 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
1206
1207 // It is not keepable
1208 if (Cache[Pkg].InstallVer == 0 ||
1209 Pkg->CurrentVer == 0)
1210 continue;
1211
1212 if ((Flags[I->ID] & Protected) == 0)
1213 {
1214 if (Debug == true)
1215 clog << " Keeping Package " << Pkg.Name() << " due to dep" << endl;
74a05226 1216 Cache.MarkKeep(Pkg, false, false);
c5532863
AL
1217 }
1218
1219 if (Cache[I].InstBroken() == false)
1220 break;
0a8e3465
AL
1221 }
1222
1223 if (Cache[I].InstBroken() == false)
1224 break;
0a8e3465 1225
c5532863
AL
1226 if (Start == End)
1227 break;
1228 Start++;
1229 }
1230
0a8e3465
AL
1231 if (Cache[I].InstBroken() == false)
1232 break;
1233 }
1234
1235 if (Cache[I].InstBroken() == true)
1236 continue;
1237
1238 // Restart again.
1239 if (K == LastStop)
1240 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.Name());
1241 LastStop = K;
b2e465d6 1242 K = PList - 1;
0a8e3465 1243 }
6c139d6e
AL
1244
1245 return true;
1246}
1247 /*}}}*/
3b5421b4
AL
1248// ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
1249// ---------------------------------------------------------------------
1250/* This is used to make sure protected packages are installed */
1251void pkgProblemResolver::InstallProtect()
1252{
74a05226
MV
1253 pkgDepCache::ActionGroup group(Cache);
1254
3b5421b4
AL
1255 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1256 {
1257 if ((Flags[I->ID] & Protected) == Protected)
1258 {
1259 if ((Flags[I->ID] & ToRemove) == ToRemove)
1260 Cache.MarkDelete(I);
c15f5690
MV
1261 else
1262 {
1263 // preserver the information if the package was auto
1264 // or manual installed
1265 bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
1266 Cache.MarkInstall(I, false, 0, !autoInst);
1267 }
3b5421b4
AL
1268 }
1269 }
1270}
1271 /*}}}*/
b2e465d6
AL
1272
1273// PrioSortList - Sort a list of versions by priority /*{{{*/
1274// ---------------------------------------------------------------------
1275/* This is ment to be used in conjunction with AllTargets to get a list
1276 of versions ordered by preference. */
1277static pkgCache *PrioCache;
1278static int PrioComp(const void *A,const void *B)
1279{
1280 pkgCache::VerIterator L(*PrioCache,*(pkgCache::Version **)A);
1281 pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
1282
1283 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
b8c0f9b7
AL
1284 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
1285 return 1;
b2e465d6 1286 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
b8c0f9b7
AL
1287 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
1288 return -1;
b2e465d6
AL
1289
1290 if (L->Priority != R->Priority)
b8c0f9b7 1291 return R->Priority - L->Priority;
b2e465d6
AL
1292 return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
1293}
1294void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
1295{
1296 unsigned long Count = 0;
1297 PrioCache = &Cache;
1298 for (pkgCache::Version **I = List; *I != 0; I++)
1299 Count++;
1300 qsort(List,Count,sizeof(*List),PrioComp);
1301}
1302 /*}}}*/
db1e7193 1303