]>
git.saurik.com Git - apt.git/blob - apt-pkg/orderlist.cc
cb55147c3640da1105acc08c7479fab021377e56
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: orderlist.cc,v 1.14 2001/05/07 05:49:43 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 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.
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 arbitrary priority to give quite abit of control over the final unpacking
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.
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
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.
63 ##################################################################### */
65 // Include Files /*{{{*/
66 #include <apt-pkg/orderlist.h>
67 #include <apt-pkg/depcache.h>
68 #include <apt-pkg/error.h>
69 #include <apt-pkg/version.h>
70 #include <apt-pkg/sptr.h>
71 #include <apt-pkg/configuration.h>
78 pkgOrderList
*pkgOrderList::Me
= 0;
80 // OrderList::pkgOrderList - Constructor /*{{{*/
81 // ---------------------------------------------------------------------
83 pkgOrderList::pkgOrderList(pkgDepCache
*pCache
) : Cache(*pCache
)
91 Debug
= _config
->FindB("Debug::pkgOrderList",false);
93 /* Construct the arrays, egcs 1.0.1 bug requires the package count
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
);
101 // OrderList::~pkgOrderList - Destructor /*{{{*/
102 // ---------------------------------------------------------------------
104 pkgOrderList::~pkgOrderList()
110 // OrderList::IsMissing - Check if a file is missing /*{{{*/
111 // ---------------------------------------------------------------------
113 bool pkgOrderList::IsMissing(PkgIterator Pkg
)
115 // Skip packages to erase
116 if (Cache
[Pkg
].Delete() == true)
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)
128 if (FileList
[Pkg
->ID
].empty() == false)
131 // Missing Pseudo packages are missing if the real package is missing
132 if (pkgCache::VerIterator(Cache
, Cache
[Pkg
].CandidateVer
).Pseudo() == true)
133 return IsMissing(Pkg
.Group().FindPkg("all"));
138 // OrderList::DoRun - Does an order run /*{{{*/
139 // ---------------------------------------------------------------------
140 /* The caller is expeted to have setup the desired probe state */
141 bool pkgOrderList::DoRun()
144 unsigned long Size
= Cache
.Head().PackageCount
;
145 SPtrArray
<Package
*> NList
= new Package
*[Size
];
146 SPtrArray
<Package
*> AfterList
= new Package
*[Size
];
147 AfterEnd
= AfterList
;
150 WipeFlags(Added
| AddPending
| Loop
| InList
);
152 for (iterator I
= List
; I
!= End
; I
++)
155 // Rebuild the main list into the temp list.
156 iterator OldEnd
= End
;
158 for (iterator I
= List
; I
!= OldEnd
; I
++)
159 if (VisitNode(PkgIterator(Cache
,*I
)) == false)
165 // Copy the after list to the end of the main list
166 for (Package
**I
= AfterList
; I
!= AfterEnd
; I
++)
169 // Swap the main list to the new list
171 List
= NList
.UnGuard();
175 // OrderList::OrderCritical - Perform critical unpacking ordering /*{{{*/
176 // ---------------------------------------------------------------------
177 /* This performs predepends and immediate configuration ordering only.
178 This is termed critical unpacking ordering. Any loops that form are
179 fatal and indicate that the packages cannot be installed. */
180 bool pkgOrderList::OrderCritical()
184 Primary
= &pkgOrderList::DepUnPackPreD
;
192 qsort(List
,End
- List
,sizeof(*List
),&OrderCompareB
);
194 if (DoRun() == false)
198 return _error
->Error("Fatal, predepends looping detected");
202 clog
<< "** Critical Unpack ordering done" << endl
;
204 for (iterator I
= List
; I
!= End
; I
++)
206 PkgIterator
P(Cache
,*I
);
207 if (IsNow(P
) == true)
208 clog
<< " " << P
.FullName() << ' ' << IsMissing(P
) << ',' << IsFlag(P
,After
) << endl
;
215 // OrderList::OrderUnpack - Perform complete unpacking ordering /*{{{*/
216 // ---------------------------------------------------------------------
217 /* This performs complete unpacking ordering and creates an order that is
218 suitable for unpacking */
219 bool pkgOrderList::OrderUnpack(string
*FileList
)
221 this->FileList
= FileList
;
223 // Setup the after flags
228 // Set the inlist flag
229 for (iterator I
= List
; I
!= End
; I
++)
231 PkgIterator
P(Cache
,*I
);
232 if (IsMissing(P
) == true && IsNow(P
) == true)
237 Primary
= &pkgOrderList::DepUnPackCrit
;
238 Secondary
= &pkgOrderList::DepConfigure
;
239 RevDepends
= &pkgOrderList::DepUnPackDep
;
240 Remove
= &pkgOrderList::DepRemove
;
245 qsort(List
,End
- List
,sizeof(*List
),&OrderCompareA
);
248 clog
<< "** Pass A" << endl
;
249 if (DoRun() == false)
253 clog
<< "** Pass B" << endl
;
255 if (DoRun() == false)
259 clog
<< "** Pass C" << endl
;
262 Remove
= 0; // Otherwise the libreadline remove problem occures
263 if (DoRun() == false)
267 clog
<< "** Pass D" << endl
;
269 Primary
= &pkgOrderList::DepUnPackPre
;
270 if (DoRun() == false)
275 clog
<< "** Unpack ordering done" << endl
;
277 for (iterator I
= List
; I
!= End
; I
++)
279 PkgIterator
P(Cache
,*I
);
280 if (IsNow(P
) == true)
281 clog
<< " " << P
.FullName() << ' ' << IsMissing(P
) << ',' << IsFlag(P
,After
) << endl
;
288 // OrderList::OrderConfigure - Perform configuration ordering /*{{{*/
289 // ---------------------------------------------------------------------
290 /* This orders by depends only and produces an order which is suitable
292 bool pkgOrderList::OrderConfigure()
295 Primary
= &pkgOrderList::DepConfigure
;
303 // OrderList::Score - Score the package for sorting /*{{{*/
304 // ---------------------------------------------------------------------
305 /* Higher scores order earlier */
306 int pkgOrderList::Score(PkgIterator Pkg
)
308 static int const ScoreDelete
= _config
->FindI("OrderList::Score::Delete", 500);
310 // Removal is always done first
311 if (Cache
[Pkg
].Delete() == true)
314 // This should never happen..
315 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
318 static int const ScoreEssential
= _config
->FindI("OrderList::Score::Essential", 200);
319 static int const ScoreImmediate
= _config
->FindI("OrderList::Score::Immediate", 10);
320 static int const ScorePreDepends
= _config
->FindI("OrderList::Score::PreDepends", 50);
323 if ((Pkg
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
324 Score
+= ScoreEssential
;
326 if (IsFlag(Pkg
,Immediate
) == true)
327 Score
+= ScoreImmediate
;
329 for (DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList();
330 D
.end() == false; D
++)
331 if (D
->Type
== pkgCache::Dep::PreDepends
)
333 Score
+= ScorePreDepends
;
337 // Important Required Standard Optional Extra
338 signed short PrioMap
[] = {0,5,4,3,1,0};
339 if (Cache
[Pkg
].InstVerIter(Cache
)->Priority
<= 5)
340 Score
+= PrioMap
[Cache
[Pkg
].InstVerIter(Cache
)->Priority
];
344 // OrderList::FileCmp - Compare by package file /*{{{*/
345 // ---------------------------------------------------------------------
346 /* This compares by the package file that the install version is in. */
347 int pkgOrderList::FileCmp(PkgIterator A
,PkgIterator B
)
349 if (Cache
[A
].Delete() == true && Cache
[B
].Delete() == true)
351 if (Cache
[A
].Delete() == true)
353 if (Cache
[B
].Delete() == true)
356 if (Cache
[A
].InstVerIter(Cache
).FileList().end() == true)
358 if (Cache
[B
].InstVerIter(Cache
).FileList().end() == true)
361 pkgCache::PackageFile
*FA
= Cache
[A
].InstVerIter(Cache
).FileList().File();
362 pkgCache::PackageFile
*FB
= Cache
[B
].InstVerIter(Cache
).FileList().File();
370 // BoolCompare - Comparison function for two booleans /*{{{*/
371 // ---------------------------------------------------------------------
373 static int BoolCompare(bool A
,bool B
)
382 // OrderList::OrderCompareA - Order the installation by op /*{{{*/
383 // ---------------------------------------------------------------------
384 /* This provides a first-pass sort of the list and gives a decent starting
385 point for further complete ordering. It is used by OrderUnpack only */
386 int pkgOrderList::OrderCompareA(const void *a
, const void *b
)
388 PkgIterator
A(Me
->Cache
,*(Package
**)a
);
389 PkgIterator
B(Me
->Cache
,*(Package
**)b
);
391 // We order packages with a set state toward the front
393 if ((Res
= BoolCompare(Me
->IsNow(A
),Me
->IsNow(B
))) != 0)
396 // We order missing files to toward the end
397 /* if (Me->FileList != 0)
399 if ((Res = BoolCompare(Me->IsMissing(A),
400 Me->IsMissing(B))) != 0)
404 if (A
.State() != pkgCache::PkgIterator::NeedsNothing
&&
405 B
.State() == pkgCache::PkgIterator::NeedsNothing
)
408 if (A
.State() == pkgCache::PkgIterator::NeedsNothing
&&
409 B
.State() != pkgCache::PkgIterator::NeedsNothing
)
412 int ScoreA
= Me
->Score(A
);
413 int ScoreB
= Me
->Score(B
);
421 return strcmp(A
.Name(),B
.Name());
424 // OrderList::OrderCompareB - Order the installation by source /*{{{*/
425 // ---------------------------------------------------------------------
426 /* This orders by installation source. This is useful to handle
427 inter-source breaks */
428 int pkgOrderList::OrderCompareB(const void *a
, const void *b
)
430 PkgIterator
A(Me
->Cache
,*(Package
**)a
);
431 PkgIterator
B(Me
->Cache
,*(Package
**)b
);
433 if (A
.State() != pkgCache::PkgIterator::NeedsNothing
&&
434 B
.State() == pkgCache::PkgIterator::NeedsNothing
)
437 if (A
.State() == pkgCache::PkgIterator::NeedsNothing
&&
438 B
.State() != pkgCache::PkgIterator::NeedsNothing
)
441 int F
= Me
->FileCmp(A
,B
);
449 int ScoreA
= Me
->Score(A
);
450 int ScoreB
= Me
->Score(B
);
458 return strcmp(A
.Name(),B
.Name());
461 // OrderList::VisitDeps - Visit forward install dependencies /*{{{*/
462 // ---------------------------------------------------------------------
463 /* This calls the dependency function for the normal forwards dependencies
465 bool pkgOrderList::VisitDeps(DepFunc F
,PkgIterator Pkg
)
467 if (F
== 0 || Pkg
.end() == true || Cache
[Pkg
].InstallVer
== 0)
470 return (this->*F
)(Cache
[Pkg
].InstVerIter(Cache
).DependsList());
473 // OrderList::VisitRDeps - Visit reverse dependencies /*{{{*/
474 // ---------------------------------------------------------------------
475 /* This calls the dependency function for all of the normal reverse depends
477 bool pkgOrderList::VisitRDeps(DepFunc F
,PkgIterator Pkg
)
479 if (F
== 0 || Pkg
.end() == true)
482 return (this->*F
)(Pkg
.RevDependsList());
485 // OrderList::VisitRProvides - Visit provides reverse dependencies /*{{{*/
486 // ---------------------------------------------------------------------
487 /* This calls the dependency function for all reverse dependencies
488 generated by the provides line on the package. */
489 bool pkgOrderList::VisitRProvides(DepFunc F
,VerIterator Ver
)
491 if (F
== 0 || Ver
.end() == true)
495 for (PrvIterator P
= Ver
.ProvidesList(); P
.end() == false; P
++)
496 Res
&= (this->*F
)(P
.ParentPkg().RevDependsList());
500 // OrderList::VisitProvides - Visit all of the providing packages /*{{{*/
501 // ---------------------------------------------------------------------
502 /* This routine calls visit on all providing packages. */
503 bool pkgOrderList::VisitProvides(DepIterator D
,bool Critical
)
505 SPtrArray
<Version
*> List
= D
.AllTargets();
506 for (Version
**I
= List
; *I
!= 0; I
++)
508 VerIterator
Ver(Cache
,*I
);
509 PkgIterator Pkg
= Ver
.ParentPkg();
511 if (Cache
[Pkg
].Keep() == true && Pkg
.State() == PkgIterator::NeedsNothing
)
514 if (D
->Type
!= pkgCache::Dep::Conflicts
&&
515 D
->Type
!= pkgCache::Dep::DpkgBreaks
&&
516 D
->Type
!= pkgCache::Dep::Obsoletes
&&
517 Cache
[Pkg
].InstallVer
!= *I
)
520 if ((D
->Type
== pkgCache::Dep::Conflicts
||
521 D
->Type
== pkgCache::Dep::DpkgBreaks
||
522 D
->Type
== pkgCache::Dep::Obsoletes
) &&
523 (Version
*)Pkg
.CurrentVer() != *I
)
526 // Skip over missing files
527 if (Critical
== false && IsMissing(D
.ParentPkg()) == true)
530 if (VisitNode(Pkg
) == false)
536 // OrderList::VisitNode - Recursive ordering director /*{{{*/
537 // ---------------------------------------------------------------------
538 /* This is the core ordering routine. It calls the set dependency
539 consideration functions which then potentialy call this again. Finite
540 depth is achived through the colouring mechinism. */
541 bool pkgOrderList::VisitNode(PkgIterator Pkg
)
543 // Looping or irrelevent.
544 // This should probably trancend not installed packages
545 if (Pkg
.end() == true || IsFlag(Pkg
,Added
) == true ||
546 IsFlag(Pkg
,AddPending
) == true || IsFlag(Pkg
,InList
) == false)
551 for (int j
= 0; j
!= Depth
; j
++) clog
<< ' ';
552 clog
<< "Visit " << Pkg
.FullName() << endl
;
558 Flag(Pkg
,AddPending
);
560 DepFunc Old
= Primary
;
562 // Perform immedate configuration of the package if so flagged.
563 if (IsFlag(Pkg
,Immediate
) == true && Primary
!= &pkgOrderList::DepUnPackPre
)
564 Primary
= &pkgOrderList::DepUnPackPreD
;
566 if (IsNow(Pkg
) == true)
569 if (Cache
[Pkg
].Delete() == false)
572 Res
&= Res
&& VisitDeps(Primary
,Pkg
);
573 Res
&= Res
&& VisitRDeps(Primary
,Pkg
);
574 Res
&= Res
&& VisitRProvides(Primary
,Pkg
.CurrentVer());
575 Res
&= Res
&& VisitRProvides(Primary
,Cache
[Pkg
].InstVerIter(Cache
));
578 Res
&= Res
&& VisitRDeps(RevDepends
,Pkg
);
579 Res
&= Res
&& VisitRProvides(RevDepends
,Pkg
.CurrentVer());
580 Res
&= Res
&& VisitRProvides(RevDepends
,Cache
[Pkg
].InstVerIter(Cache
));
583 Res
&= Res
&& VisitDeps(Secondary
,Pkg
);
584 Res
&= Res
&& VisitRDeps(Secondary
,Pkg
);
585 Res
&= Res
&& VisitRProvides(Secondary
,Pkg
.CurrentVer());
586 Res
&= Res
&& VisitRProvides(Secondary
,Cache
[Pkg
].InstVerIter(Cache
));
591 Res
&= Res
&& VisitRDeps(Remove
,Pkg
);
592 Res
&= Res
&& VisitRProvides(Remove
,Pkg
.CurrentVer());
596 if (IsFlag(Pkg
,Added
) == false)
598 Flag(Pkg
,Added
,Added
| AddPending
);
599 if (IsFlag(Pkg
,After
) == true)
610 for (int j
= 0; j
!= Depth
; j
++) clog
<< ' ';
611 clog
<< "Leave " << Pkg
.FullName() << ' ' << IsFlag(Pkg
,Added
) << ',' << IsFlag(Pkg
,AddPending
) << endl
;
617 // OrderList::DepUnPackCrit - Critical UnPacking ordering /*{{{*/
618 // ---------------------------------------------------------------------
619 /* Critical unpacking ordering strives to satisfy Conflicts: and
620 PreDepends: only. When a prdepends is encountered the Primary
621 DepFunc is changed to be DepUnPackPreD.
623 Loops are preprocessed and logged. */
624 bool pkgOrderList::DepUnPackCrit(DepIterator D
)
626 for (; D
.end() == false; D
++)
628 if (D
.Reverse() == true)
630 /* Reverse depenanices are only interested in conflicts,
631 predepend breakage is ignored here */
632 if (D
->Type
!= pkgCache::Dep::Conflicts
&&
633 D
->Type
!= pkgCache::Dep::Obsoletes
)
636 // Duplication elimination, consider only the current version
637 if (D
.ParentPkg().CurrentVer() != D
.ParentVer())
640 /* For reverse dependencies we wish to check if the
641 dependency is satisifed in the install state. The
642 target package (caller) is going to be in the installed
644 if (CheckDep(D
) == true)
647 if (VisitNode(D
.ParentPkg()) == false)
652 /* Forward critical dependencies MUST be correct before the
653 package can be unpacked. */
654 if (D
->Type
!= pkgCache::Dep::Conflicts
&&
655 D
->Type
!= pkgCache::Dep::DpkgBreaks
&&
656 D
->Type
!= pkgCache::Dep::Obsoletes
&&
657 D
->Type
!= pkgCache::Dep::PreDepends
)
660 /* We wish to check if the dep is okay in the now state of the
661 target package against the install state of this package. */
662 if (CheckDep(D
) == true)
664 /* We want to catch predepends loops with the code below.
665 Conflicts loops that are Dep OK are ignored */
666 if (IsFlag(D
.TargetPkg(),AddPending
) == false ||
667 D
->Type
!= pkgCache::Dep::PreDepends
)
671 // This is the loop detection
672 if (IsFlag(D
.TargetPkg(),Added
) == true ||
673 IsFlag(D
.TargetPkg(),AddPending
) == true)
675 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
680 /* Predepends require a special ordering stage, they must have
681 all dependents installed as well */
682 DepFunc Old
= Primary
;
684 if (D
->Type
== pkgCache::Dep::PreDepends
)
685 Primary
= &pkgOrderList::DepUnPackPreD
;
686 Res
= VisitProvides(D
,true);
695 // OrderList::DepUnPackPreD - Critical UnPacking ordering with depends /*{{{*/
696 // ---------------------------------------------------------------------
697 /* Critical PreDepends (also configure immediate and essential) strives to
698 ensure not only that all conflicts+predepends are met but that this
699 package will be immediately configurable when it is unpacked.
700 Loops are preprocessed and logged. */
701 bool pkgOrderList::DepUnPackPreD(DepIterator D
)
703 if (D
.Reverse() == true)
704 return DepUnPackCrit(D
);
706 for (; D
.end() == false; D
++)
708 if (D
.IsCritical() == false)
711 /* We wish to check if the dep is okay in the now state of the
712 target package against the install state of this package. */
713 if (CheckDep(D
) == true)
715 /* We want to catch predepends loops with the code below.
716 Conflicts loops that are Dep OK are ignored */
717 if (IsFlag(D
.TargetPkg(),AddPending
) == false ||
718 D
->Type
!= pkgCache::Dep::PreDepends
)
722 // This is the loop detection
723 if (IsFlag(D
.TargetPkg(),Added
) == true ||
724 IsFlag(D
.TargetPkg(),AddPending
) == true)
726 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
731 if (VisitProvides(D
,true) == false)
737 // OrderList::DepUnPackPre - Critical Predepends ordering /*{{{*/
738 // ---------------------------------------------------------------------
739 /* Critical PreDepends (also configure immediate and essential) strives to
740 ensure not only that all conflicts+predepends are met but that this
741 package will be immediately configurable when it is unpacked.
743 Loops are preprocessed and logged. All loops will be fatal. */
744 bool pkgOrderList::DepUnPackPre(DepIterator D
)
746 if (D
.Reverse() == true)
749 for (; D
.end() == false; D
++)
751 /* Only consider the PreDepends or Depends. Depends are only
752 considered at the lowest depth or in the case of immediate
754 if (D
->Type
!= pkgCache::Dep::PreDepends
)
756 if (D
->Type
== pkgCache::Dep::Depends
)
758 if (Depth
== 1 && IsFlag(D
.ParentPkg(),Immediate
) == false)
765 /* We wish to check if the dep is okay in the now state of the
766 target package against the install state of this package. */
767 if (CheckDep(D
) == true)
769 /* We want to catch predepends loops with the code below.
770 Conflicts loops that are Dep OK are ignored */
771 if (IsFlag(D
.TargetPkg(),AddPending
) == false)
775 // This is the loop detection
776 if (IsFlag(D
.TargetPkg(),Added
) == true ||
777 IsFlag(D
.TargetPkg(),AddPending
) == true)
779 if (IsFlag(D
.TargetPkg(),AddPending
) == true)
784 if (VisitProvides(D
,true) == false)
790 // OrderList::DepUnPackDep - Reverse dependency considerations /*{{{*/
791 // ---------------------------------------------------------------------
792 /* Reverse dependencies are considered to determine if unpacking this
793 package will break any existing dependencies. If so then those
794 packages are ordered before this one so that they are in the
797 The forwards depends loop is designed to bring the packages dependents
798 close to the package. This helps reduce deconfigure time.
800 Loops are irrelevent to this. */
801 bool pkgOrderList::DepUnPackDep(DepIterator D
)
804 for (; D
.end() == false; D
++)
805 if (D
.IsCritical() == true)
807 if (D
.Reverse() == true)
809 /* Duplication prevention. We consider rev deps only on
810 the current version, a not installed package
812 if (D
.ParentPkg()->CurrentVer
== 0 ||
813 D
.ParentPkg().CurrentVer() != D
.ParentVer())
816 // The dep will not break so it is irrelevent.
817 if (CheckDep(D
) == true)
820 // Skip over missing files
821 if (IsMissing(D
.ParentPkg()) == true)
824 if (VisitNode(D
.ParentPkg()) == false)
829 if (D
->Type
== pkgCache::Dep::Depends
)
830 if (VisitProvides(D
,false) == false)
833 if (D
->Type
== pkgCache::Dep::DpkgBreaks
)
835 if (CheckDep(D
) == true)
838 if (VisitNode(D
.TargetPkg()) == false)
846 // OrderList::DepConfigure - Configuration ordering /*{{{*/
847 // ---------------------------------------------------------------------
848 /* Configuration only ordering orders by the Depends: line only. It
849 orders configuration so that when a package comes to be configured it's
850 dependents are configured.
852 Loops are ingored. Depends loop entry points are chaotic. */
853 bool pkgOrderList::DepConfigure(DepIterator D
)
855 // Never consider reverse configuration dependencies.
856 if (D
.Reverse() == true)
859 for (; D
.end() == false; D
++)
860 if (D
->Type
== pkgCache::Dep::Depends
)
861 if (VisitProvides(D
,false) == false)
866 // OrderList::DepRemove - Removal ordering /*{{{*/
867 // ---------------------------------------------------------------------
868 /* Removal visits all reverse depends. It considers if the dependency
869 of the Now state version to see if it is okay with removing this
870 package. This check should always fail, but is provided for symetery
871 with the other critical handlers.
873 Loops are preprocessed and logged. Removal loops can also be
874 detected in the critical handler. They are characterized by an
875 old version of A depending on B but the new version of A conflicting
876 with B, thus either A or B must break to install. */
877 bool pkgOrderList::DepRemove(DepIterator D
)
879 if (D
.Reverse() == false)
881 for (; D
.end() == false; D
++)
882 if (D
->Type
== pkgCache::Dep::Depends
|| D
->Type
== pkgCache::Dep::PreDepends
)
884 // Duplication elimination, consider the current version only
885 if (D
.ParentPkg().CurrentVer() != D
.ParentVer())
888 /* We wish to see if the dep on the parent package is okay
889 in the removed (install) state of the target pkg. */
890 bool tryFixDeps
= false;
891 if (CheckDep(D
) == true)
893 // We want to catch loops with the code below.
894 if (IsFlag(D
.ParentPkg(),AddPending
) == false)
900 // This is the loop detection
901 if (IsFlag(D
.ParentPkg(),Added
) == true ||
902 IsFlag(D
.ParentPkg(),AddPending
) == true)
904 if (IsFlag(D
.ParentPkg(),AddPending
) == true)
909 if (tryFixDeps
== true)
911 for (pkgCache::DepIterator F
= D
.ParentPkg().CurrentVer().DependsList();
912 F
.end() == false; ++F
)
914 if (F
->Type
!= pkgCache::Dep::Depends
&& F
->Type
!= pkgCache::Dep::PreDepends
)
916 // Check the Providers
917 if (F
.TargetPkg()->ProvidesList
!= 0)
919 pkgCache::PrvIterator Prov
= F
.TargetPkg().ProvidesList();
920 for (; Prov
.end() == false; ++Prov
)
922 pkgCache::PkgIterator
const P
= Prov
.OwnerPkg();
923 if (IsFlag(P
, InList
) == true &&
924 IsFlag(P
, AddPending
) == true &&
925 IsFlag(P
, Added
) == false &&
926 Cache
[P
].InstallVer
== 0)
929 if (Prov
.end() == false)
930 for (pkgCache::PrvIterator Prv
= F
.TargetPkg().ProvidesList();
931 Prv
.end() == false; ++Prv
)
933 pkgCache::PkgIterator
const P
= Prv
.OwnerPkg();
934 if (IsFlag(P
, InList
) == true &&
935 IsFlag(P
, AddPending
) == false &&
936 Cache
[P
].InstallVer
!= 0 &&
937 VisitNode(P
) == true)
943 if (tryFixDeps
== false)
947 // Check for Or groups
948 if ((F
->CompareOp
& pkgCache::Dep::Or
) != pkgCache::Dep::Or
)
950 // Lets see if the package is part of the Or group
951 pkgCache::DepIterator S
= F
;
952 for (; S
.end() == false; ++S
)
954 if (S
.TargetPkg() == D
.TargetPkg())
956 if ((S
->CompareOp
& pkgCache::Dep::Or
) != pkgCache::Dep::Or
||
957 CheckDep(S
)) // Or group is satisfied by another package
958 for (;S
.end() == false; ++S
);
962 // skip to the end of the or group
963 for (;S
.end() == false && (S
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
; ++S
);
965 // The soon to be removed is part of the Or group
966 // start again in the or group and find something which will serve as replacement
967 for (; F
.end() == false && F
!= S
; ++F
)
969 if (F
.TargetPkg() == D
.TargetPkg() ||
970 IsFlag(F
.TargetPkg(), InList
) == false ||
971 VisitNode(F
.TargetPkg()) == false)
976 if (tryFixDeps
== false)
981 // Skip over missing files
982 if (IsMissing(D
.ParentPkg()) == true)
985 if (VisitNode(D
.ParentPkg()) == false)
992 // OrderList::AddLoop - Add a loop to the loop list /*{{{*/
993 // ---------------------------------------------------------------------
994 /* We record the loops. This is a relic since loop breaking is done
995 genericaly as part of the safety routines. */
996 bool pkgOrderList::AddLoop(DepIterator D
)
998 if (LoopCount
< 0 || LoopCount
>= 20)
1004 if (Loops
[LoopCount
- 1].ParentPkg() == D
.ParentPkg() ||
1005 Loops
[LoopCount
- 1].TargetPkg() == D
.ParentPkg())
1009 Loops
[LoopCount
++] = D
;
1011 // Mark the packages as being part of a loop.
1012 Flag(D
.TargetPkg(),Loop
);
1013 Flag(D
.ParentPkg(),Loop
);
1017 // OrderList::WipeFlags - Unset the given flags from all packages /*{{{*/
1018 // ---------------------------------------------------------------------
1020 void pkgOrderList::WipeFlags(unsigned long F
)
1022 unsigned long Size
= Cache
.Head().PackageCount
;
1023 for (unsigned long I
= 0; I
!= Size
; I
++)
1027 // OrderList::CheckDep - Check a dependency for truth /*{{{*/
1028 // ---------------------------------------------------------------------
1029 /* This performs a complete analysis of the dependency wrt to the
1030 current add list. It returns true if after all events are
1031 performed it is still true. This sort of routine can be approximated
1032 by examining the DepCache, however in convoluted cases of provides
1033 this fails to produce a suitable result. */
1034 bool pkgOrderList::CheckDep(DepIterator D
)
1036 SPtrArray
<Version
*> List
= D
.AllTargets();
1038 for (Version
**I
= List
; *I
!= 0; I
++)
1040 VerIterator
Ver(Cache
,*I
);
1041 PkgIterator Pkg
= Ver
.ParentPkg();
1043 /* The meaning of Added and AddPending is subtle. AddPending is
1044 an indication that the package is looping. Because of the
1045 way ordering works Added means the package will be unpacked
1046 before this one and AddPending means after. It is therefore
1047 correct to ignore AddPending in all cases, but that exposes
1048 reverse-ordering loops which should be ignored. */
1049 if (IsFlag(Pkg
,Added
) == true ||
1050 (IsFlag(Pkg
,AddPending
) == true && D
.Reverse() == true))
1052 if (Cache
[Pkg
].InstallVer
!= *I
)
1056 if ((Version
*)Pkg
.CurrentVer() != *I
||
1057 Pkg
.State() != PkgIterator::NeedsNothing
)
1060 /* Conflicts requires that all versions are not present, depends
1062 if (D
->Type
!= pkgCache::Dep::Conflicts
&&
1063 D
->Type
!= pkgCache::Dep::DpkgBreaks
&&
1064 D
->Type
!= pkgCache::Dep::Obsoletes
)
1066 /* Try to find something that does not have the after flag set
1067 if at all possible */
1068 if (IsFlag(Pkg
,After
) == true)
1078 if (IsFlag(Pkg
,After
) == true)
1079 Flag(D
.ParentPkg(),After
);
1085 // We found a hit, but it had the after flag set
1086 if (Hit
== true && D
->Type
== pkgCache::Dep::PreDepends
)
1088 Flag(D
.ParentPkg(),After
);
1092 /* Conflicts requires that all versions are not present, depends
1094 if (D
->Type
== pkgCache::Dep::Conflicts
||
1095 D
->Type
== pkgCache::Dep::Obsoletes
)