]>
git.saurik.com Git - apt.git/blob - apt-pkg/orderlist.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: orderlist.cc,v 1.2 1998/07/12 23:58:28 jgg Exp $
4 /* ######################################################################
6 Order List - Represents and Manipulates an ordered list of packages.
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 usefull 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.
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
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
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
34 And some features that are valuable for unpacking ordering.
35 f1) Unpacking a new package should advoid breaking dependencies of
37 f2) Removal should not require a force, corrolory of f1
38 f3) Unpacking should order by depends rather than fall back to random
41 Each of the features can be enabled in the sorting routine at an
42 arbitary priority to give quite abit of control over the final unpacking
45 The rules listed above my 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.
49 ##################################################################### */
51 // Include Files /*{{{*/
53 #pragma implementation "apt-pkg/orderlist.h"
55 #include <apt-pkg/orderlist.h>
56 #include <apt-pkg/depcache.h>
57 #include <apt-pkg/error.h>
58 #include <apt-pkg/version.h>
61 pkgOrderList
*pkgOrderList::Me
= 0;
63 // OrderList::pkgOrderList - Constructor /*{{{*/
64 // ---------------------------------------------------------------------
66 pkgOrderList::pkgOrderList(pkgDepCache
&Cache
) : Cache(Cache
)
74 /* Construct the arrays, egcs 1.0.1 bug requires the package count
76 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
77 Flags
= new unsigned char[Size
];
78 End
= List
= new Package
*[Size
];
79 memset(Flags
,0,sizeof(*Flags
)*Size
);
82 // OrderList::~pkgOrderList - Destructor /*{{{*/
83 // ---------------------------------------------------------------------
85 pkgOrderList::~pkgOrderList()
92 // OrderList::DoRun - Does an order run /*{{{*/
93 // ---------------------------------------------------------------------
94 /* The caller is expeted to have setup the desired probe state */
95 bool pkgOrderList::DoRun()
98 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
99 Package
**NList
= new Package
*[Size
];
102 WipeFlags(Added
| AddPending
| Loop
| InList
);
104 for (iterator I
= List
; I
!= End
; I
++)
107 // Rebuild the main list into the temp list.
108 iterator OldEnd
= End
;
110 for (iterator I
= List
; I
!= OldEnd
; I
++)
111 if (VisitNode(PkgIterator(Cache
,*I
)) == false)
118 // Swap the main list to the new list
124 // OrderList::OrderCritical - Perform critical unpacking ordering /*{{{*/
125 // ---------------------------------------------------------------------
126 /* This performs predepends and immediate configuration ordering only.
127 This is termed critical unpacking ordering. Any loops that form are
128 fatal and indicate that the packages cannot be installed. */
129 bool pkgOrderList::OrderCritical()
131 Primary
= &DepUnPackPre
;
139 qsort(List
,End
- List
,sizeof(*List
),&OrderCompareB
);
141 if (DoRun() == false)
145 return _error
->Error("Fatal, predepends looping detected");
149 // OrderList::OrderUnpack - Perform complete unpacking ordering /*{{{*/
150 // ---------------------------------------------------------------------
151 /* This performs complete unpacking ordering and creates an order that is
152 suitable for unpacking */
153 bool pkgOrderList::OrderUnpack()
155 Primary
= &DepUnPackCrit
;
156 Secondary
= &DepConfigure
;
157 RevDepends
= &DepUnPackDep
;
163 qsort(List
,End
- List
,sizeof(*List
),&OrderCompareA
);
165 if (DoRun() == false)
169 if (DoRun() == false)
174 Remove
= 0; // Otherwise the libreadline remove problem occures
175 if (DoRun() == false)
179 Primary
= &DepUnPackPre
;
180 if (DoRun() == false)
183 /* cout << "----------END" << endl;
185 for (iterator I = List; I != End; I++)
187 PkgIterator P(Cache,*I);
188 cout << P.Name() << endl;
194 // OrderList::OrderConfigure - Perform configuration ordering /*{{{*/
195 // ---------------------------------------------------------------------
196 /* This orders by depends only and produces an order which is suitable
198 bool pkgOrderList::OrderConfigure()
200 Primary
= &DepConfigure
;
209 // OrderList::Score - Score the package for sorting /*{{{*/
210 // ---------------------------------------------------------------------
211 /* Higher scores order earlier */
212 int pkgOrderList::Score(PkgIterator Pkg
)
214 // Removal is always done first
215 if (Cache
[Pkg
].Delete() == true)
219 if ((Pkg
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
222 for (DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList();
223 D
.end() == false; D
++)
224 if (D
->Type
== pkgCache::Dep::PreDepends
)
230 // Important Required Standard Optional Extra
231 signed short PrioMap
[] = {0,5,4,3,1,0};
232 if (Cache
[Pkg
].InstVerIter(Cache
)->Priority
<= 5)
233 Score
+= PrioMap
[Cache
[Pkg
].InstVerIter(Cache
)->Priority
];
237 // OrderList::FileCmp - Compare by package file /*{{{*/
238 // ---------------------------------------------------------------------
239 /* This compares by the package file that the install version is in. */
240 int pkgOrderList::FileCmp(PkgIterator A
,PkgIterator B
)
242 if (Cache
[A
].Delete() == true && Cache
[B
].Delete() == true)
244 if (Cache
[A
].Delete() == true)
246 if (Cache
[B
].Delete() == true)
249 if (Cache
[A
].InstVerIter(Cache
).FileList().end() == true)
251 if (Cache
[A
].InstVerIter(Cache
).FileList().end() == true)
254 pkgCache::PackageFile
*FA
= Cache
[A
].InstVerIter(Cache
).FileList().File();
255 pkgCache::PackageFile
*FB
= Cache
[B
].InstVerIter(Cache
).FileList().File();
263 // OrderList::OrderCompareA - Order the installation by op /*{{{*/
264 // ---------------------------------------------------------------------
265 /* This provides a first-pass sort of the list and gives a decent starting
266 point for further complete ordering. It is used by OrderUnpack only */
267 int pkgOrderList::OrderCompareA(const void *a
, const void *b
)
269 PkgIterator
A(Me
->Cache
,*(Package
**)a
);
270 PkgIterator
B(Me
->Cache
,*(Package
**)b
);
272 if (A
.State() != pkgCache::PkgIterator::NeedsNothing
&&
273 B
.State() == pkgCache::PkgIterator::NeedsNothing
)
276 if (A
.State() == pkgCache::PkgIterator::NeedsNothing
&&
277 B
.State() != pkgCache::PkgIterator::NeedsNothing
)
280 int ScoreA
= Me
->Score(A
);
281 int ScoreB
= Me
->Score(B
);
288 return strcmp(A
.Name(),B
.Name());
291 // OrderList::OrderCompareB - Order the installation by source /*{{{*/
292 // ---------------------------------------------------------------------
293 /* This orders by installation source. This is usefull to handle
294 inter-source breaks */
295 int pkgOrderList::OrderCompareB(const void *a
, const void *b
)
297 PkgIterator
A(Me
->Cache
,*(Package
**)a
);
298 PkgIterator
B(Me
->Cache
,*(Package
**)b
);
300 if (A
.State() != pkgCache::PkgIterator::NeedsNothing
&&
301 B
.State() == pkgCache::PkgIterator::NeedsNothing
)
304 if (A
.State() == pkgCache::PkgIterator::NeedsNothing
&&
305 B
.State() != pkgCache::PkgIterator::NeedsNothing
)
308 int F
= Me
->FileCmp(A
,B
);
316 int ScoreA
= Me
->Score(A
);
317 int ScoreB
= Me
->Score(B
);
324 return strcmp(A
.Name(),B
.Name());
328 // OrderList::VisitDeps - Visit forward install dependencies /*{{{*/
329 // ---------------------------------------------------------------------
330 /* This calls the dependency function for the normal forwards dependencies
332 bool pkgOrderList::VisitDeps(DepFunc F
,PkgIterator Pkg
)
334 if (F
== 0 || Pkg
.end() == true || Cache
[Pkg
].InstallVer
== 0)
337 return (this->*F
)(Cache
[Pkg
].InstVerIter(Cache
).DependsList());
340 // OrderList::VisitRDeps - Visit reverse dependencies /*{{{*/
341 // ---------------------------------------------------------------------
342 /* This calls the dependency function for all of the normal reverse depends
344 bool pkgOrderList::VisitRDeps(DepFunc F
,PkgIterator Pkg
)
346 if (F
== 0 || Pkg
.end() == true)
349 return (this->*F
)(Pkg
.RevDependsList());
352 // OrderList::VisitRProvides - Visit provides reverse dependencies /*{{{*/
353 // ---------------------------------------------------------------------
354 /* This calls the dependency function for all reverse dependencies
355 generated by the provides line on the package. */
356 bool pkgOrderList::VisitRProvides(DepFunc F
,VerIterator Ver
)
358 if (F
== 0 || Ver
.end() == true)
362 for (PrvIterator P
= Ver
.ProvidesList(); P
.end() == false; P
++)
363 Res
&= (this->*F
)(P
.ParentPkg().RevDependsList());
367 // OrderList::VisitProvides - Visit all of the providing packages /*{{{*/
368 // ---------------------------------------------------------------------
369 /* This routine calls visit on all providing packages. */
370 bool pkgOrderList::VisitProvides(DepIterator D
)
372 Version
**List
= D
.AllTargets();
373 for (Version
**I
= List
; *I
!= 0; I
++)
375 VerIterator
Ver(Cache
,*I
);
376 PkgIterator Pkg
= Ver
.ParentPkg();
378 if (Cache
[Pkg
].Keep() == true)
381 if (D
->Type
!= pkgCache::Dep::Conflicts
&& Cache
[Pkg
].InstallVer
!= *I
)
384 if (D
->Type
== pkgCache::Dep::Conflicts
&& (Version
*)Pkg
.CurrentVer() != *I
)
387 if (VisitNode(Pkg
) == false)
397 // OrderList::VisitNode - Recursive ordering director /*{{{*/
398 // ---------------------------------------------------------------------
399 /* This is the core ordering routine. It calls the set dependency
400 consideration functions which then potentialy call this again. Finite
401 depth is achived through the colouring mechinism. */
402 bool pkgOrderList::VisitNode(PkgIterator Pkg
)
404 // Looping or irrelevent.
405 if (Pkg
.end() == true || IsFlag(Pkg
,Added
) == true ||
406 IsFlag(Pkg
,AddPending
) == true || IsFlag(Pkg
,InList
) == false)
409 /* for (int j = 0; j != Depth; j++) cout << ' ';
410 cout << "Visit " << Pkg.Name() << endl;*/
414 Flag(Pkg
,AddPending
);
416 DepFunc Old
= Primary
;
418 // Perform immedate configuration of the package if so flagged.
419 if (IsFlag(Pkg
,Immediate
) == true && Primary
!= &DepUnPackPre
)
420 Primary
= &DepUnPackPreD
;
423 if (Cache
[Pkg
].Delete() == false)
426 Res
&= Res
&& VisitDeps(Primary
,Pkg
);
427 Res
&= Res
&& VisitRDeps(Primary
,Pkg
);
428 Res
&= Res
&& VisitRProvides(Primary
,Pkg
.CurrentVer());
429 Res
&= Res
&& VisitRProvides(Primary
,Cache
[Pkg
].InstVerIter(Cache
));
432 Res
&= Res
&& VisitRDeps(RevDepends
,Pkg
);
433 Res
&= Res
&& VisitRProvides(RevDepends
,Pkg
.CurrentVer());
434 Res
&= Res
&& VisitRProvides(RevDepends
,Cache
[Pkg
].InstVerIter(Cache
));
437 Res
&= Res
&& VisitDeps(Secondary
,Pkg
);
438 Res
&= Res
&& VisitRDeps(Secondary
,Pkg
);
439 Res
&= Res
&& VisitRProvides(Secondary
,Pkg
.CurrentVer());
440 Res
&= Res
&& VisitRProvides(Secondary
,Cache
[Pkg
].InstVerIter(Cache
));
445 Res
&= Res
&& VisitRDeps(Remove
,Pkg
);
446 Res
&= Res
&& VisitRProvides(Remove
,Pkg
.CurrentVer());
449 if (IsFlag(Pkg
,Added
) == false)
451 Flag(Pkg
,Added
,Added
| AddPending
);
459 /* for (int j = 0; j != Depth; j++) cout << ' ';
460 cout << "Leave " << Pkg.Name() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;*/
466 // OrderList::DepUnPackCrit - Critical UnPacking ordering /*{{{*/
467 // ---------------------------------------------------------------------
468 /* Critical unpacking ordering strives to satisfy Conflicts: and
469 PreDepends: only. When a prdepends is encountered the Primary
470 DepFunc is changed to be DepUnPackPreD.
472 Loops are preprocessed and logged. */
473 bool pkgOrderList::DepUnPackCrit(DepIterator D
)
475 for (; D
.end() == false; D
++)
477 if (D
.Reverse() == true)
479 /* Reverse depenanices are only interested in conflicts,
480 predepend breakage is ignored here */
481 if (D
->Type
!= pkgCache::Dep::Conflicts
)
484 // Duplication elimination, consider only the current version
485 if (D
.ParentPkg().CurrentVer() != D
.ParentVer())
488 /* For reverse dependencies we wish to check if the
489 dependency is satisifed in the install state. The
490 target package (caller) is going to be in the installed
492 if (CheckDep(D
) == true)
495 if (VisitNode(D
.ParentPkg()) == false)
500 /* Forward critical dependencies MUST be correct before the
501 package can be unpacked. */
502 if (D
->Type
!= pkgCache::Dep::Conflicts
&& D
->Type
!= pkgCache::Dep::PreDepends
)
505 /* We wish to check if the dep is okay in the now state of the
506 target package against the install state of this package. */
507 if (CheckDep(D
) == true)
509 /* We want to catch predepends loops with the code below.
510 Conflicts loops that are Dep OK are ignored */
511 if (IsFlag(D
.TargetPkg(),AddPending
) == false ||
512 D
->Type
!= pkgCache::Dep::PreDepends
)
516 // This is the loop detection
517 if (IsFlag(D
.TargetPkg(),Added
) == true ||
518 IsFlag(D
.TargetPkg(),AddPending
) == true)
520 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
525 /* Predepends require a special ordering stage, they must have
526 all dependents installed as well */
527 DepFunc Old
= Primary
;
529 if (D
->Type
== pkgCache::Dep::PreDepends
)
530 Primary
= &DepUnPackPreD
;
531 Res
= VisitProvides(D
);
540 // OrderList::DepUnPackPreD - Critical UnPacking ordering with depends /*{{{*/
541 // ---------------------------------------------------------------------
542 /* Critical PreDepends (also configure immediate and essential) strives to
543 ensure not only that all conflicts+predepends are met but that this
544 package will be immediately configurable when it is unpacked.
546 Loops are preprocessed and logged. */
547 bool pkgOrderList::DepUnPackPreD(DepIterator D
)
549 if (D
.Reverse() == true)
550 return DepUnPackCrit(D
);
552 for (; D
.end() == false; D
++)
554 if (D
.IsCritical() == false)
557 /* We wish to check if the dep is okay in the now state of the
558 target package against the install state of this package. */
559 if (CheckDep(D
) == true)
561 /* We want to catch predepends loops with the code below.
562 Conflicts loops that are Dep OK are ignored */
563 if (IsFlag(D
.TargetPkg(),AddPending
) == false ||
564 D
->Type
!= pkgCache::Dep::PreDepends
)
568 // This is the loop detection
569 if (IsFlag(D
.TargetPkg(),Added
) == true ||
570 IsFlag(D
.TargetPkg(),AddPending
) == true)
572 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
577 if (VisitProvides(D
) == false)
583 // OrderList::DepUnPackPre - Critical Predepends ordering /*{{{*/
584 // ---------------------------------------------------------------------
585 /* Critical PreDepends (also configure immediate and essential) strives to
586 ensure not only that all conflicts+predepends are met but that this
587 package will be immediately configurable when it is unpacked.
589 Loops are preprocessed and logged. All loops will be fatal. */
590 bool pkgOrderList::DepUnPackPre(DepIterator D
)
592 if (D
.Reverse() == true)
595 for (; D
.end() == false; D
++)
597 /* Only consider the PreDepends or Depends. Depends are only
598 considered at the lowest depth or in the case of immediate
600 if (D
->Type
!= pkgCache::Dep::PreDepends
)
602 if (D
->Type
== pkgCache::Dep::Depends
)
604 if (Depth
== 1 && IsFlag(D
.ParentPkg(),Immediate
) == false)
611 /* We wish to check if the dep is okay in the now state of the
612 target package against the install state of this package. */
613 if (CheckDep(D
) == true)
615 /* We want to catch predepends loops with the code below.
616 Conflicts loops that are Dep OK are ignored */
617 if (IsFlag(D
.TargetPkg(),AddPending
) == false)
621 // This is the loop detection
622 if (IsFlag(D
.TargetPkg(),Added
) == true ||
623 IsFlag(D
.TargetPkg(),AddPending
) == true)
625 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
630 if (VisitProvides(D
) == false)
636 // OrderList::DepUnPackDep - Reverse dependency considerations /*{{{*/
637 // ---------------------------------------------------------------------
638 /* Reverse dependencies are considered to determine if unpacking this
639 package will break any existing dependencies. If so then those
640 packages are ordered before this one so that they are in the
643 The forwards depends loop is designed to bring the packages dependents
644 close to the package. This helps reduce deconfigure time.
646 Loops are irrelevent to this. */
647 bool pkgOrderList::DepUnPackDep(DepIterator D
)
650 for (; D
.end() == false; D
++)
651 if (D
.IsCritical() == true)
653 if (D
.Reverse() == true)
655 /* Duplication prevention. We consider rev deps only on
656 the current version, a not installed package
658 if (D
.ParentPkg()->CurrentVer
== 0 ||
659 D
.ParentPkg().CurrentVer() != D
.ParentVer())
662 // The dep will not break so it is irrelevent.
663 if (CheckDep(D
) == true)
666 if (VisitNode(D
.ParentPkg()) == false)
670 if (D
->Type
== pkgCache::Dep::Depends
)
671 if (VisitProvides(D
) == false)
677 // OrderList::DepConfigure - Configuration ordering /*{{{*/
678 // ---------------------------------------------------------------------
679 /* Configuration only ordering orders by the Depends: line only. It
680 orders configuration so that when a package comes to be configured it's
681 dependents are configured.
683 Loops are ingored. Depends loop entry points are chaotic. */
684 bool pkgOrderList::DepConfigure(DepIterator D
)
686 // Never consider reverse configuration dependencies.
687 if (D
.Reverse() == true)
690 for (; D
.end() == false; D
++)
691 if (D
->Type
== pkgCache::Dep::Depends
)
692 if (VisitProvides(D
) == false)
697 // OrderList::DepRemove - Removal ordering /*{{{*/
698 // ---------------------------------------------------------------------
699 /* Removal visits all reverse depends. It considers if the dependency
700 of the Now state version to see if it is okay with removing this
701 package. This check should always fail, but is provided for symetery
702 with the other critical handlers.
704 Loops are preprocessed and logged. Removal loops can also be
705 detected in the critical handler. They are characterized by an
706 old version of A depending on B but the new version of A conflicting
707 with B, thus either A or B must break to install. */
708 bool pkgOrderList::DepRemove(DepIterator D
)
710 if (D
.Reverse() == false)
712 for (; D
.end() == false; D
++)
713 if (D
->Type
== pkgCache::Dep::Depends
|| D
->Type
== pkgCache::Dep::PreDepends
)
715 // Duplication elimination, consider the current version only
716 if (D
.ParentPkg().CurrentVer() != D
.ParentVer())
719 /* We wish to see if the dep on the parent package is okay
720 in the removed (install) state of the target pkg. */
721 if (CheckDep(D
) == true)
723 // We want to catch loops with the code below.
724 if (IsFlag(D
.ParentPkg(),AddPending
) == false)
728 // This is the loop detection
729 if (IsFlag(D
.ParentPkg(),Added
) == true ||
730 IsFlag(D
.ParentPkg(),AddPending
) == true)
732 if (IsFlag(D
.ParentPkg(),AddPending
) == true)
737 if (VisitNode(D
.ParentPkg()) == false)
745 // OrderList::AddLoop - Add a loop to the loop list /*{{{*/
746 // ---------------------------------------------------------------------
747 /* We record the loops. This is a relic since loop breaking is done
748 genericaly as part of the safety routines. */
749 bool pkgOrderList::AddLoop(DepIterator D
)
751 if (LoopCount
< 0 || LoopCount
>= 20)
757 if (Loops
[LoopCount
- 1].ParentPkg() == D
.ParentPkg() ||
758 Loops
[LoopCount
- 1].TargetPkg() == D
.ParentPkg())
762 Loops
[LoopCount
++] = D
;
764 // Mark the packages as being part of a loop.
765 Flag(D
.TargetPkg(),Loop
);
766 Flag(D
.ParentPkg(),Loop
);
770 // OrderList::WipeFlags - Unset the given flags from all packages /*{{{*/
771 // ---------------------------------------------------------------------
773 void pkgOrderList::WipeFlags(unsigned long F
)
775 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
776 for (unsigned long I
= 0; I
!= Size
; I
++)
780 // OrderList::CheckDep - Check a dependency for truth /*{{{*/
781 // ---------------------------------------------------------------------
782 /* This performs a complete analysis of the dependency wrt to the
783 current add list. It returns true if after all events are
784 performed it is still true. This sort of routine can be approximated
785 by examining the DepCache, however in convoluted cases of provides
786 this fails to produce a suitable result. */
787 bool pkgOrderList::CheckDep(DepIterator D
)
789 Version
**List
= D
.AllTargets();
790 for (Version
**I
= List
; *I
!= 0; I
++)
792 VerIterator
Ver(Cache
,*I
);
793 PkgIterator Pkg
= Ver
.ParentPkg();
795 /* The meaning of Added and AddPending is subtle. AddPending is
796 an indication that the package is looping. Because of the
797 way ordering works Added means the package will be unpacked
798 before this one and AddPending means after. It is therefore
799 correct to ignore AddPending in all cases, but that exposes
800 reverse-ordering loops which should be ignore. */
801 if (IsFlag(Pkg
,Added
) == true ||
802 (IsFlag(Pkg
,AddPending
) == true && D
.Reverse() == true))
804 if (Cache
[Pkg
].InstallVer
!= *I
)
808 if ((Version
*)Pkg
.CurrentVer() != *I
||
809 Pkg
.State() != PkgIterator::NeedsNothing
)
814 /* Conflicts requires that all versions are not present, depends
816 if (D
->Type
!= pkgCache::Dep::Conflicts
)
823 /* Conflicts requires that all versions are not present, depends
825 if (D
->Type
== pkgCache::Dep::Conflicts
)