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