X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/8a3a2e994e0e49fb5b610dba0f810b67f0ab229e..3bb98bee11b38df0264099f3c9e858880759999d:/apt-pkg/depcache.cc diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 4794d3503..ca9636cc1 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -8,9 +8,6 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#ifdef __GNUG__ -#pragma implementation "apt-pkg/depcache.h" -#endif #include #include #include @@ -181,7 +178,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) return true; } -bool pkgDepCache::writeStateFile(OpProgress *prog) +bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) { if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "pkgDepCache::writeStateFile()" << std::endl; @@ -243,6 +240,9 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) std::clog << "Skipping already written " << pkg.Name() << std::endl; continue; } + // skip not installed ones if requested + if(InstalledOnly && pkg->CurrentVer == 0) + continue; if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "Writing new AutoInstall: " << pkg.Name() << std::endl; @@ -276,7 +276,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) we allow it anyhow because dpkg does. Technically it is a packaging bug. Conflicts may never self match */ if (Dep.TargetPkg() != Dep.ParentPkg() || - (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes)) + (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes)) { PkgIterator Pkg = Dep.TargetPkg(); // Check the base package @@ -306,7 +306,8 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) { /* Provides may never be applied against the same package if it is a conflicts. See the comment above. */ - if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts) + if (P.OwnerPkg() == Pkg && + (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks)) continue; // Check if the provides is a hit @@ -402,9 +403,11 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add) { StateCache &State = PkgState[Pkg->ID]; - // The Package is broken + // The Package is broken (either minimal dep or policy dep) if ((State.DepState & DepInstMin) != DepInstMin) iBrokenCount += Add; + if ((State.DepState & DepInstPolicy) != DepInstPolicy) + iPolicyBrokenCount += Add; // Bad state if (Pkg.State() != PkgIterator::NeedsNothing) @@ -458,7 +461,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) /* Invert for Conflicts. We have to do this twice to get the right sense for a conflicts group */ - if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) + if (D->Type == Dep::Conflicts || + D->Type == Dep::DpkgBreaks || + D->Type == Dep::Obsoletes) State = ~State; // Add to the group if we are within an or.. @@ -469,7 +474,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) Group = 0; // Invert for Conflicts - if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) + if (D->Type == Dep::Conflicts || + D->Type == Dep::DpkgBreaks || + D->Type == Dep::Obsoletes) State = ~State; } } @@ -602,7 +609,9 @@ void pkgDepCache::Update(OpProgress *Prog) Group = 0; // Invert for Conflicts - if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) + if (D->Type == Dep::Conflicts || + D->Type == Dep::DpkgBreaks || + D->Type == Dep::Obsoletes) State = ~State; } } @@ -632,7 +641,9 @@ void pkgDepCache::Update(DepIterator D) State = DependencyState(D); // Invert for Conflicts - if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) + if (D->Type == Dep::Conflicts || + D->Type == Dep::DpkgBreaks || + D->Type == Dep::Obsoletes) State = ~State; RemoveStates(D.ParentPkg()); @@ -704,7 +715,6 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser) // We dont even try to keep virtual packages.. if (Pkg->VersionList == 0) return; - #if 0 // reseting the autoflag here means we lose the // auto-mark information if a user selects a package for removal // but changes his mind then and sets it for keep again @@ -775,7 +785,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge) // --------------------------------------------------------------------- /* */ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, - unsigned long Depth, bool FromUser) + unsigned long Depth, bool FromUser, + bool ForceImportantDeps) { if (Depth > 100) return; @@ -790,7 +801,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, installed */ StateCache &P = PkgState[Pkg->ID]; P.iFlags &= ~AutoKept; - if (P.InstBroken() == false && (P.Mode == ModeInstall || + if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && + (P.Mode == ModeInstall || P.CandidateVer == (Version *)Pkg.CurrentVer())) { if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0) @@ -801,11 +813,9 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, // See if there is even any possible instalation candidate if (P.CandidateVer == 0) return; - // We dont even try to install virtual packages.. if (Pkg->VersionList == 0) return; - /* Target the candidate version and remove the autoflag. We reset the autoflag below if this was called recursively. Otherwise the user should have the ability to de-auto a package by changing its state */ @@ -859,10 +869,43 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /* Check if this dep should be consider for install. If it is a user defined important dep and we are installed a new package then - it will be installed. Otherwise we only worry about critical deps */ + it will be installed. Otherwise we only check for important + deps that have changed from the installed version + */ if (IsImportantDep(Start) == false) continue; - if (Pkg->CurrentVer != 0 && Start.IsCritical() == false) + + /* check if any ImportantDep() (but not Critial) where added + * since we installed the package + */ + bool isNewImportantDep = false; + if(!ForceImportantDeps && !Start.IsCritical()) + { + bool found=false; + VerIterator instVer = Pkg.CurrentVer(); + if(!instVer.end()) + { + for (DepIterator D = instVer.DependsList(); D.end() != true; D++) + { + //FIXME: deal better with or-groups(?) + DepIterator LocalStart = D; + + if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg()) + found=true; + } + // this is a new dep if it was not found to be already + // a important dep of the installed pacakge + isNewImportantDep = !found; + } + } + if(isNewImportantDep) + if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true) + std::clog << "new important dependency: " + << Start.TargetPkg().Name() << std::endl; + + // skip important deps if the package is already installed + if (Pkg->CurrentVer != 0 && Start.IsCritical() == false + && !isNewImportantDep && !ForceImportantDeps) continue; /* If we are in an or group locate the first or that can @@ -873,7 +916,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /* This bit is for processing the possibilty of an install/upgrade fixing the problem */ SPtrArray List = Start.AllTargets(); - if ((DepState[Start->ID] & DepCVer) == DepCVer) + if (Start->Type != Dep::DpkgBreaks && + (DepState[Start->ID] & DepCVer) == DepCVer) { // Right, find the best version to install.. Version **Cur = List; @@ -921,7 +965,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, else { // mark automatic dependency - MarkInstall(InstPkg,true,Depth + 1, false); + MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps); // Set the autoflag, after MarkInstall because MarkInstall unsets it if (P->CurrentVer == 0) PkgState[InstPkg->ID].Flags |= Flag::Auto; @@ -929,17 +973,23 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, } continue; } - + /* For conflicts we just de-install the package and mark as auto, - Conflicts may not have or groups */ - if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes) + Conflicts may not have or groups. For dpkg's Breaks we try to + upgrade the package. */ + if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes || + Start->Type == Dep::DpkgBreaks) { for (Version **I = List; *I != 0; I++) { VerIterator Ver(*this,*I); PkgIterator Pkg = Ver.ParentPkg(); - - MarkDelete(Pkg); + + if (Start->Type != Dep::DpkgBreaks) + MarkDelete(Pkg); + else + if (PkgState[Pkg->ID].CandidateVer != *I) + MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps); } continue; } @@ -1087,7 +1137,28 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg) /* */ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep) { - return Dep.IsCritical(); + if(Dep.IsCritical()) + return true; + else if(Dep->Type == pkgCache::Dep::Recommends) + { + if ( _config->FindB("APT::Install-Recommends", false)) + return true; + // we suport a special mode to only install-recommends for certain + // sections + // FIXME: this is a meant as a temporarly solution until the + // recommends are cleaned up + string s = _config->Find("APT::Install-Recommends-Section",""); + if(s.size() > 0) + { + const char *sec = Dep.ParentVer().Section(); + if (sec && strcmp(sec, s.c_str()) == 0) + return true; + } + } + else if(Dep->Type == pkgCache::Dep::Suggests) + return _config->FindB("APT::Install-Suggests", false); + + return false; } /*}}}*/ @@ -1307,3 +1378,4 @@ bool pkgDepCache::Sweep() return true; } +