diff options
Diffstat (limited to 'apt-pkg/orderlist.cc')
-rw-r--r-- | apt-pkg/orderlist.cc | 95 |
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; |