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