X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/24fd9c0645b34ebb433588582d4e593cfcc5427a..6c55f07a5fa3612a5d59c61a17da5fe640eadc8b:/apt-pkg/depcache.cc diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index deb8ec21f..d01c14223 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -11,23 +11,28 @@ #include #include -#include #include #include #include -#include #include #include #include #include -#include #include #include #include - +#include +#include +#include + +#include +#include +#include +#include +#include +#include #include #include -#include #include #include @@ -58,7 +63,7 @@ ConfigValueInSubTree(const char* SubTree, const char *needle) } /*}}}*/ pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) : /*{{{*/ - cache(cache), released(false) + d(NULL), cache(cache), released(false) { ++cache.group_level; } @@ -90,7 +95,9 @@ pkgDepCache::ActionGroup::~ActionGroup() // --------------------------------------------------------------------- /* */ pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) : - group_level(0), Cache(pCache), PkgState(0), DepState(0) + group_level(0), Cache(pCache), PkgState(0), DepState(0), + iUsrSize(0), iDownloadSize(0), iInstCount(0), iDelCount(0), iKeepCount(0), + iBrokenCount(0), iPolicyBrokenCount(0), iBadCount(0), d(NULL) { DebugMarker = _config->FindB("Debug::pkgDepCache::Marker", false); DebugAutoInstall = _config->FindB("Debug::pkgDepCache::AutoInstall", false); @@ -222,7 +229,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ return true; } /*}}}*/ -bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ +bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{{*/ { bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); @@ -231,9 +238,11 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ FileFd StateFile; string const state = _config->FindFile("Dir::State::extended_states"); + if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), flNotFile(state)) == false) + return false; // if it does not exist, create a empty one - if(!RealFileExists(state)) + if(!RealFileExists(state)) { StateFile.Open(state, FileFd::WriteAtomic); StateFile.Close(); @@ -244,17 +253,14 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ return _error->Error(_("Failed to open StateFile %s"), state.c_str()); - FILE *OutFile; - string const outfile = state + ".tmp"; - if((OutFile = fopen(outfile.c_str(),"w")) == NULL) - return _error->Error(_("Failed to write temporary StateFile %s"), - outfile.c_str()); + FileFd OutFile(state, FileFd::ReadWrite | FileFd::Atomic); + if (OutFile.IsOpen() == false || OutFile.Failed() == true) + return _error->Error(_("Failed to write temporary StateFile %s"), state.c_str()); // first merge with the existing sections pkgTagFile tagfile(&StateFile); pkgTagSection section; std::set pkgs_seen; - const char *nullreorderlist[] = {0}; while(tagfile.Step(section)) { string const pkgname = section.FindS("Package"); string pkgarch = section.FindS("Architecture"); @@ -263,7 +269,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ // Silently ignore unknown packages and packages with no actual // version. pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch); - if(pkg.end() || pkg.VersionList().end()) + if(pkg.end() || pkg.VersionList().end()) continue; StateCache const &P = PkgState[pkg->ID]; bool newAuto = (P.Flags & Flag::Auto); @@ -284,21 +290,17 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "Update existing AutoInstall info: " << pkg.FullName() << std::endl; - TFRewriteData rewrite[3]; - rewrite[0].Tag = "Architecture"; - rewrite[0].Rewrite = pkg.Arch(); - rewrite[0].NewTag = 0; - rewrite[1].Tag = "Auto-Installed"; - rewrite[1].Rewrite = newAuto ? "1" : "0"; - rewrite[1].NewTag = 0; - rewrite[2].Tag = 0; - TFRewrite(OutFile, section, nullreorderlist, rewrite); - fprintf(OutFile,"\n"); + + std::vector rewrite; + rewrite.push_back(pkgTagSection::Tag::Rewrite("Architecture", pkg.Arch())); + rewrite.push_back(pkgTagSection::Tag::Rewrite("Auto-Installed", newAuto ? "1" : "0")); + section.Write(OutFile, NULL, rewrite); + if (OutFile.Write("\n", 1) == false) + return false; pkgs_seen.insert(pkg.FullName()); } - + // then write the ones we have not seen yet - std::ostringstream ostr; for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); ++pkg) { StateCache const &P = PkgState[pkg->ID]; if(P.Flags & Flag::Auto) { @@ -317,19 +319,17 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ continue; if(debug_autoremove) std::clog << "Writing new AutoInstall: " << pkg.FullName() << std::endl; - ostr.str(string("")); - ostr << "Package: " << pkg.Name() - << "\nArchitecture: " << pkgarch - << "\nAuto-Installed: 1\n\n"; - fprintf(OutFile,"%s",ostr.str().c_str()); + std::string stanza = "Package: "; + stanza.append(pkg.Name()) + .append("\nArchitecture: ").append(pkgarch) + .append("\nAuto-Installed: 1\n\n"); + if (OutFile.Write(stanza.c_str(), stanza.length()) == false) + return false; } } - fclose(OutFile); - - // move the outfile over the real file and set permissions - rename(outfile.c_str(), state.c_str()); + if (OutFile.Close() == false) + return false; chmod(state.c_str(), 0644); - return true; } /*}}}*/ @@ -351,18 +351,15 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) PkgIterator Pkg = Dep.TargetPkg(); // Check the base package if (Type == NowVersion && Pkg->CurrentVer != 0) - if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp, - Dep.TargetVer()) == true) + if (Dep.IsSatisfied(Pkg.CurrentVer()) == true) return true; if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0) - if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(), - Dep->CompareOp,Dep.TargetVer()) == true) + if (Dep.IsSatisfied(PkgState[Pkg->ID].InstVerIter(*this)) == true) return true; if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0) - if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(), - Dep->CompareOp,Dep.TargetVer()) == true) + if (Dep.IsSatisfied(PkgState[Pkg->ID].CandidateVerIter(*this)) == true) return true; } @@ -398,7 +395,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) } // Compare the versions. - if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true) + if (Dep.IsSatisfied(P) == true) { Res = P.OwnerPkg(); return true; @@ -660,10 +657,11 @@ void pkgDepCache::Update(OpProgress *Prog) { iUsrSize = 0; iDownloadSize = 0; - iDelCount = 0; iInstCount = 0; + iDelCount = 0; iKeepCount = 0; iBrokenCount = 0; + iPolicyBrokenCount = 0; iBadCount = 0; // Perform the depends pass @@ -792,7 +790,7 @@ bool pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser, // - this makes sense as default when all Garbage dependencies // are automatically marked for removal (as aptitude does). // setting a package for keep then makes it no longer autoinstalled - // for all other use-case this action is rather suprising + // for all other use-case this action is rather surprising if(FromUser && !P.Marked) P.Flags &= ~Flag::Auto; #endif @@ -867,6 +865,11 @@ bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, dpkg holds are enforced by the private IsModeChangeOk */ bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge, unsigned long Depth, bool FromUser) +{ + return IsDeleteOkProtectInstallRequests(Pkg, rPurge, Depth, FromUser); +} +bool pkgDepCache::IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg, + bool const /*rPurge*/, unsigned long const Depth, bool const FromUser) { if (FromUser == false && Pkg->CurrentVer == 0) { @@ -887,13 +890,14 @@ bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge, and prevents mode changes for packages on hold for example. If you want to check Mode specific stuff you can use the virtual public IsOk methods instead */ -char const* PrintMode(char const mode) +static char const* PrintMode(char const mode) { switch (mode) { case pkgDepCache::ModeInstall: return "Install"; case pkgDepCache::ModeKeep: return "Keep"; case pkgDepCache::ModeDelete: return "Delete"; + case pkgDepCache::ModeGarbage: return "Garbage"; default: return "UNKNOWN"; } } @@ -913,11 +917,15 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, return true; StateCache &P = PkgState[Pkg->ID]; + // not changing the mode is obviously also fine as we might want to call + // e.g. MarkInstall multiple times with different arguments for the same package + if (P.Mode == mode) + return true; // if previous state was set by user only user can reset it if ((P.iFlags & Protected) == Protected) { - if (unlikely(DebugMarker == true) && P.Mode != mode) + if (unlikely(DebugMarker == true)) std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode) << " of " << Pkg << " as its mode (" << PrintMode(P.Mode) << ") is protected" << std::endl; @@ -927,7 +935,7 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, else if (mode != ModeKeep && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false) { - if (unlikely(DebugMarker == true) && P.Mode != mode) + if (unlikely(DebugMarker == true)) std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode) << " of " << Pkg << std::endl; return false; @@ -941,12 +949,43 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, /* */ struct CompareProviders { pkgCache::PkgIterator const Pkg; - CompareProviders(pkgCache::DepIterator const &Dep) : Pkg(Dep.TargetPkg()) {}; + explicit CompareProviders(pkgCache::DepIterator const &Dep) : Pkg(Dep.TargetPkg()) {}; //bool operator() (APT::VersionList::iterator const &AV, APT::VersionList::iterator const &BV) bool operator() (pkgCache::VerIterator const &AV, pkgCache::VerIterator const &BV) { pkgCache::PkgIterator const A = AV.ParentPkg(); pkgCache::PkgIterator const B = BV.ParentPkg(); + // Prefer MA:same packages if other architectures for it are installed + if ((AV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same || + (BV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) + { + bool instA = false; + if ((AV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) + { + pkgCache::GrpIterator Grp = A.Group(); + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + if (P->CurrentVer != 0) + { + instA = true; + break; + } + } + bool instB = false; + if ((BV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) + { + pkgCache::GrpIterator Grp = B.Group(); + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + { + if (P->CurrentVer != 0) + { + instB = true; + break; + } + } + } + if (instA != instB) + return instA == false; + } // Prefer packages in the same group as the target; e.g. foo:i386, foo:amd64 if (A->Group != B->Group) { @@ -970,9 +1009,6 @@ struct CompareProviders { else if ((B->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) return true; } - // higher priority seems like a good idea - if (AV->Priority != BV->Priority) - return AV->Priority < BV->Priority; // prefer native architecture if (strcmp(A.Arch(), B.Arch()) != 0) { @@ -987,6 +1023,9 @@ struct CompareProviders { else if (*a == B.Arch()) return true; } + // higher priority seems like a good idea + if (AV->Priority != BV->Priority) + return AV->Priority > BV->Priority; // unable to decide… return A->ID < B->ID; } @@ -1078,27 +1117,22 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, continue; /* 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 + defined important dep and we are installed a new package then it will be installed. Otherwise we only check for important - deps that have changed from the installed version - */ + deps that have changed from the installed version */ if (IsImportantDep(Start) == false) continue; - /* If we are in an or group locate the first or that can - succeed. We have already cached this.. */ + /* If we are in an or group locate the first or that can + succeed. We have already cached this… */ for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; --Ors) ++Start; + + /* unsatisfiable dependency: IsInstallOkDependenciesSatisfiableByCandidates + would have prevented us to get here if not overridden, so just skip + over the problem here as the frontend will know what it is doing */ if (Ors == 1 && (DepState[Start->ID] &DepCVer) != DepCVer && Start.IsNegative() == false) - { - if(DebugAutoInstall == true) - std::clog << OutputInDepth(Depth) << Start << " can't be satisfied!" << std::endl; - if (Start.IsCritical() == false) - continue; - // if the dependency was critical, we can't install it, so remove it again - MarkDelete(Pkg,false,Depth + 1, false); - return false; - } + continue; /* Check if any ImportantDep() (but not Critical) were added * since we installed the package. Also check for deps that @@ -1151,50 +1185,50 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, } } - /* This bit is for processing the possibilty of an install/upgrade + /* This bit is for processing the possibility of an install/upgrade fixing the problem for "positive" dependencies */ if (Start.IsNegative() == false && (DepState[Start->ID] & DepCVer) == DepCVer) { APT::VersionList verlist; pkgCache::VerIterator Cand = PkgState[Start.TargetPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == false && VS().CheckDep(Cand.VerStr(), Start->CompareOp, Start.TargetVer()) == true) + if (Cand.end() == false && Start.IsSatisfied(Cand) == true) verlist.insert(Cand); for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv) { pkgCache::VerIterator V = Prv.OwnerVer(); pkgCache::VerIterator Cand = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == true || V != Cand || - VS().CheckDep(Prv.ProvideVersion(), Start->CompareOp, Start.TargetVer()) == false) + if (Cand.end() == true || V != Cand || Start.IsSatisfied(Prv) == false) continue; verlist.insert(Cand); } CompareProviders comp(Start); - APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp); - if (InstVer != verlist.end()) - { + do { + APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp); + + if (InstVer == verlist.end()) + break; + pkgCache::PkgIterator InstPkg = InstVer.ParentPkg(); if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name() << " as " << Start.DepType() << " of " << Pkg.Name() << std::endl; - // now check if we should consider it a automatic dependency or not - if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section())) - { + if (MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps) == false) + { + verlist.erase(InstVer); + continue; + } + // now check if we should consider it a automatic dependency or not + if(InstPkg->CurrentVer == 0 && InstVer->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", InstVer.Section())) + { if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct " << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl; - MarkInstall(InstPkg,true,Depth + 1, true); - } - else - { - // mark automatic dependency - MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps); - // Set the autoflag, after MarkInstall because MarkInstall unsets it - if (InstPkg->CurrentVer == 0) - PkgState[InstPkg->ID].Flags |= Flag::Auto; - } - } + MarkAuto(InstPkg, false); + } + break; + } while(true); continue; } /* Negative dependencies have no or-group @@ -1214,14 +1248,26 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, if (PkgState[Pkg->ID].InstallVer == 0) continue; + /* Ignore negative dependencies that we are not going to + get installed */ + if (PkgState[Pkg->ID].InstallVer != *I) + continue; + if ((Start->Version != 0 || TrgPkg != Pkg) && PkgState[Pkg->ID].CandidateVer != PkgState[Pkg->ID].InstallVer && PkgState[Pkg->ID].CandidateVer != *I && MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps) == true) continue; - else if ((Start->Type == pkgCache::Dep::Conflicts || Start->Type == pkgCache::Dep::DpkgBreaks) && - MarkDelete(Pkg,false,Depth + 1, false) == false) - break; + else if (Start->Type == pkgCache::Dep::Conflicts || + Start->Type == pkgCache::Dep::DpkgBreaks) + { + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) + << " Removing: " << Pkg.Name() + << std::endl; + if (MarkDelete(Pkg,false,Depth + 1, false) == false) + break; + } } continue; } @@ -1232,11 +1278,108 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /*}}}*/ // DepCache::IsInstallOk - check if it is ok to install this package /*{{{*/ // --------------------------------------------------------------------- -/* The default implementation does nothing. +/* The default implementation checks if the installation of an M-A:same + package would lead us into a version-screw and if so forbids it. dpkg holds are enforced by the private IsModeChangeOk */ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst, unsigned long Depth, bool FromUser) { + return IsInstallOkMultiArchSameVersionSynced(Pkg,AutoInst, Depth, FromUser) && + IsInstallOkDependenciesSatisfiableByCandidates(Pkg,AutoInst, Depth, FromUser); +} +bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, + bool const /*AutoInst*/, unsigned long const Depth, bool const FromUser) +{ + if (FromUser == true) // as always: user is always right + return true; + + // if we have checked before and it was okay, it will still be okay + if (PkgState[Pkg->ID].Mode == ModeInstall && + PkgState[Pkg->ID].InstallVer == PkgState[Pkg->ID].CandidateVer) + return true; + + // ignore packages with none-M-A:same candidates + VerIterator const CandVer = PkgState[Pkg->ID].CandidateVerIter(*this); + if (unlikely(CandVer.end() == true) || CandVer == Pkg.CurrentVer() || + (CandVer->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same) + return true; + + GrpIterator const Grp = Pkg.Group(); + for (PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + { + // not installed or self-check: fine by definition + if (P->CurrentVer == 0 || P == Pkg) + continue; + + // not having a candidate or being in sync + // (simple string-compare as stuff like '1' == '0:1-0' can't happen here) + VerIterator CV = PkgState[P->ID].CandidateVerIter(*this); + if (CV.end() == true || strcmp(Pkg.CandVersion(), CV.VerStr()) == 0) + continue; + + // packages losing M-A:same can be out-of-sync + if ((CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same) + continue; + + // not downloadable means the package is obsolete, so allow out-of-sync + if (CV.Downloadable() == false) + continue; + + PkgState[Pkg->ID].iFlags |= AutoKept; + if (unlikely(DebugMarker == true)) + std::clog << OutputInDepth(Depth) << "Ignore MarkInstall of " << Pkg + << " as it is not in sync with its M-A:same sibling " << P + << " (" << Pkg.CandVersion() << " != " << CV.VerStr() << ")" << std::endl; + return false; + } + + return true; +} +bool pkgDepCache::IsInstallOkDependenciesSatisfiableByCandidates(PkgIterator const &Pkg, + bool const AutoInst, unsigned long const Depth, bool const /*FromUser*/) +{ + if (AutoInst == false) + return true; + + VerIterator const CandVer = PkgState[Pkg->ID].CandidateVerIter(*this); + if (unlikely(CandVer.end() == true) || CandVer == Pkg.CurrentVer()) + return true; + + for (DepIterator Dep = CandVer.DependsList(); Dep.end() != true;) + { + // Grok or groups + DepIterator Start = Dep; + bool Result = true; + unsigned Ors = 0; + for (bool LastOR = true; Dep.end() == false && LastOR == true; ++Dep, ++Ors) + { + LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or; + + if ((DepState[Dep->ID] & DepInstall) == DepInstall) + Result = false; + } + + if (Start.IsCritical() == false || Start.IsNegative() == true || Result == false) + continue; + + /* If we are in an or group locate the first or that can succeed. + We have already cached this… */ + for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; --Ors) + ++Start; + + if (Ors == 1 && (DepState[Start->ID] &DepCVer) != DepCVer) + { + if (DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << Start << " can't be satisfied!" << std::endl; + + // the dependency is critical, but can't be installed, so discard the candidate + // as the problemresolver will trip over it otherwise trying to install it (#735967) + if (Pkg->CurrentVer != 0 && (PkgState[Pkg->ID].iFlags & Protected) != Protected) + SetCandidateVersion(Pkg.CurrentVer()); + return false; + } + } + return true; } /*}}}*/ @@ -1379,7 +1522,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer, if (Cand.end() == true) continue; // check if the current candidate is enough for the versioned dependency - and installable? - if (VS().CheckDep(P.CandVersion(), Start->CompareOp, Start.TargetVer()) == true && + if (Start.IsSatisfied(Cand) == true && (VersionState(Cand.DependsList(), DepInstall, DepCandMin, DepCandPolicy) & DepCandMin) == DepCandMin) { itsFine = true; @@ -1413,7 +1556,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer, V = Match.Find(D.TargetPkg()); // check if the version from this release could satisfy the dependency - if (V.end() == true || VS().CheckDep(V.VerStr(), D->CompareOp, D.TargetVer()) == false) + if (V.end() == true || D.IsSatisfied(V) == false) { if (stillOr == true) continue; @@ -1437,7 +1580,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer, if (itsFine == false) { // change the candidate - Changed.push_back(make_pair(oldCand, TargetVer)); + Changed.push_back(make_pair(V, TargetVer)); if (SetCandidateRelease(V, TargetRel, Changed) == false) { if (stillOr == false) @@ -1535,7 +1678,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk { /* Not source/not automatic versions cannot be a candidate version unless they are already installed */ - VerIterator Last(*(pkgCache *)this,0); + VerIterator Last; for (VerIterator I = Pkg.VersionList(); I.end() == false; ++I) { @@ -1544,13 +1687,13 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk for (VerFileIterator J = I.FileList(); J.end() == false; ++J) { - if ((J.File()->Flags & Flag::NotSource) != 0) + if (J.File().Flagged(Flag::NotSource)) continue; /* Stash the highest version of a not-automatic source, we use it if there is nothing better */ - if ((J.File()->Flags & Flag::NotAutomatic) != 0 || - (J.File()->Flags & Flag::ButAutomaticUpgrades) != 0) + if (J.File().Flagged(Flag::NotAutomatic) || + J.File().Flagged(Flag::ButAutomaticUpgrades)) { if (Last.end() == true) Last = I; @@ -1590,10 +1733,10 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) } /*}}}*/ // Policy::GetPriority - Get the priority of the package pin /*{{{*/ -signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgIterator const &Pkg) -{ return 0; }; -signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgFileIterator const &File) -{ return 0; }; +APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgIterator const &/*Pkg*/) +{ return 0; } +APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgFileIterator const &/*File*/) +{ return 0; } /*}}}*/ pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc() /*{{{*/ { @@ -1642,8 +1785,6 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) follow_recommends = MarkFollowsRecommends(); follow_suggests = MarkFollowsSuggests(); - - // do the mark part, this is the core bit of the algorithm for(PkgIterator p = PkgBegin(); !p.end(); ++p) { @@ -1654,7 +1795,9 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) // be nice even then a required package violates the policy (#583517) // and do the full mark process also for required packages (p.CurrentVer().end() != true && - p.CurrentVer()->Priority == pkgCache::State::Required)) + p.CurrentVer()->Priority == pkgCache::State::Required) || + // packages which can't be changed (like holds) can't be garbage + (IsModeChangeOk(ModeGarbage, p, 0, false) == false)) { // the package is installed (and set to keep) if(PkgState[p->ID].Keep() && !p.CurrentVer().end()) @@ -1743,7 +1886,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, for(VerIterator V = d.TargetPkg().VersionList(); !V.end(); ++V) { - if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer())) + if(d.IsSatisfied(V)) { if(debug_autoremove) { @@ -1765,8 +1908,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, for(PrvIterator prv=d.TargetPkg().ProvidesList(); !prv.end(); ++prv) { - if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, - d.TargetVer())) + if(d.IsSatisfied(prv)) { if(debug_autoremove) { @@ -1818,3 +1960,17 @@ bool pkgDepCache::Sweep() /*{{{*/ return true; } /*}}}*/ +// DepCache::MarkAndSweep /*{{{*/ +bool pkgDepCache::MarkAndSweep(InRootSetFunc &rootFunc) +{ + return MarkRequired(rootFunc) && Sweep(); +} +bool pkgDepCache::MarkAndSweep() +{ + std::auto_ptr f(GetRootSetFunc()); + if(f.get() != NULL) + return MarkAndSweep(*f.get()); + else + return false; +} + /*}}}*/