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