summaryrefslogtreecommitdiff
path: root/apt-pkg/orderlist.cc
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/orderlist.cc')
-rw-r--r--apt-pkg/orderlist.cc95
1 files changed, 89 insertions, 6 deletions
diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc
index 0ee2e2bc8..602b63d3b 100644
--- a/apt-pkg/orderlist.cc
+++ b/apt-pkg/orderlist.cc
@@ -117,7 +117,8 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
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;
@@ -126,6 +127,11 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
if (FileList[Pkg->ID].empty() == false)
return false;
+
+ // Missing Pseudo packages are missing if the real package is missing
+ if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true)
+ return IsMissing(Pkg.Group().FindPkg("all"));
+
return true;
}
/*}}}*/
@@ -199,7 +205,7 @@ bool pkgOrderList::OrderCritical()
{
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;
}
}
@@ -272,7 +278,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
{
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;
}
}
@@ -543,7 +549,7 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg)
if (Debug == true)
{
for (int j = 0; j != Depth; j++) clog << ' ';
- clog << "Visit " << Pkg.Name() << endl;
+ clog << "Visit " << Pkg.FullName() << endl;
}
Depth++;
@@ -602,7 +608,7 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg)
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;
@@ -880,13 +886,16 @@ bool pkgOrderList::DepRemove(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 ||
@@ -897,6 +906,80 @@ bool pkgOrderList::DepRemove(DepIterator D)
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 (F.TargetPkg() == D.TargetPkg() ||
+ IsFlag(F.TargetPkg(), InList) == false ||
+ VisitNode(F.TargetPkg()) == false)
+ continue;
+ Flag(F.TargetPkg(), Immediate);
+ tryFixDeps = false;
+ break;
+ }
+ if (tryFixDeps == false)
+ break;
+ }
+ }
+
// Skip over missing files
if (IsMissing(D.ParentPkg()) == true)
continue;