ordering.
Each of the features can be enabled in the sorting routine at an
- arbitary priority to give quite abit of control over the final unpacking
+ arbitrary priority to give quite abit of control over the final unpacking
order.
The rules listed above may never be violated and are called Critical.
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/orderlist.h"
-#endif
#include <apt-pkg/orderlist.h>
#include <apt-pkg/depcache.h>
#include <apt-pkg/error.h>
return false;
// Skip Packages that need configure only.
- if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
+ if ((Pkg.State() == pkgCache::PkgIterator::NeedsConfigure ||
+ Pkg.State() == pkgCache::PkgIterator::NeedsNothing) &&
Cache[Pkg].Keep() == true)
return false;
if (FileList[Pkg->ID].empty() == false)
return false;
+
return true;
}
/*}}}*/
-
// OrderList::DoRun - Does an order run /*{{{*/
// ---------------------------------------------------------------------
/* The caller is expeted to have setup the desired probe state */
bool pkgOrderList::OrderCritical()
{
FileList = 0;
-
- Primary = &pkgOrderList::DepUnPackPre;
+
+ Primary = &pkgOrderList::DepUnPackPreD;
Secondary = 0;
RevDepends = 0;
Remove = 0;
LoopCount = 0;
-
+
// Sort
Me = this;
- qsort(List,End - List,sizeof(*List),&OrderCompareB);
-
+ qsort(List,End - List,sizeof(*List),&OrderCompareB);
+
if (DoRun() == false)
return false;
-
+
if (LoopCount != 0)
return _error->Error("Fatal, predepends looping detected");
+
+ if (Debug == true)
+ {
+ clog << "** Critical Unpack ordering done" << endl;
+
+ for (iterator I = List; I != End; I++)
+ {
+ PkgIterator P(Cache,*I);
+ if (IsNow(P) == true)
+ clog << " " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+ }
+ }
+
return true;
}
/*}}}*/
if (FileList != 0)
{
WipeFlags(After);
-
+
// Set the inlist flag
for (iterator I = List; I != End; I++)
{
Flag(*I,After);
}
}
-
+
Primary = &pkgOrderList::DepUnPackCrit;
Secondary = &pkgOrderList::DepConfigure;
RevDepends = &pkgOrderList::DepUnPackDep;
clog << "** Pass A" << endl;
if (DoRun() == false)
return false;
-
+
if (Debug == true)
clog << "** Pass B" << endl;
Secondary = 0;
Remove = 0; // Otherwise the libreadline remove problem occures
if (DoRun() == false)
return false;
-
+
if (Debug == true)
clog << "** Pass D" << endl;
LoopCount = 0;
{
PkgIterator P(Cache,*I);
if (IsNow(P) == true)
- clog << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+ clog << " " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
}
- }
+ }
return true;
}
return DoRun();
}
/*}}}*/
-
// OrderList::Score - Score the package for sorting /*{{{*/
// ---------------------------------------------------------------------
/* Higher scores order earlier */
int pkgOrderList::Score(PkgIterator Pkg)
{
+ static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 500);
+
// Removal is always done first
if (Cache[Pkg].Delete() == true)
- return 200;
-
+ return ScoreDelete;
+
// This should never happen..
if (Cache[Pkg].InstVerIter(Cache).end() == true)
return -1;
-
+
+ static int const ScoreEssential = _config->FindI("OrderList::Score::Essential", 200);
+ static int const ScoreImmediate = _config->FindI("OrderList::Score::Immediate", 10);
+ static int const ScorePreDepends = _config->FindI("OrderList::Score::PreDepends", 50);
+
int Score = 0;
if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
- Score += 100;
+ Score += ScoreEssential;
if (IsFlag(Pkg,Immediate) == true)
- Score += 10;
-
- for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
+ Score += ScoreImmediate;
+
+ for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
D.end() == false; D++)
if (D->Type == pkgCache::Dep::PreDepends)
{
- Score += 50;
+ Score += ScorePreDepends;
break;
}
-
+
// Important Required Standard Optional Extra
signed short PrioMap[] = {0,5,4,3,1,0};
if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5)
int ScoreA = Me->Score(A);
int ScoreB = Me->Score(B);
+
if (ScoreA > ScoreB)
return -1;
int ScoreA = Me->Score(A);
int ScoreB = Me->Score(B);
+
if (ScoreA > ScoreB)
return -1;
return strcmp(A.Name(),B.Name());
}
/*}}}*/
-
// OrderList::VisitDeps - Visit forward install dependencies /*{{{*/
// ---------------------------------------------------------------------
/* This calls the dependency function for the normal forwards dependencies
bool Res = true;
for (PrvIterator P = Ver.ProvidesList(); P.end() == false; P++)
Res &= (this->*F)(P.ParentPkg().RevDependsList());
- return true;
+ return Res;
}
/*}}}*/
// OrderList::VisitProvides - Visit all of the providing packages /*{{{*/
if (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)
continue;
- if (D->Type != pkgCache::Dep::Conflicts &&
- D->Type != pkgCache::Dep::DpkgBreaks &&
- D->Type != pkgCache::Dep::Obsoletes &&
+ if (D.IsNegative() == false &&
Cache[Pkg].InstallVer != *I)
continue;
- if ((D->Type == pkgCache::Dep::Conflicts ||
- D->Type == pkgCache::Dep::DpkgBreaks ||
- D->Type == pkgCache::Dep::Obsoletes) &&
+ if (D.IsNegative() == true &&
(Version *)Pkg.CurrentVer() != *I)
continue;
if (Debug == true)
{
for (int j = 0; j != Depth; j++) clog << ' ';
- clog << "Visit " << Pkg.Name() << endl;
+ clog << "Visit " << Pkg.FullName() << endl;
}
Depth++;
if (Debug == true)
{
for (int j = 0; j != Depth; j++) clog << ' ';
- clog << "Leave " << Pkg.Name() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;
+ clog << "Leave " << Pkg.FullName() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;
}
return true;
}
/*}}}*/
-
// OrderList::DepUnPackCrit - Critical UnPacking ordering /*{{{*/
// ---------------------------------------------------------------------
/* Critical unpacking ordering strives to satisfy Conflicts: and
{
/* Forward critical dependencies MUST be correct before the
package can be unpacked. */
- if (D->Type != pkgCache::Dep::Conflicts &&
- D->Type != pkgCache::Dep::DpkgBreaks &&
- D->Type != pkgCache::Dep::Obsoletes &&
+ if (D.IsNegative() == false &&
D->Type != pkgCache::Dep::PreDepends)
continue;
}
return true;
}
-
+ /*}}}*/
// OrderList::DepUnPackPreD - Critical UnPacking ordering with depends /*{{{*/
// ---------------------------------------------------------------------
/* Critical PreDepends (also configure immediate and essential) strives to
ensure not only that all conflicts+predepends are met but that this
- package will be immediately configurable when it is unpacked.
-
+ package will be immediately configurable when it is unpacked.
Loops are preprocessed and logged. */
bool pkgOrderList::DepUnPackPreD(DepIterator D)
{
continue;
/* We wish to see if the dep on the parent package is okay
- in the removed (install) state of the target pkg. */
+ in the removed (install) state of the target pkg. */
+ bool tryFixDeps = false;
if (CheckDep(D) == true)
{
// We want to catch loops with the code below.
if (IsFlag(D.ParentPkg(),AddPending) == false)
continue;
}
+ else
+ tryFixDeps = true;
// This is the loop detection
if (IsFlag(D.ParentPkg(),Added) == true ||
continue;
}
+ if (tryFixDeps == true)
+ {
+ for (pkgCache::DepIterator F = D.ParentPkg().CurrentVer().DependsList();
+ F.end() == false; ++F)
+ {
+ if (F->Type != pkgCache::Dep::Depends && F->Type != pkgCache::Dep::PreDepends)
+ continue;
+ // Check the Providers
+ if (F.TargetPkg()->ProvidesList != 0)
+ {
+ pkgCache::PrvIterator Prov = F.TargetPkg().ProvidesList();
+ for (; Prov.end() == false; ++Prov)
+ {
+ pkgCache::PkgIterator const P = Prov.OwnerPkg();
+ if (IsFlag(P, InList) == true &&
+ IsFlag(P, AddPending) == true &&
+ IsFlag(P, Added) == false &&
+ Cache[P].InstallVer == 0)
+ break;
+ }
+ if (Prov.end() == false)
+ for (pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList();
+ Prv.end() == false; ++Prv)
+ {
+ pkgCache::PkgIterator const P = Prv.OwnerPkg();
+ if (IsFlag(P, InList) == true &&
+ IsFlag(P, AddPending) == false &&
+ Cache[P].InstallVer != 0 &&
+ VisitNode(P) == true)
+ {
+ Flag(P, Immediate);
+ tryFixDeps = false;
+ break;
+ }
+ }
+ if (tryFixDeps == false)
+ break;
+ }
+
+ // Check for Or groups
+ if ((F->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or)
+ continue;
+ // Lets see if the package is part of the Or group
+ pkgCache::DepIterator S = F;
+ for (; S.end() == false; ++S)
+ {
+ if (S.TargetPkg() == D.TargetPkg())
+ break;
+ if ((S->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or ||
+ CheckDep(S)) // Or group is satisfied by another package
+ for (;S.end() == false; ++S);
+ }
+ if (S.end() == true)
+ continue;
+ // skip to the end of the or group
+ for (;S.end() == false && (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; ++S);
+ ++S;
+ // The soon to be removed is part of the Or group
+ // start again in the or group and find something which will serve as replacement
+ for (; F.end() == false && F != S; ++F)
+ {
+ if (IsFlag(F.TargetPkg(), InList) == true &&
+ IsFlag(F.TargetPkg(), AddPending) == false &&
+ Cache[F.TargetPkg()].InstallVer != 0 &&
+ VisitNode(F.TargetPkg()) == true)
+ {
+ Flag(F.TargetPkg(), Immediate);
+ tryFixDeps = false;
+ break;
+ }
+ else if (F.TargetPkg()->ProvidesList != 0)
+ {
+ pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList();
+ for (; Prv.end() == false; ++Prv)
+ {
+ if (IsFlag(Prv.OwnerPkg(), InList) == true &&
+ IsFlag(Prv.OwnerPkg(), AddPending) == false &&
+ Cache[Prv.OwnerPkg()].InstallVer != 0 &&
+ VisitNode(Prv.OwnerPkg()) == true)
+ {
+ Flag(Prv.OwnerPkg(), Immediate);
+ tryFixDeps = false;
+ break;
+ }
+ }
+ if (Prv.end() == false)
+ break;
+ }
+ }
+ if (tryFixDeps == false)
+ break;
+ }
+ }
+
// Skip over missing files
if (IsMissing(D.ParentPkg()) == true)
continue;
return true;
}
/*}}}*/
-
// OrderList::AddLoop - Add a loop to the loop list /*{{{*/
// ---------------------------------------------------------------------
/* We record the loops. This is a relic since loop breaking is done
/* Conflicts requires that all versions are not present, depends
just needs one */
- if (D->Type != pkgCache::Dep::Conflicts &&
- D->Type != pkgCache::Dep::DpkgBreaks &&
- D->Type != pkgCache::Dep::Obsoletes)
+ if (D.IsNegative() == false)
{
+ // ignore provides by older versions of this package
+ if (((D.Reverse() == false && Pkg == D.ParentPkg()) ||
+ (D.Reverse() == true && Pkg == D.TargetPkg())) &&
+ Cache[Pkg].InstallVer != *I)
+ continue;
+
/* Try to find something that does not have the after flag set
if at all possible */
if (IsFlag(Pkg,After) == true)