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