]> git.saurik.com Git - apt.git/blame - apt-pkg/orderlist.cc
force fancy progressbar redraw on window size change
[apt.git] / apt-pkg / orderlist.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
5819a761 3// $Id: orderlist.cc,v 1.14 2001/05/07 05:49:43 jgg Exp $
6c139d6e
AL
4/* ######################################################################
5
6 Order List - Represents and Manipulates an ordered list of packages.
7
8 A list of packages can be ordered by a number of conflicting criteria
9 each given a specific priority. Each package also has a set of flags
b2e465d6 10 indicating some useful things about it that are derived in the
6c139d6e
AL
11 course of sorting. The pkgPackageManager class uses this class for
12 all of it's installation ordering needs.
13
14 This is a modified version of Manoj's Routine B. It consists of four
15 independent ordering algorithms that can be applied at for different
16 points in the ordering. By appling progressivly fewer ordering
17 operations it is possible to give each consideration it's own
18 priority and create an order that satisfies the lowest applicable
19 consideration.
20
21 The rules for unpacking ordering are:
22 1) Unpacking ignores Depends: on all packages
23 2) Unpacking requires Conflicts: on -ALL- packages to be satisfied
24 3) Unpacking requires PreDepends: on this package only to be satisfied
25 4) Removing requires that no packages depend on the package to be
26 removed.
27
28 And the rule for configuration ordering is:
29 1) Configuring requires that the Depends: of the package be satisfied
30 Conflicts+PreDepends are ignored because unpacking says they are
31 already correct [exageration, it does check but we need not be
32 concerned]
33
34 And some features that are valuable for unpacking ordering.
35 f1) Unpacking a new package should advoid breaking dependencies of
36 configured packages
37 f2) Removal should not require a force, corrolory of f1
38 f3) Unpacking should order by depends rather than fall back to random
39 ordering.
40
41 Each of the features can be enabled in the sorting routine at an
7365ff46 42 arbitrary priority to give quite abit of control over the final unpacking
6c139d6e
AL
43 order.
44
281daf46 45 The rules listed above may never be violated and are called Critical.
6c139d6e
AL
46 When a critical rule is violated then a loop condition is recorded
47 and will have to be delt with in the caller.
63d3141a
AL
48
49 The ordering keeps two lists, the main list and the 'After List'. The
50 purpose of the after list is to allow packages to be delayed. This is done
51 by setting the after flag on the package. Any package which requires this
52 package to be ordered before will inherit the after flag and so on. This
53 is used for CD swap ordering where all packages on a second CD have the
54 after flag set. This forces them and all their dependents to be ordered
55 toward the end.
6c139d6e 56
b2e465d6
AL
57 There are complications in this algorithm when presented with cycles.
58 For all known practical cases it works, all cases where it doesn't work
59 is fixable by tweaking the package descriptions. However, it should be
60 possible to impove this further to make some better choices when
61 presented with cycles.
62
6c139d6e
AL
63 ##################################################################### */
64 /*}}}*/
65// Include Files /*{{{*/
ea542140
DK
66#include<config.h>
67
094a497d
AL
68#include <apt-pkg/orderlist.h>
69#include <apt-pkg/depcache.h>
70#include <apt-pkg/error.h>
b2e465d6
AL
71#include <apt-pkg/sptr.h>
72#include <apt-pkg/configuration.h>
453b82a3
DK
73#include <apt-pkg/cacheiterators.h>
74#include <apt-pkg/pkgcache.h>
5819a761 75
453b82a3
DK
76#include <stdlib.h>
77#include <string.h>
78#include <string>
5819a761 79#include <iostream>
6c139d6e
AL
80 /*}}}*/
81
5819a761
AL
82using namespace std;
83
6c139d6e
AL
84pkgOrderList *pkgOrderList::Me = 0;
85
86// OrderList::pkgOrderList - Constructor /*{{{*/
87// ---------------------------------------------------------------------
88/* */
dcaa1185
DK
89pkgOrderList::pkgOrderList(pkgDepCache *pCache) : Cache(*pCache),
90 Primary(NULL), Secondary(NULL),
91 RevDepends(NULL), Remove(NULL),
92 AfterEnd(NULL), FileList(NULL),
93 LoopCount(-1), Depth(0)
6c139d6e 94{
b2e465d6 95 Debug = _config->FindB("Debug::pkgOrderList",false);
dcaa1185 96
6c139d6e
AL
97 /* Construct the arrays, egcs 1.0.1 bug requires the package count
98 hack */
b2e465d6 99 unsigned long Size = Cache.Head().PackageCount;
63d3141a 100 Flags = new unsigned short[Size];
6c139d6e
AL
101 End = List = new Package *[Size];
102 memset(Flags,0,sizeof(*Flags)*Size);
103}
104 /*}}}*/
105// OrderList::~pkgOrderList - Destructor /*{{{*/
106// ---------------------------------------------------------------------
107/* */
108pkgOrderList::~pkgOrderList()
109{
110 delete [] List;
111 delete [] Flags;
112}
113 /*}}}*/
2fd65468
AL
114// OrderList::IsMissing - Check if a file is missing /*{{{*/
115// ---------------------------------------------------------------------
116/* */
117bool pkgOrderList::IsMissing(PkgIterator Pkg)
118{
119 // Skip packages to erase
120 if (Cache[Pkg].Delete() == true)
121 return false;
122
123 // Skip Packages that need configure only.
c0ba35fc
DK
124 if ((Pkg.State() == pkgCache::PkgIterator::NeedsConfigure ||
125 Pkg.State() == pkgCache::PkgIterator::NeedsNothing) &&
2fd65468
AL
126 Cache[Pkg].Keep() == true)
127 return false;
7cd4153b
AL
128
129 if (FileList == 0)
130 return false;
2fd65468 131
7cd4153b 132 if (FileList[Pkg->ID].empty() == false)
2fd65468 133 return false;
803ea2a8 134
2fd65468
AL
135 return true;
136}
137 /*}}}*/
6c139d6e
AL
138// OrderList::DoRun - Does an order run /*{{{*/
139// ---------------------------------------------------------------------
140/* The caller is expeted to have setup the desired probe state */
141bool pkgOrderList::DoRun()
281daf46 142{
6c139d6e 143 // Temp list
b2e465d6
AL
144 unsigned long Size = Cache.Head().PackageCount;
145 SPtrArray<Package *> NList = new Package *[Size];
146 SPtrArray<Package *> AfterList = new Package *[Size];
63d3141a
AL
147 AfterEnd = AfterList;
148
6c139d6e
AL
149 Depth = 0;
150 WipeFlags(Added | AddPending | Loop | InList);
151
91c03d37 152 for (iterator I = List; I != End; ++I)
6c139d6e 153 Flag(*I,InList);
63d3141a 154
6c139d6e
AL
155 // Rebuild the main list into the temp list.
156 iterator OldEnd = End;
157 End = NList;
91c03d37 158 for (iterator I = List; I != OldEnd; ++I)
3b8d1773 159 if (VisitNode(PkgIterator(Cache,*I), "DoRun") == false)
6c139d6e
AL
160 {
161 End = OldEnd;
6c139d6e
AL
162 return false;
163 }
164
63d3141a
AL
165 // Copy the after list to the end of the main list
166 for (Package **I = AfterList; I != AfterEnd; I++)
167 *End++ = *I;
168
6c139d6e
AL
169 // Swap the main list to the new list
170 delete [] List;
b2e465d6 171 List = NList.UnGuard();
6c139d6e
AL
172 return true;
173}
174 /*}}}*/
175// OrderList::OrderCritical - Perform critical unpacking ordering /*{{{*/
176// ---------------------------------------------------------------------
177/* This performs predepends and immediate configuration ordering only.
178 This is termed critical unpacking ordering. Any loops that form are
179 fatal and indicate that the packages cannot be installed. */
180bool pkgOrderList::OrderCritical()
181{
281daf46 182 FileList = 0;
5e312de7 183
d5081aee 184 Primary = &pkgOrderList::DepUnPackPreD;
6c139d6e
AL
185 Secondary = 0;
186 RevDepends = 0;
187 Remove = 0;
188 LoopCount = 0;
5e312de7 189
6c139d6e
AL
190 // Sort
191 Me = this;
5e312de7
DK
192 qsort(List,End - List,sizeof(*List),&OrderCompareB);
193
6c139d6e
AL
194 if (DoRun() == false)
195 return false;
5e312de7 196
6c139d6e
AL
197 if (LoopCount != 0)
198 return _error->Error("Fatal, predepends looping detected");
5e312de7
DK
199
200 if (Debug == true)
201 {
202 clog << "** Critical Unpack ordering done" << endl;
203
91c03d37 204 for (iterator I = List; I != End; ++I)
5e312de7
DK
205 {
206 PkgIterator P(Cache,*I);
207 if (IsNow(P) == true)
70ae2409 208 clog << " " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
5e312de7
DK
209 }
210 }
211
6c139d6e
AL
212 return true;
213}
214 /*}}}*/
215// OrderList::OrderUnpack - Perform complete unpacking ordering /*{{{*/
216// ---------------------------------------------------------------------
217/* This performs complete unpacking ordering and creates an order that is
218 suitable for unpacking */
281daf46 219bool pkgOrderList::OrderUnpack(string *FileList)
6c139d6e 220{
281daf46
AL
221 this->FileList = FileList;
222
63d3141a
AL
223 // Setup the after flags
224 if (FileList != 0)
225 {
226 WipeFlags(After);
5e312de7 227
63d3141a 228 // Set the inlist flag
91c03d37 229 for (iterator I = List; I != End; ++I)
63d3141a
AL
230 {
231 PkgIterator P(Cache,*I);
232 if (IsMissing(P) == true && IsNow(P) == true)
233 Flag(*I,After);
234 }
235 }
5e312de7 236
727f18af
AL
237 Primary = &pkgOrderList::DepUnPackCrit;
238 Secondary = &pkgOrderList::DepConfigure;
239 RevDepends = &pkgOrderList::DepUnPackDep;
240 Remove = &pkgOrderList::DepRemove;
6c139d6e
AL
241 LoopCount = -1;
242
243 // Sort
244 Me = this;
245 qsort(List,End - List,sizeof(*List),&OrderCompareA);
281daf46 246
d5081aee
DK
247 if (Debug == true)
248 clog << "** Pass A" << endl;
249 if (DoRun() == false)
250 return false;
5e312de7 251
b2e465d6
AL
252 if (Debug == true)
253 clog << "** Pass B" << endl;
6c139d6e
AL
254 Secondary = 0;
255 if (DoRun() == false)
256 return false;
257
b2e465d6
AL
258 if (Debug == true)
259 clog << "** Pass C" << endl;
6c139d6e
AL
260 LoopCount = 0;
261 RevDepends = 0;
262 Remove = 0; // Otherwise the libreadline remove problem occures
263 if (DoRun() == false)
264 return false;
5e312de7 265
b2e465d6
AL
266 if (Debug == true)
267 clog << "** Pass D" << endl;
6c139d6e 268 LoopCount = 0;
727f18af 269 Primary = &pkgOrderList::DepUnPackPre;
6c139d6e
AL
270 if (DoRun() == false)
271 return false;
272
b2e465d6 273 if (Debug == true)
6c139d6e 274 {
b2e465d6
AL
275 clog << "** Unpack ordering done" << endl;
276
91c03d37 277 for (iterator I = List; I != End; ++I)
b2e465d6
AL
278 {
279 PkgIterator P(Cache,*I);
280 if (IsNow(P) == true)
70ae2409 281 clog << " " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
b2e465d6 282 }
5e312de7 283 }
6c139d6e
AL
284
285 return true;
286}
287 /*}}}*/
288// OrderList::OrderConfigure - Perform configuration ordering /*{{{*/
289// ---------------------------------------------------------------------
290/* This orders by depends only and produces an order which is suitable
291 for configuration */
292bool pkgOrderList::OrderConfigure()
293{
281daf46 294 FileList = 0;
727f18af 295 Primary = &pkgOrderList::DepConfigure;
6c139d6e
AL
296 Secondary = 0;
297 RevDepends = 0;
298 Remove = 0;
299 LoopCount = -1;
300 return DoRun();
301}
302 /*}}}*/
6c139d6e
AL
303// OrderList::Score - Score the package for sorting /*{{{*/
304// ---------------------------------------------------------------------
305/* Higher scores order earlier */
306int pkgOrderList::Score(PkgIterator Pkg)
307{
978844db
DK
308 // Removals should be done after we dealt with essentials
309 static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 100);
6c139d6e 310 if (Cache[Pkg].Delete() == true)
5e312de7
DK
311 return ScoreDelete;
312
281daf46
AL
313 // This should never happen..
314 if (Cache[Pkg].InstVerIter(Cache).end() == true)
315 return -1;
5e312de7
DK
316
317 static int const ScoreEssential = _config->FindI("OrderList::Score::Essential", 200);
318 static int const ScoreImmediate = _config->FindI("OrderList::Score::Immediate", 10);
319 static int const ScorePreDepends = _config->FindI("OrderList::Score::PreDepends", 50);
320
6c139d6e
AL
321 int Score = 0;
322 if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
5e312de7 323 Score += ScoreEssential;
6c139d6e 324
b2e465d6 325 if (IsFlag(Pkg,Immediate) == true)
5e312de7
DK
326 Score += ScoreImmediate;
327
328 for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
f7f0d6c7 329 D.end() == false; ++D)
6c139d6e
AL
330 if (D->Type == pkgCache::Dep::PreDepends)
331 {
5e312de7 332 Score += ScorePreDepends;
6c139d6e
AL
333 break;
334 }
5e312de7 335
6c139d6e 336 // Important Required Standard Optional Extra
6c139d6e 337 if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5)
69c2ecbd
DK
338 {
339 signed short PrioMap[] = {0,5,4,3,1,0};
6c139d6e 340 Score += PrioMap[Cache[Pkg].InstVerIter(Cache)->Priority];
69c2ecbd 341 }
6c139d6e
AL
342 return Score;
343}
344 /*}}}*/
345// OrderList::FileCmp - Compare by package file /*{{{*/
346// ---------------------------------------------------------------------
347/* This compares by the package file that the install version is in. */
348int pkgOrderList::FileCmp(PkgIterator A,PkgIterator B)
349{
350 if (Cache[A].Delete() == true && Cache[B].Delete() == true)
351 return 0;
352 if (Cache[A].Delete() == true)
353 return -1;
354 if (Cache[B].Delete() == true)
355 return 1;
356
357 if (Cache[A].InstVerIter(Cache).FileList().end() == true)
358 return -1;
281daf46 359 if (Cache[B].InstVerIter(Cache).FileList().end() == true)
6c139d6e
AL
360 return 1;
361
362 pkgCache::PackageFile *FA = Cache[A].InstVerIter(Cache).FileList().File();
363 pkgCache::PackageFile *FB = Cache[B].InstVerIter(Cache).FileList().File();
364 if (FA < FB)
365 return -1;
366 if (FA > FB)
367 return 1;
368 return 0;
369}
370 /*}}}*/
281daf46
AL
371// BoolCompare - Comparison function for two booleans /*{{{*/
372// ---------------------------------------------------------------------
373/* */
374static int BoolCompare(bool A,bool B)
375{
376 if (A == B)
377 return 0;
378 if (A == false)
379 return -1;
380 return 1;
381}
382 /*}}}*/
6c139d6e
AL
383// OrderList::OrderCompareA - Order the installation by op /*{{{*/
384// ---------------------------------------------------------------------
385/* This provides a first-pass sort of the list and gives a decent starting
386 point for further complete ordering. It is used by OrderUnpack only */
387int pkgOrderList::OrderCompareA(const void *a, const void *b)
388{
389 PkgIterator A(Me->Cache,*(Package **)a);
390 PkgIterator B(Me->Cache,*(Package **)b);
391
281daf46
AL
392 // We order packages with a set state toward the front
393 int Res;
7834cb57 394 if ((Res = BoolCompare(Me->IsNow(A),Me->IsNow(B))) != 0)
281daf46
AL
395 return -1*Res;
396
397 // We order missing files to toward the end
63d3141a 398/* if (Me->FileList != 0)
281daf46 399 {
2fd65468 400 if ((Res = BoolCompare(Me->IsMissing(A),
7834cb57 401 Me->IsMissing(B))) != 0)
2fd65468 402 return Res;
63d3141a 403 }*/
281daf46 404
6c139d6e
AL
405 if (A.State() != pkgCache::PkgIterator::NeedsNothing &&
406 B.State() == pkgCache::PkgIterator::NeedsNothing)
407 return -1;
408
409 if (A.State() == pkgCache::PkgIterator::NeedsNothing &&
410 B.State() != pkgCache::PkgIterator::NeedsNothing)
411 return 1;
412
413 int ScoreA = Me->Score(A);
414 int ScoreB = Me->Score(B);
5e312de7 415
6c139d6e
AL
416 if (ScoreA > ScoreB)
417 return -1;
418
419 if (ScoreA < ScoreB)
420 return 1;
421
422 return strcmp(A.Name(),B.Name());
423}
424 /*}}}*/
425// OrderList::OrderCompareB - Order the installation by source /*{{{*/
426// ---------------------------------------------------------------------
b2e465d6 427/* This orders by installation source. This is useful to handle
6c139d6e
AL
428 inter-source breaks */
429int pkgOrderList::OrderCompareB(const void *a, const void *b)
430{
431 PkgIterator A(Me->Cache,*(Package **)a);
432 PkgIterator B(Me->Cache,*(Package **)b);
433
434 if (A.State() != pkgCache::PkgIterator::NeedsNothing &&
435 B.State() == pkgCache::PkgIterator::NeedsNothing)
436 return -1;
437
438 if (A.State() == pkgCache::PkgIterator::NeedsNothing &&
439 B.State() != pkgCache::PkgIterator::NeedsNothing)
440 return 1;
441
442 int F = Me->FileCmp(A,B);
443 if (F != 0)
444 {
445 if (F > 0)
446 return -1;
447 return 1;
448 }
449
450 int ScoreA = Me->Score(A);
451 int ScoreB = Me->Score(B);
5e312de7 452
6c139d6e
AL
453 if (ScoreA > ScoreB)
454 return -1;
455
456 if (ScoreA < ScoreB)
457 return 1;
458
459 return strcmp(A.Name(),B.Name());
460}
461 /*}}}*/
6c139d6e
AL
462// OrderList::VisitDeps - Visit forward install dependencies /*{{{*/
463// ---------------------------------------------------------------------
464/* This calls the dependency function for the normal forwards dependencies
465 of the package */
466bool pkgOrderList::VisitDeps(DepFunc F,PkgIterator Pkg)
467{
468 if (F == 0 || Pkg.end() == true || Cache[Pkg].InstallVer == 0)
469 return true;
470
471 return (this->*F)(Cache[Pkg].InstVerIter(Cache).DependsList());
472}
473 /*}}}*/
474// OrderList::VisitRDeps - Visit reverse dependencies /*{{{*/
475// ---------------------------------------------------------------------
476/* This calls the dependency function for all of the normal reverse depends
477 of the package */
478bool pkgOrderList::VisitRDeps(DepFunc F,PkgIterator Pkg)
479{
480 if (F == 0 || Pkg.end() == true)
481 return true;
482
483 return (this->*F)(Pkg.RevDependsList());
484}
485 /*}}}*/
486// OrderList::VisitRProvides - Visit provides reverse dependencies /*{{{*/
487// ---------------------------------------------------------------------
488/* This calls the dependency function for all reverse dependencies
489 generated by the provides line on the package. */
490bool pkgOrderList::VisitRProvides(DepFunc F,VerIterator Ver)
491{
492 if (F == 0 || Ver.end() == true)
493 return true;
494
495 bool Res = true;
f7f0d6c7 496 for (PrvIterator P = Ver.ProvidesList(); P.end() == false; ++P)
6c139d6e 497 Res &= (this->*F)(P.ParentPkg().RevDependsList());
92a21ab5 498 return Res;
6c139d6e
AL
499}
500 /*}}}*/
501// OrderList::VisitProvides - Visit all of the providing packages /*{{{*/
502// ---------------------------------------------------------------------
05b64a6f
DK
503/* This routine calls visit on all providing packages.
504
505 If the dependency is negative it first visits packages which are
506 intended to be removed and after that all other packages.
507 It does so to avoid situations in which this package is used to
508 satisfy a (or-group/provides) dependency of another package which
509 could have been satisfied also by upgrading another package -
510 otherwise we have more broken packages dpkg needs to auto-
511 deconfigure and in very complicated situations it even decides
512 against it! */
3fb5f4e4 513bool pkgOrderList::VisitProvides(DepIterator D,bool Critical)
05b64a6f 514{
b2e465d6 515 SPtrArray<Version *> List = D.AllTargets();
05b64a6f 516 for (Version **I = List; *I != 0; ++I)
6c139d6e
AL
517 {
518 VerIterator Ver(Cache,*I);
519 PkgIterator Pkg = Ver.ParentPkg();
25be5a8f 520
05b64a6f
DK
521 if (D.IsNegative() == true && Cache[Pkg].Delete() == false)
522 continue;
523
25be5a8f 524 if (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)
6c139d6e 525 continue;
05b64a6f 526
359e46db 527 if (D.IsNegative() == false &&
b2e465d6 528 Cache[Pkg].InstallVer != *I)
6c139d6e 529 continue;
05b64a6f 530
359e46db 531 if (D.IsNegative() == true &&
b2e465d6 532 (Version *)Pkg.CurrentVer() != *I)
6c139d6e 533 continue;
05b64a6f 534
3fb5f4e4 535 // Skip over missing files
140fd43f 536 if (Critical == false && IsMissing(D.ParentPkg()) == true)
3fb5f4e4 537 continue;
25be5a8f 538
05b64a6f 539 if (VisitNode(Pkg, "Provides-1") == false)
6c139d6e 540 return false;
6c139d6e 541 }
05b64a6f
DK
542 if (D.IsNegative() == false)
543 return true;
544 for (Version **I = List; *I != 0; ++I)
545 {
546 VerIterator Ver(Cache,*I);
547 PkgIterator Pkg = Ver.ParentPkg();
548
549 if (Cache[Pkg].Delete() == true)
550 continue;
551
552 if (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)
553 continue;
554
555 if ((Version *)Pkg.CurrentVer() != *I)
556 continue;
557
3fb5f4e4 558 // Skip over missing files
140fd43f 559 if (Critical == false && IsMissing(D.ParentPkg()) == true)
3fb5f4e4 560 continue;
25be5a8f 561
05b64a6f 562 if (VisitNode(Pkg, "Provides-2") == false)
6c139d6e 563 return false;
6c139d6e 564 }
05b64a6f 565
6c139d6e
AL
566 return true;
567}
568 /*}}}*/
569// OrderList::VisitNode - Recursive ordering director /*{{{*/
570// ---------------------------------------------------------------------
571/* This is the core ordering routine. It calls the set dependency
572 consideration functions which then potentialy call this again. Finite
1e3f4083 573 depth is achieved through the colouring mechinism. */
3b8d1773 574bool pkgOrderList::VisitNode(PkgIterator Pkg, char const* from)
6c139d6e 575{
1e3f4083 576 // Looping or irrelevant.
e1b74f61 577 // This should probably trancend not installed packages
6c139d6e
AL
578 if (Pkg.end() == true || IsFlag(Pkg,Added) == true ||
579 IsFlag(Pkg,AddPending) == true || IsFlag(Pkg,InList) == false)
580 return true;
581
b2e465d6
AL
582 if (Debug == true)
583 {
584 for (int j = 0; j != Depth; j++) clog << ' ';
3b8d1773 585 clog << "Visit " << Pkg.FullName() << " from " << from << endl;
b2e465d6
AL
586 }
587
6c139d6e
AL
588 Depth++;
589
590 // Color grey
591 Flag(Pkg,AddPending);
592
593 DepFunc Old = Primary;
594
595 // Perform immedate configuration of the package if so flagged.
727f18af
AL
596 if (IsFlag(Pkg,Immediate) == true && Primary != &pkgOrderList::DepUnPackPre)
597 Primary = &pkgOrderList::DepUnPackPreD;
281daf46
AL
598
599 if (IsNow(Pkg) == true)
6c139d6e 600 {
281daf46
AL
601 bool Res = true;
602 if (Cache[Pkg].Delete() == false)
603 {
604 // Primary
605 Res &= Res && VisitDeps(Primary,Pkg);
606 Res &= Res && VisitRDeps(Primary,Pkg);
607 Res &= Res && VisitRProvides(Primary,Pkg.CurrentVer());
608 Res &= Res && VisitRProvides(Primary,Cache[Pkg].InstVerIter(Cache));
609
610 // RevDep
611 Res &= Res && VisitRDeps(RevDepends,Pkg);
612 Res &= Res && VisitRProvides(RevDepends,Pkg.CurrentVer());
613 Res &= Res && VisitRProvides(RevDepends,Cache[Pkg].InstVerIter(Cache));
614
615 // Secondary
616 Res &= Res && VisitDeps(Secondary,Pkg);
617 Res &= Res && VisitRDeps(Secondary,Pkg);
618 Res &= Res && VisitRProvides(Secondary,Pkg.CurrentVer());
619 Res &= Res && VisitRProvides(Secondary,Cache[Pkg].InstVerIter(Cache));
620 }
621 else
622 {
623 // RevDep
624 Res &= Res && VisitRDeps(Remove,Pkg);
625 Res &= Res && VisitRProvides(Remove,Pkg.CurrentVer());
626 }
6c139d6e 627 }
281daf46 628
6c139d6e
AL
629 if (IsFlag(Pkg,Added) == false)
630 {
631 Flag(Pkg,Added,Added | AddPending);
63d3141a
AL
632 if (IsFlag(Pkg,After) == true)
633 *AfterEnd++ = Pkg;
634 else
635 *End++ = Pkg;
6c139d6e
AL
636 }
637
638 Primary = Old;
639 Depth--;
6c139d6e 640
b2e465d6
AL
641 if (Debug == true)
642 {
643 for (int j = 0; j != Depth; j++) clog << ' ';
70ae2409 644 clog << "Leave " << Pkg.FullName() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;
b2e465d6
AL
645 }
646
6c139d6e
AL
647 return true;
648}
649 /*}}}*/
6c139d6e
AL
650// OrderList::DepUnPackCrit - Critical UnPacking ordering /*{{{*/
651// ---------------------------------------------------------------------
652/* Critical unpacking ordering strives to satisfy Conflicts: and
653 PreDepends: only. When a prdepends is encountered the Primary
654 DepFunc is changed to be DepUnPackPreD.
655
656 Loops are preprocessed and logged. */
657bool pkgOrderList::DepUnPackCrit(DepIterator D)
658{
f7f0d6c7 659 for (; D.end() == false; ++D)
6c139d6e
AL
660 {
661 if (D.Reverse() == true)
662 {
663 /* Reverse depenanices are only interested in conflicts,
664 predepend breakage is ignored here */
b2e465d6
AL
665 if (D->Type != pkgCache::Dep::Conflicts &&
666 D->Type != pkgCache::Dep::Obsoletes)
6c139d6e
AL
667 continue;
668
669 // Duplication elimination, consider only the current version
670 if (D.ParentPkg().CurrentVer() != D.ParentVer())
671 continue;
672
673 /* For reverse dependencies we wish to check if the
674 dependency is satisifed in the install state. The
675 target package (caller) is going to be in the installed
676 state. */
677 if (CheckDep(D) == true)
678 continue;
679
3b8d1773 680 if (VisitNode(D.ParentPkg(), "UnPackCrit") == false)
6c139d6e
AL
681 return false;
682 }
683 else
684 {
685 /* Forward critical dependencies MUST be correct before the
686 package can be unpacked. */
359e46db 687 if (D.IsNegative() == false &&
b2e465d6 688 D->Type != pkgCache::Dep::PreDepends)
6c139d6e
AL
689 continue;
690
691 /* We wish to check if the dep is okay in the now state of the
692 target package against the install state of this package. */
693 if (CheckDep(D) == true)
694 {
695 /* We want to catch predepends loops with the code below.
696 Conflicts loops that are Dep OK are ignored */
697 if (IsFlag(D.TargetPkg(),AddPending) == false ||
698 D->Type != pkgCache::Dep::PreDepends)
699 continue;
700 }
701
702 // This is the loop detection
703 if (IsFlag(D.TargetPkg(),Added) == true ||
704 IsFlag(D.TargetPkg(),AddPending) == true)
705 {
706 if (IsFlag(D.TargetPkg(),AddPending) == true)
707 AddLoop(D);
708 continue;
709 }
710
711 /* Predepends require a special ordering stage, they must have
712 all dependents installed as well */
713 DepFunc Old = Primary;
714 bool Res = false;
715 if (D->Type == pkgCache::Dep::PreDepends)
727f18af 716 Primary = &pkgOrderList::DepUnPackPreD;
3fb5f4e4 717 Res = VisitProvides(D,true);
6c139d6e
AL
718 Primary = Old;
719 if (Res == false)
720 return false;
721 }
722 }
723 return true;
724}
92fcbfc1 725 /*}}}*/
6c139d6e
AL
726// OrderList::DepUnPackPreD - Critical UnPacking ordering with depends /*{{{*/
727// ---------------------------------------------------------------------
728/* Critical PreDepends (also configure immediate and essential) strives to
729 ensure not only that all conflicts+predepends are met but that this
92fcbfc1 730 package will be immediately configurable when it is unpacked.
6c139d6e
AL
731 Loops are preprocessed and logged. */
732bool pkgOrderList::DepUnPackPreD(DepIterator D)
733{
734 if (D.Reverse() == true)
735 return DepUnPackCrit(D);
736
f7f0d6c7 737 for (; D.end() == false; ++D)
6c139d6e
AL
738 {
739 if (D.IsCritical() == false)
740 continue;
741
742 /* We wish to check if the dep is okay in the now state of the
743 target package against the install state of this package. */
744 if (CheckDep(D) == true)
745 {
746 /* We want to catch predepends loops with the code below.
747 Conflicts loops that are Dep OK are ignored */
748 if (IsFlag(D.TargetPkg(),AddPending) == false ||
749 D->Type != pkgCache::Dep::PreDepends)
750 continue;
751 }
752
753 // This is the loop detection
754 if (IsFlag(D.TargetPkg(),Added) == true ||
755 IsFlag(D.TargetPkg(),AddPending) == true)
756 {
757 if (IsFlag(D.TargetPkg(),AddPending) == true)
758 AddLoop(D);
759 continue;
760 }
761
3fb5f4e4 762 if (VisitProvides(D,true) == false)
6c139d6e
AL
763 return false;
764 }
765 return true;
766}
767 /*}}}*/
768// OrderList::DepUnPackPre - Critical Predepends ordering /*{{{*/
769// ---------------------------------------------------------------------
770/* Critical PreDepends (also configure immediate and essential) strives to
771 ensure not only that all conflicts+predepends are met but that this
772 package will be immediately configurable when it is unpacked.
773
774 Loops are preprocessed and logged. All loops will be fatal. */
775bool pkgOrderList::DepUnPackPre(DepIterator D)
776{
777 if (D.Reverse() == true)
778 return true;
779
f7f0d6c7 780 for (; D.end() == false; ++D)
6c139d6e
AL
781 {
782 /* Only consider the PreDepends or Depends. Depends are only
783 considered at the lowest depth or in the case of immediate
784 configure */
785 if (D->Type != pkgCache::Dep::PreDepends)
786 {
787 if (D->Type == pkgCache::Dep::Depends)
788 {
789 if (Depth == 1 && IsFlag(D.ParentPkg(),Immediate) == false)
790 continue;
791 }
792 else
793 continue;
794 }
b2e465d6 795
6c139d6e
AL
796 /* We wish to check if the dep is okay in the now state of the
797 target package against the install state of this package. */
798 if (CheckDep(D) == true)
799 {
800 /* We want to catch predepends loops with the code below.
801 Conflicts loops that are Dep OK are ignored */
802 if (IsFlag(D.TargetPkg(),AddPending) == false)
803 continue;
804 }
b2e465d6 805
6c139d6e
AL
806 // This is the loop detection
807 if (IsFlag(D.TargetPkg(),Added) == true ||
808 IsFlag(D.TargetPkg(),AddPending) == true)
809 {
810 if (IsFlag(D.TargetPkg(),AddPending) == true)
811 AddLoop(D);
812 continue;
813 }
814
3fb5f4e4 815 if (VisitProvides(D,true) == false)
6c139d6e
AL
816 return false;
817 }
818 return true;
819}
820 /*}}}*/
821// OrderList::DepUnPackDep - Reverse dependency considerations /*{{{*/
822// ---------------------------------------------------------------------
823/* Reverse dependencies are considered to determine if unpacking this
824 package will break any existing dependencies. If so then those
825 packages are ordered before this one so that they are in the
826 UnPacked state.
827
828 The forwards depends loop is designed to bring the packages dependents
829 close to the package. This helps reduce deconfigure time.
830
1e3f4083 831 Loops are irrelevant to this. */
6c139d6e
AL
832bool pkgOrderList::DepUnPackDep(DepIterator D)
833{
834
f7f0d6c7 835 for (; D.end() == false; ++D)
6c139d6e
AL
836 if (D.IsCritical() == true)
837 {
838 if (D.Reverse() == true)
839 {
840 /* Duplication prevention. We consider rev deps only on
841 the current version, a not installed package
842 cannot break */
843 if (D.ParentPkg()->CurrentVer == 0 ||
844 D.ParentPkg().CurrentVer() != D.ParentVer())
845 continue;
846
1e3f4083 847 // The dep will not break so it is irrelevant.
6c139d6e
AL
848 if (CheckDep(D) == true)
849 continue;
850
3fb5f4e4
AL
851 // Skip over missing files
852 if (IsMissing(D.ParentPkg()) == true)
853 continue;
854
3b8d1773 855 if (VisitNode(D.ParentPkg(), "UnPackDep-Parent") == false)
6c139d6e
AL
856 return false;
857 }
858 else
308c7d30 859 {
6c139d6e 860 if (D->Type == pkgCache::Dep::Depends)
3fb5f4e4 861 if (VisitProvides(D,false) == false)
6c139d6e 862 return false;
308c7d30
IJ
863
864 if (D->Type == pkgCache::Dep::DpkgBreaks)
865 {
866 if (CheckDep(D) == true)
867 continue;
868
3b8d1773 869 if (VisitNode(D.TargetPkg(), "UnPackDep-Target") == false)
308c7d30
IJ
870 return false;
871 }
872 }
6c139d6e
AL
873 }
874 return true;
875}
876 /*}}}*/
877// OrderList::DepConfigure - Configuration ordering /*{{{*/
878// ---------------------------------------------------------------------
879/* Configuration only ordering orders by the Depends: line only. It
880 orders configuration so that when a package comes to be configured it's
881 dependents are configured.
882
883 Loops are ingored. Depends loop entry points are chaotic. */
884bool pkgOrderList::DepConfigure(DepIterator D)
885{
886 // Never consider reverse configuration dependencies.
887 if (D.Reverse() == true)
888 return true;
889
f7f0d6c7 890 for (; D.end() == false; ++D)
6c139d6e 891 if (D->Type == pkgCache::Dep::Depends)
3fb5f4e4 892 if (VisitProvides(D,false) == false)
6c139d6e
AL
893 return false;
894 return true;
895}
896 /*}}}*/
897// OrderList::DepRemove - Removal ordering /*{{{*/
898// ---------------------------------------------------------------------
2de71577
DK
899/* Checks all given dependencies if they are broken by the remove of a
900 package and if so fix it by visiting another provider or or-group
901 member to ensure that the dependee keeps working which is especially
902 important for Immediate packages like e.g. those depending on an
903 awk implementation. If the dependency can't be fixed with another
904 package this means an upgrade of the package will solve the problem. */
905bool pkgOrderList::DepRemove(DepIterator Broken)
6c139d6e 906{
2de71577 907 if (Broken.Reverse() == false)
6c139d6e 908 return true;
2de71577
DK
909
910 for (; Broken.end() == false; ++Broken)
911 {
912 if (Broken->Type != pkgCache::Dep::Depends &&
913 Broken->Type != pkgCache::Dep::PreDepends)
914 continue;
915
916 PkgIterator BrokenPkg = Broken.ParentPkg();
917 // uninstalled packages can't break via a remove
918 if (BrokenPkg->CurrentVer == 0)
919 continue;
920
921 // if its already added, we can't do anything useful
922 if (IsFlag(BrokenPkg, AddPending) == true || IsFlag(BrokenPkg, Added) == true)
923 continue;
924
925 // if the dependee is going to be removed, visit it now
926 if (Cache[BrokenPkg].Delete() == true)
927 return VisitNode(BrokenPkg, "Remove-Dependee");
928
929 // The package stays around, so find out how this is possible
930 for (DepIterator D = BrokenPkg.CurrentVer().DependsList(); D.end() == false;)
6c139d6e 931 {
2de71577
DK
932 // only important or-groups need fixing
933 if (D->Type != pkgCache::Dep::Depends &&
934 D->Type != pkgCache::Dep::PreDepends)
935 {
936 ++D;
6c139d6e 937 continue;
2de71577 938 }
6c139d6e 939
2de71577
DK
940 // Start is the beginning of the or-group, D is the first one after or
941 DepIterator Start = D;
942 bool foundBroken = false;
943 for (bool LastOR = true; D.end() == false && LastOR == true; ++D)
6c139d6e 944 {
2de71577
DK
945 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
946 if (D == Broken)
947 foundBroken = true;
6c139d6e
AL
948 }
949
2de71577
DK
950 // this or-group isn't the broken one: keep searching
951 if (foundBroken == false)
6c139d6e 952 continue;
2de71577
DK
953
954 // iterate over all members of the or-group searching for a ready replacement
955 bool readyReplacement = false;
956 for (DepIterator OrMember = Start; OrMember != D && readyReplacement == false; ++OrMember)
957 {
958 Version ** Replacements = OrMember.AllTargets();
959 for (Version **R = Replacements; *R != 0; ++R)
960 {
961 VerIterator Ver(Cache,*R);
962 // only currently installed packages can be a replacement
963 PkgIterator RPkg = Ver.ParentPkg();
964 if (RPkg.CurrentVer() != Ver)
965 continue;
966
967 // packages going to be removed can't be a replacement
968 if (Cache[RPkg].Delete() == true)
969 continue;
970
971 readyReplacement = true;
972 break;
973 }
974 delete[] Replacements;
6c139d6e
AL
975 }
976
2de71577
DK
977 // something else is ready to take over, do nothing
978 if (readyReplacement == true)
979 continue;
980
981 // see if we can visit a replacement
982 bool visitReplacement = false;
983 for (DepIterator OrMember = Start; OrMember != D && visitReplacement == false; ++OrMember)
966640d8 984 {
2de71577
DK
985 Version ** Replacements = OrMember.AllTargets();
986 for (Version **R = Replacements; *R != 0; ++R)
966640d8 987 {
2de71577
DK
988 VerIterator Ver(Cache,*R);
989 // consider only versions we plan to install
990 PkgIterator RPkg = Ver.ParentPkg();
991 if (Cache[RPkg].Install() == false || Cache[RPkg].InstallVer != Ver)
966640d8 992 continue;
966640d8 993
2de71577
DK
994 // loops are not going to help us, so don't create them
995 if (IsFlag(RPkg, AddPending) == true)
966640d8 996 continue;
2de71577
DK
997
998 if (IsMissing(RPkg) == true)
999 continue;
1000
1001 visitReplacement = true;
1002 if (IsFlag(BrokenPkg, Immediate) == false)
966640d8 1003 {
2de71577 1004 if (VisitNode(RPkg, "Remove-Rep") == true)
966640d8 1005 break;
966640d8 1006 }
2de71577 1007 else
966640d8 1008 {
2de71577
DK
1009 Flag(RPkg, Immediate);
1010 if (VisitNode(RPkg, "Remove-ImmRep") == true)
543b0abf 1011 break;
966640d8 1012 }
2de71577 1013 visitReplacement = false;
966640d8 1014 }
2de71577 1015 delete[] Replacements;
966640d8 1016 }
2de71577 1017 if (visitReplacement == true)
3fb5f4e4 1018 continue;
2de71577
DK
1019
1020 // the broken package in current version can't be fixed, so install new version
1021 if (IsMissing(BrokenPkg) == true)
1022 break;
1023
1024 if (VisitNode(BrokenPkg, "Remove-Upgrade") == false)
6c139d6e
AL
1025 return false;
1026 }
2de71577
DK
1027 }
1028
6c139d6e
AL
1029 return true;
1030}
1031 /*}}}*/
6c139d6e
AL
1032// OrderList::AddLoop - Add a loop to the loop list /*{{{*/
1033// ---------------------------------------------------------------------
1034/* We record the loops. This is a relic since loop breaking is done
1035 genericaly as part of the safety routines. */
1036bool pkgOrderList::AddLoop(DepIterator D)
1037{
1038 if (LoopCount < 0 || LoopCount >= 20)
1039 return false;
1040
1041 // Skip dups
1042 if (LoopCount != 0)
1043 {
1044 if (Loops[LoopCount - 1].ParentPkg() == D.ParentPkg() ||
1045 Loops[LoopCount - 1].TargetPkg() == D.ParentPkg())
1046 return true;
1047 }
1048
1049 Loops[LoopCount++] = D;
1050
1051 // Mark the packages as being part of a loop.
e2a5ff0c
CB
1052 //Flag(D.TargetPkg(),Loop);
1053 //Flag(D.ParentPkg(),Loop);
e7ecc218
CB
1054 /* This is currently disabled because the Loop flag is being used for
1055 loop management in the package manager. Check the orderlist.h file for more info */
6c139d6e
AL
1056 return true;
1057}
1058 /*}}}*/
1059// OrderList::WipeFlags - Unset the given flags from all packages /*{{{*/
1060// ---------------------------------------------------------------------
1061/* */
1062void pkgOrderList::WipeFlags(unsigned long F)
1063{
b2e465d6 1064 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
1065 for (unsigned long I = 0; I != Size; I++)
1066 Flags[I] &= ~F;
1067}
1068 /*}}}*/
1069// OrderList::CheckDep - Check a dependency for truth /*{{{*/
1070// ---------------------------------------------------------------------
1071/* This performs a complete analysis of the dependency wrt to the
1072 current add list. It returns true if after all events are
1073 performed it is still true. This sort of routine can be approximated
1074 by examining the DepCache, however in convoluted cases of provides
1075 this fails to produce a suitable result. */
1076bool pkgOrderList::CheckDep(DepIterator D)
1077{
b2e465d6 1078 SPtrArray<Version *> List = D.AllTargets();
63d3141a 1079 bool Hit = false;
6c139d6e
AL
1080 for (Version **I = List; *I != 0; I++)
1081 {
1082 VerIterator Ver(Cache,*I);
1083 PkgIterator Pkg = Ver.ParentPkg();
1084
1085 /* The meaning of Added and AddPending is subtle. AddPending is
1086 an indication that the package is looping. Because of the
1087 way ordering works Added means the package will be unpacked
1088 before this one and AddPending means after. It is therefore
1089 correct to ignore AddPending in all cases, but that exposes
63d3141a
AL
1090 reverse-ordering loops which should be ignored. */
1091 if (IsFlag(Pkg,Added) == true ||
6c139d6e
AL
1092 (IsFlag(Pkg,AddPending) == true && D.Reverse() == true))
1093 {
1094 if (Cache[Pkg].InstallVer != *I)
1095 continue;
1096 }
1097 else
1098 if ((Version *)Pkg.CurrentVer() != *I ||
1099 Pkg.State() != PkgIterator::NeedsNothing)
1100 continue;
b2e465d6 1101
6c139d6e
AL
1102 /* Conflicts requires that all versions are not present, depends
1103 just needs one */
359e46db 1104 if (D.IsNegative() == false)
63d3141a 1105 {
cfcdf7fe 1106 // ignore provides by older versions of this package
15657fcc
MV
1107 if (((D.Reverse() == false && Pkg == D.ParentPkg()) ||
1108 (D.Reverse() == true && Pkg == D.TargetPkg())) &&
1109 Cache[Pkg].InstallVer != *I)
1110 continue;
1111
63d3141a
AL
1112 /* Try to find something that does not have the after flag set
1113 if at all possible */
1114 if (IsFlag(Pkg,After) == true)
1115 {
1116 Hit = true;
1117 continue;
1118 }
1119
6c139d6e 1120 return true;
63d3141a 1121 }
6c139d6e 1122 else
63d3141a
AL
1123 {
1124 if (IsFlag(Pkg,After) == true)
1125 Flag(D.ParentPkg(),After);
1126
6c139d6e 1127 return false;
63d3141a 1128 }
6c139d6e 1129 }
63d3141a
AL
1130
1131 // We found a hit, but it had the after flag set
1132 if (Hit == true && D->Type == pkgCache::Dep::PreDepends)
1133 {
1134 Flag(D.ParentPkg(),After);
1135 return true;
1136 }
1137
6c139d6e
AL
1138 /* Conflicts requires that all versions are not present, depends
1139 just needs one */
b2e465d6
AL
1140 if (D->Type == pkgCache::Dep::Conflicts ||
1141 D->Type == pkgCache::Dep::Obsoletes)
6c139d6e
AL
1142 return true;
1143 return false;
1144}
1145 /*}}}*/