]>
git.saurik.com Git - apt.git/blob - apt-pkg/orderlist.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: orderlist.cc,v 1.3 1998/09/26 05:34:21 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 // This should probably trancend not installed packages
406 if (Pkg
.end() == true || IsFlag(Pkg
,Added
) == true ||
407 IsFlag(Pkg
,AddPending
) == true || IsFlag(Pkg
,InList
) == false)
410 /* for (int j = 0; j != Depth; j++) cout << ' ';
411 cout << "Visit " << Pkg.Name() << endl;*/
415 Flag(Pkg
,AddPending
);
417 DepFunc Old
= Primary
;
419 // Perform immedate configuration of the package if so flagged.
420 if (IsFlag(Pkg
,Immediate
) == true && Primary
!= &DepUnPackPre
)
421 Primary
= &DepUnPackPreD
;
424 if (Cache
[Pkg
].Delete() == false)
427 Res
&= Res
&& VisitDeps(Primary
,Pkg
);
428 Res
&= Res
&& VisitRDeps(Primary
,Pkg
);
429 Res
&= Res
&& VisitRProvides(Primary
,Pkg
.CurrentVer());
430 Res
&= Res
&& VisitRProvides(Primary
,Cache
[Pkg
].InstVerIter(Cache
));
433 Res
&= Res
&& VisitRDeps(RevDepends
,Pkg
);
434 Res
&= Res
&& VisitRProvides(RevDepends
,Pkg
.CurrentVer());
435 Res
&= Res
&& VisitRProvides(RevDepends
,Cache
[Pkg
].InstVerIter(Cache
));
438 Res
&= Res
&& VisitDeps(Secondary
,Pkg
);
439 Res
&= Res
&& VisitRDeps(Secondary
,Pkg
);
440 Res
&= Res
&& VisitRProvides(Secondary
,Pkg
.CurrentVer());
441 Res
&= Res
&& VisitRProvides(Secondary
,Cache
[Pkg
].InstVerIter(Cache
));
446 Res
&= Res
&& VisitRDeps(Remove
,Pkg
);
447 Res
&= Res
&& VisitRProvides(Remove
,Pkg
.CurrentVer());
450 if (IsFlag(Pkg
,Added
) == false)
452 Flag(Pkg
,Added
,Added
| AddPending
);
460 /* for (int j = 0; j != Depth; j++) cout << ' ';
461 cout << "Leave " << Pkg.Name() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;*/
467 // OrderList::DepUnPackCrit - Critical UnPacking ordering /*{{{*/
468 // ---------------------------------------------------------------------
469 /* Critical unpacking ordering strives to satisfy Conflicts: and
470 PreDepends: only. When a prdepends is encountered the Primary
471 DepFunc is changed to be DepUnPackPreD.
473 Loops are preprocessed and logged. */
474 bool pkgOrderList::DepUnPackCrit(DepIterator D
)
476 for (; D
.end() == false; D
++)
478 if (D
.Reverse() == true)
480 /* Reverse depenanices are only interested in conflicts,
481 predepend breakage is ignored here */
482 if (D
->Type
!= pkgCache::Dep::Conflicts
)
485 // Duplication elimination, consider only the current version
486 if (D
.ParentPkg().CurrentVer() != D
.ParentVer())
489 /* For reverse dependencies we wish to check if the
490 dependency is satisifed in the install state. The
491 target package (caller) is going to be in the installed
493 if (CheckDep(D
) == true)
496 if (VisitNode(D
.ParentPkg()) == false)
501 /* Forward critical dependencies MUST be correct before the
502 package can be unpacked. */
503 if (D
->Type
!= pkgCache::Dep::Conflicts
&& D
->Type
!= pkgCache::Dep::PreDepends
)
506 /* We wish to check if the dep is okay in the now state of the
507 target package against the install state of this package. */
508 if (CheckDep(D
) == true)
510 /* We want to catch predepends loops with the code below.
511 Conflicts loops that are Dep OK are ignored */
512 if (IsFlag(D
.TargetPkg(),AddPending
) == false ||
513 D
->Type
!= pkgCache::Dep::PreDepends
)
517 // This is the loop detection
518 if (IsFlag(D
.TargetPkg(),Added
) == true ||
519 IsFlag(D
.TargetPkg(),AddPending
) == true)
521 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
526 /* Predepends require a special ordering stage, they must have
527 all dependents installed as well */
528 DepFunc Old
= Primary
;
530 if (D
->Type
== pkgCache::Dep::PreDepends
)
531 Primary
= &DepUnPackPreD
;
532 Res
= VisitProvides(D
);
541 // OrderList::DepUnPackPreD - Critical UnPacking ordering with depends /*{{{*/
542 // ---------------------------------------------------------------------
543 /* Critical PreDepends (also configure immediate and essential) strives to
544 ensure not only that all conflicts+predepends are met but that this
545 package will be immediately configurable when it is unpacked.
547 Loops are preprocessed and logged. */
548 bool pkgOrderList::DepUnPackPreD(DepIterator D
)
550 if (D
.Reverse() == true)
551 return DepUnPackCrit(D
);
553 for (; D
.end() == false; D
++)
555 if (D
.IsCritical() == false)
558 /* We wish to check if the dep is okay in the now state of the
559 target package against the install state of this package. */
560 if (CheckDep(D
) == true)
562 /* We want to catch predepends loops with the code below.
563 Conflicts loops that are Dep OK are ignored */
564 if (IsFlag(D
.TargetPkg(),AddPending
) == false ||
565 D
->Type
!= pkgCache::Dep::PreDepends
)
569 // This is the loop detection
570 if (IsFlag(D
.TargetPkg(),Added
) == true ||
571 IsFlag(D
.TargetPkg(),AddPending
) == true)
573 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
578 if (VisitProvides(D
) == false)
584 // OrderList::DepUnPackPre - Critical Predepends ordering /*{{{*/
585 // ---------------------------------------------------------------------
586 /* Critical PreDepends (also configure immediate and essential) strives to
587 ensure not only that all conflicts+predepends are met but that this
588 package will be immediately configurable when it is unpacked.
590 Loops are preprocessed and logged. All loops will be fatal. */
591 bool pkgOrderList::DepUnPackPre(DepIterator D
)
593 if (D
.Reverse() == true)
596 for (; D
.end() == false; D
++)
598 /* Only consider the PreDepends or Depends. Depends are only
599 considered at the lowest depth or in the case of immediate
601 if (D
->Type
!= pkgCache::Dep::PreDepends
)
603 if (D
->Type
== pkgCache::Dep::Depends
)
605 if (Depth
== 1 && IsFlag(D
.ParentPkg(),Immediate
) == false)
612 /* We wish to check if the dep is okay in the now state of the
613 target package against the install state of this package. */
614 if (CheckDep(D
) == true)
616 /* We want to catch predepends loops with the code below.
617 Conflicts loops that are Dep OK are ignored */
618 if (IsFlag(D
.TargetPkg(),AddPending
) == false)
622 // This is the loop detection
623 if (IsFlag(D
.TargetPkg(),Added
) == true ||
624 IsFlag(D
.TargetPkg(),AddPending
) == true)
626 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
631 if (VisitProvides(D
) == false)
637 // OrderList::DepUnPackDep - Reverse dependency considerations /*{{{*/
638 // ---------------------------------------------------------------------
639 /* Reverse dependencies are considered to determine if unpacking this
640 package will break any existing dependencies. If so then those
641 packages are ordered before this one so that they are in the
644 The forwards depends loop is designed to bring the packages dependents
645 close to the package. This helps reduce deconfigure time.
647 Loops are irrelevent to this. */
648 bool pkgOrderList::DepUnPackDep(DepIterator D
)
651 for (; D
.end() == false; D
++)
652 if (D
.IsCritical() == true)
654 if (D
.Reverse() == true)
656 /* Duplication prevention. We consider rev deps only on
657 the current version, a not installed package
659 if (D
.ParentPkg()->CurrentVer
== 0 ||
660 D
.ParentPkg().CurrentVer() != D
.ParentVer())
663 // The dep will not break so it is irrelevent.
664 if (CheckDep(D
) == true)
667 if (VisitNode(D
.ParentPkg()) == false)
671 if (D
->Type
== pkgCache::Dep::Depends
)
672 if (VisitProvides(D
) == false)
678 // OrderList::DepConfigure - Configuration ordering /*{{{*/
679 // ---------------------------------------------------------------------
680 /* Configuration only ordering orders by the Depends: line only. It
681 orders configuration so that when a package comes to be configured it's
682 dependents are configured.
684 Loops are ingored. Depends loop entry points are chaotic. */
685 bool pkgOrderList::DepConfigure(DepIterator D
)
687 // Never consider reverse configuration dependencies.
688 if (D
.Reverse() == true)
691 for (; D
.end() == false; D
++)
692 if (D
->Type
== pkgCache::Dep::Depends
)
693 if (VisitProvides(D
) == false)
698 // OrderList::DepRemove - Removal ordering /*{{{*/
699 // ---------------------------------------------------------------------
700 /* Removal visits all reverse depends. It considers if the dependency
701 of the Now state version to see if it is okay with removing this
702 package. This check should always fail, but is provided for symetery
703 with the other critical handlers.
705 Loops are preprocessed and logged. Removal loops can also be
706 detected in the critical handler. They are characterized by an
707 old version of A depending on B but the new version of A conflicting
708 with B, thus either A or B must break to install. */
709 bool pkgOrderList::DepRemove(DepIterator D
)
711 if (D
.Reverse() == false)
713 for (; D
.end() == false; D
++)
714 if (D
->Type
== pkgCache::Dep::Depends
|| D
->Type
== pkgCache::Dep::PreDepends
)
716 // Duplication elimination, consider the current version only
717 if (D
.ParentPkg().CurrentVer() != D
.ParentVer())
720 /* We wish to see if the dep on the parent package is okay
721 in the removed (install) state of the target pkg. */
722 if (CheckDep(D
) == true)
724 // We want to catch loops with the code below.
725 if (IsFlag(D
.ParentPkg(),AddPending
) == false)
729 // This is the loop detection
730 if (IsFlag(D
.ParentPkg(),Added
) == true ||
731 IsFlag(D
.ParentPkg(),AddPending
) == true)
733 if (IsFlag(D
.ParentPkg(),AddPending
) == true)
738 if (VisitNode(D
.ParentPkg()) == false)
746 // OrderList::AddLoop - Add a loop to the loop list /*{{{*/
747 // ---------------------------------------------------------------------
748 /* We record the loops. This is a relic since loop breaking is done
749 genericaly as part of the safety routines. */
750 bool pkgOrderList::AddLoop(DepIterator D
)
752 if (LoopCount
< 0 || LoopCount
>= 20)
758 if (Loops
[LoopCount
- 1].ParentPkg() == D
.ParentPkg() ||
759 Loops
[LoopCount
- 1].TargetPkg() == D
.ParentPkg())
763 Loops
[LoopCount
++] = D
;
765 // Mark the packages as being part of a loop.
766 Flag(D
.TargetPkg(),Loop
);
767 Flag(D
.ParentPkg(),Loop
);
771 // OrderList::WipeFlags - Unset the given flags from all packages /*{{{*/
772 // ---------------------------------------------------------------------
774 void pkgOrderList::WipeFlags(unsigned long F
)
776 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
777 for (unsigned long I
= 0; I
!= Size
; I
++)
781 // OrderList::CheckDep - Check a dependency for truth /*{{{*/
782 // ---------------------------------------------------------------------
783 /* This performs a complete analysis of the dependency wrt to the
784 current add list. It returns true if after all events are
785 performed it is still true. This sort of routine can be approximated
786 by examining the DepCache, however in convoluted cases of provides
787 this fails to produce a suitable result. */
788 bool pkgOrderList::CheckDep(DepIterator D
)
790 Version
**List
= D
.AllTargets();
791 for (Version
**I
= List
; *I
!= 0; I
++)
793 VerIterator
Ver(Cache
,*I
);
794 PkgIterator Pkg
= Ver
.ParentPkg();
796 /* The meaning of Added and AddPending is subtle. AddPending is
797 an indication that the package is looping. Because of the
798 way ordering works Added means the package will be unpacked
799 before this one and AddPending means after. It is therefore
800 correct to ignore AddPending in all cases, but that exposes
801 reverse-ordering loops which should be ignore. */
802 if (IsFlag(Pkg
,Added
) == true ||
803 (IsFlag(Pkg
,AddPending
) == true && D
.Reverse() == true))
805 if (Cache
[Pkg
].InstallVer
!= *I
)
809 if ((Version
*)Pkg
.CurrentVer() != *I
||
810 Pkg
.State() != PkgIterator::NeedsNothing
)
815 /* Conflicts requires that all versions are not present, depends
817 if (D
->Type
!= pkgCache::Dep::Conflicts
)
824 /* Conflicts requires that all versions are not present, depends
826 if (D
->Type
== pkgCache::Dep::Conflicts
)