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