X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/7c2cc4a7bc999c8e07fba607354bfaa3b09118f9..5a3339db48479114a0e1e11ebc8d640eb3e49933:/apt-pkg/depcache.cc diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 99e694a06..eb8f6460d 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -23,6 +22,7 @@ #include #include #include +#include #include #include @@ -154,7 +154,7 @@ bool pkgDepCache::Init(OpProgress * const Prog) State.iFlags = 0; // Figure out the install version - State.CandidateVer = GetCandidateVer(I); + State.CandidateVer = LocalPolicy->GetCandidateVer(I); State.InstallVer = I.CurrentVer(); State.Mode = ModeKeep; @@ -327,6 +327,11 @@ bool pkgDepCache::writeStateFile(OpProgress * const /*prog*/, bool const Install return false; } } + if (StateFile.Failed()) + { + OutFile.OpFail(); + return false; + } if (OutFile.Close() == false) return false; chmod(state.c_str(), 0644); @@ -792,7 +797,7 @@ bool pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser, #endif if (DebugMarker == true) - std::clog << OutputInDepth(Depth) << "MarkKeep " << Pkg << " FU=" << FromUser << std::endl; + std::clog << OutputInDepth(Depth) << "MarkKeep " << APT::PrettyPkg(this, Pkg) << " FU=" << FromUser << std::endl; RemoveSizes(Pkg); RemoveStates(Pkg); @@ -872,7 +877,7 @@ bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, } if (DebugMarker == true) - std::clog << OutputInDepth(Depth) << (rPurge ? "MarkPurge " : "MarkDelete ") << Pkg << " FU=" << FromUser << std::endl; + std::clog << OutputInDepth(Depth) << (rPurge ? "MarkPurge " : "MarkDelete ") << APT::PrettyPkg(this, Pkg) << " FU=" << FromUser << std::endl; RemoveSizes(Pkg); RemoveStates(Pkg); @@ -908,7 +913,7 @@ bool pkgDepCache::IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg, if (P.InstallVer != 0 && P.Status == 2 && (P.Flags & Flag::Auto) != Flag::Auto) { if (DebugMarker == true) - std::clog << OutputInDepth(Depth) << "Manual install request prevents MarkDelete of " << Pkg << std::endl; + std::clog << OutputInDepth(Depth) << "Manual install request prevents MarkDelete of " << APT::PrettyPkg(this, Pkg) << std::endl; return false; } } @@ -958,7 +963,7 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, { if (unlikely(DebugMarker == true)) std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode) - << " of " << Pkg << " as its mode (" << PrintMode(P.Mode) + << " of " << APT::PrettyPkg(this, Pkg) << " as its mode (" << PrintMode(P.Mode) << ") is protected" << std::endl; return false; } @@ -968,7 +973,7 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, { if (unlikely(DebugMarker == true)) std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode) - << " of " << Pkg << std::endl; + << " of " << APT::PrettyPkg(this, Pkg) << std::endl; return false; } @@ -1017,6 +1022,8 @@ struct CompareProviders { if (instA != instB) return instA == false; } + if ((A->CurrentVer == 0 || B->CurrentVer == 0) && A->CurrentVer != B->CurrentVer) + return A->CurrentVer == 0; // Prefer packages in the same group as the target; e.g. foo:i386, foo:amd64 if (A->Group != B->Group) { @@ -1126,11 +1133,28 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, return true; if (DebugMarker == true) - std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << " FU=" << FromUser << std::endl; + std::clog << OutputInDepth(Depth) << "MarkInstall " << APT::PrettyPkg(this, Pkg) << " FU=" << FromUser << std::endl; + bool MoveAutoBitToDependencies = false; VerIterator const PV = P.InstVerIter(*this); if (unlikely(PV.end() == true)) return false; + else if (PV->Section != 0 && (P.Flags & Flag::Auto) != Flag::Auto) + { + VerIterator const CurVer = Pkg.CurrentVer(); + if (CurVer.end() == false && CurVer->Section != 0 && strcmp(CurVer.Section(), PV.Section()) != 0) + { + bool const CurVerInMoveSection = ConfigValueInSubTree("APT::Move-Autobit-Sections", CurVer.Section()); + bool const InstVerInMoveSection = ConfigValueInSubTree("APT::Move-Autobit-Sections", PV.Section()); + MoveAutoBitToDependencies = (CurVerInMoveSection == false && InstVerInMoveSection == true); + if (MoveAutoBitToDependencies == true) + { + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << "Setting " << Pkg.FullName(false) << " as auto-installed, moving manual to its dependencies" << std::endl; + MarkAuto(Pkg, true); + } + } + } DepIterator Dep = PV.DependsList(); for (; Dep.end() != true;) @@ -1165,7 +1189,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /* 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 */ + over the problem here as the front-end will know what it is doing */ if (Ors == 1 && (DepState[Start->ID] &DepCVer) != DepCVer && Start.IsNegative() == false) continue; @@ -1244,6 +1268,17 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, verlist.erase(InstVer); continue; } + + // now check if we should consider it a automatic dependency or not + if(InstPkg->CurrentVer == 0 && MoveAutoBitToDependencies) + { + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << "Setting " << InstPkg.FullName(false) << " NOT as auto-installed (direct " + << Start.DepType() << " of " << Pkg.FullName(false) << " which is manual and in APT::Move-Autobit-Sections)" << std::endl; + MarkAuto(InstPkg, false); + } + + break; } while(true); continue; @@ -1253,9 +1288,9 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, Otherwise we remove the offender if needed */ else if (Start.IsNegative() == true && Start->Type != pkgCache::Dep::Obsoletes) { - SPtrArray List = Start.AllTargets(); + std::unique_ptr List(Start.AllTargets()); pkgCache::PkgIterator TrgPkg = Start.TargetPkg(); - for (Version **I = List; *I != 0; I++) + for (Version **I = List.get(); *I != 0; I++) { VerIterator Ver(*this,*I); PkgIterator Pkg = Ver.ParentPkg(); @@ -1331,7 +1366,7 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, // 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) + if (CV.end() == true || strcmp(CandVer.VerStr(), CV.VerStr()) == 0) continue; // packages losing M-A:same can be out-of-sync @@ -1344,9 +1379,9 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, 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; + std::clog << OutputInDepth(Depth) << "Ignore MarkInstall of " << APT::PrettyPkg(this, Pkg) + << " as it is not in sync with its M-A:same sibling " << APT::PrettyPkg(this, P) + << " (" << CandVer.VerStr() << " != " << CV.VerStr() << ")" << std::endl; return false; } @@ -1387,12 +1422,20 @@ bool pkgDepCache::IsInstallOkDependenciesSatisfiableByCandidates(PkgIterator con if (Ors == 1 && (DepState[Start->ID] &DepCVer) != DepCVer) { if (DebugAutoInstall == true) - std::clog << OutputInDepth(Depth) << Start << " can't be satisfied!" << std::endl; + std::clog << OutputInDepth(Depth) << APT::PrettyDep(this, 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()); + StateCache &State = PkgState[Pkg->ID]; + if (State.Mode != ModeDelete) + { + State.Mode = ModeKeep; + State.Update(Pkg, *this); + } + } return false; } } @@ -1440,6 +1483,11 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To) } } /*}}}*/ +pkgCache::VerIterator pkgDepCache::GetCandidateVersion(PkgIterator const &Pkg)/*{{{*/ +{ + return PkgState[Pkg->ID].CandidateVerIter(*this); +} + /*}}}*/ // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1661,11 +1709,7 @@ void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache) CurVersion = ""; if (Pkg->CurrentVer != 0) CurVersion = Pkg.CurrentVer().VerStr(); - - // Strip off the epochs for display - CurVersion = StripEpoch(CurVersion); - CandVersion = StripEpoch(CandVersion); - + // Figure out if its up or down or equal Status = Ver.CompareVer(Pkg.CurrentVer()); if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0) @@ -1752,6 +1796,8 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) const // Policy::GetPriority - Get the priority of the package pin /*{{{*/ APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgIterator const &/*Pkg*/) { return 0; } +APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::VerIterator const &/*Ver*/, bool /*ConsiderFiles*/) +{ return 0; } APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgFileIterator const &/*File*/) { return 0; } /*}}}*/ @@ -1778,6 +1824,20 @@ bool pkgDepCache::MarkFollowsSuggests() } // pkgDepCache::MarkRequired - the main mark algorithm /*{{{*/ +static bool IsPkgInBoringState(pkgCache::PkgIterator const &Pkg, pkgDepCache::StateCache const * const PkgState) +{ + if (Pkg->CurrentVer == 0) + { + if (PkgState[Pkg->ID].Keep()) + return true; + } + else + { + if (PkgState[Pkg->ID].Delete()) + return true; + } + return false; +} bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) { if (_config->Find("APT::Solver", "internal") != "internal") @@ -1786,8 +1846,8 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); // init the states - map_id_t const PackagesCount = Head().PackageCount; - for(map_id_t i = 0; i < PackagesCount; ++i) + auto const PackagesCount = Head().PackageCount; + for(auto i = decltype(PackagesCount){0}; i < PackagesCount; ++i) { PkgState[i].Marked = false; PkgState[i].Garbage = false; @@ -1801,152 +1861,103 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) bool const follow_suggests = MarkFollowsSuggests(); // do the mark part, this is the core bit of the algorithm - for(PkgIterator p = PkgBegin(); !p.end(); ++p) + for (PkgIterator P = PkgBegin(); !P.end(); ++P) { - if(!(PkgState[p->ID].Flags & Flag::Auto) || - (p->Flags & Flag::Essential) || - (p->Flags & Flag::Important) || - userFunc.InRootSet(p) || - // 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) || - // 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()) - MarkPackage(p, p.CurrentVer(), - follow_recommends, follow_suggests); - // the package is to be installed - else if(PkgState[p->ID].Install()) - MarkPackage(p, PkgState[p->ID].InstVerIter(*this), - follow_recommends, follow_suggests); - } + if (PkgState[P->ID].Marked || IsPkgInBoringState(P, PkgState)) + continue; + + if ((PkgState[P->ID].Flags & Flag::Auto) == 0) + ; + else if ((P->Flags & Flag::Essential) || (P->Flags & Flag::Important)) + ; + // be nice even then a required package violates the policy (#583517) + // and do the full mark process also for required packages + else if (P->CurrentVer != 0 && P.CurrentVer()->Priority == pkgCache::State::Required) + ; + else if (userFunc.InRootSet(P)) + ; + // packages which can't be changed (like holds) can't be garbage + else if (IsModeChangeOk(ModeGarbage, P, 0, false) == false) + ; + else + continue; + + if (PkgState[P->ID].Install()) + MarkPackage(P, PkgState[P->ID].InstVerIter(*this), + follow_recommends, follow_suggests); + else + MarkPackage(P, P.CurrentVer(), + follow_recommends, follow_suggests); } return true; } /*}}}*/ // MarkPackage - mark a single package in Mark-and-Sweep /*{{{*/ -void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, - const pkgCache::VerIterator &ver, +void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &Pkg, + const pkgCache::VerIterator &Ver, bool const &follow_recommends, bool const &follow_suggests) { - pkgDepCache::StateCache &state = PkgState[pkg->ID]; + { + pkgDepCache::StateCache &state = PkgState[Pkg->ID]; + // if we are marked already we are done + if(state.Marked || unlikely(Ver.end())) + return; + state.Marked=true; + } - // if we are marked already we are done - if(state.Marked) + if (IsPkgInBoringState(Pkg, PkgState)) return; - VerIterator const currver = pkg.CurrentVer(); - VerIterator const instver = state.InstVerIter(*this); - -#if 0 - VerIterator const candver = state.CandidateVerIter(*this); + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false); + if(debug_autoremove) + std::clog << "Marking: " << Pkg.FullName() << " " << Ver.VerStr() << std::endl; - // If a package was garbage-collected but is now being marked, we - // should re-select it - // For cases when a pkg is set to upgrade and this trigger the - // removal of a no-longer used dependency. if the pkg is set to - // keep again later it will result in broken deps - if(state.Delete() && state.RemoveReason = Unused) + for (auto D = Ver.DependsList(); D.end() == false; ++D) { - if(ver==candver) - mark_install(pkg, false, false, NULL); - else if(ver==pkg.CurrentVer()) - MarkKeep(pkg, false, false); - - instver=state.InstVerIter(*this); - } -#endif + auto const T = D.TargetPkg(); + if (PkgState[T->ID].Marked) + continue; - // For packages that are not going to be removed, ignore versions - // other than the InstVer. For packages that are going to be - // removed, ignore versions other than the current version. - if(!(ver == instver && !instver.end()) && - !(ver == currver && instver.end() && !ver.end())) - return; + if (D->Type != Dep::Depends && + D->Type != Dep::PreDepends && + (follow_recommends == false || D->Type != Dep::Recommends) && + (follow_suggests == false || D->Type != Dep::Suggests)) + continue; - bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false); + // handle the virtual part first + for(auto Prv = T.ProvidesList(); Prv.end() == false; ++Prv) + { + auto PP = Prv.OwnerPkg(); + if (PkgState[PP->ID].Marked || IsPkgInBoringState(PP, PkgState)) + continue; - if(debug_autoremove) - { - std::clog << "Marking: " << pkg.FullName(); - if(!ver.end()) - std::clog << " " << ver.VerStr(); - if(!currver.end()) - std::clog << ", Curr=" << currver.VerStr(); - if(!instver.end()) - std::clog << ", Inst=" << instver.VerStr(); - std::clog << std::endl; - } + // we want to ignore provides from uninteresting versions + auto const PV = (PkgState[PP->ID].Install()) ? + PkgState[PP->ID].InstVerIter(*this) : PP.CurrentVer(); + if (unlikely(PV.end()) || PV != Prv.OwnerVer() || D.IsSatisfied(Prv) == false) + continue; - state.Marked=true; + if (debug_autoremove) + std::clog << "Following dep: " << APT::PrettyDep(this, D) + << ", provided by " << PP.FullName() << " " << PV.VerStr() << std::endl; + MarkPackage(PP, PV, follow_recommends, follow_suggests); + } - if(ver.end() == true) - return; + // now deal with the real part of the package + if (IsPkgInBoringState(T, PkgState)) + continue; - for(DepIterator d = ver.DependsList(); !d.end(); ++d) - { - if(d->Type == Dep::Depends || - d->Type == Dep::PreDepends || - (follow_recommends && - d->Type == Dep::Recommends) || - (follow_suggests && - d->Type == Dep::Suggests)) - { - // Try all versions of this package. - for(VerIterator V = d.TargetPkg().VersionList(); - !V.end(); ++V) - { - if(d.IsSatisfied(V)) - { - if(debug_autoremove) - { - std::clog << "Following dep: " << d.ParentPkg().FullName() - << " " << d.ParentVer().VerStr() << " " - << d.DepType() << " " << d.TargetPkg().FullName(); - if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp) - { - std::clog << " (" << d.CompType() << " " - << d.TargetVer() << ")"; - } - std::clog << std::endl; - } - MarkPackage(V.ParentPkg(), V, - follow_recommends, follow_suggests); - } - } - // Now try virtual packages - for(PrvIterator prv=d.TargetPkg().ProvidesList(); - !prv.end(); ++prv) - { - if(d.IsSatisfied(prv)) - { - if(debug_autoremove) - { - std::clog << "Following dep: " << d.ParentPkg().FullName() << " " - << d.ParentVer().VerStr() << " " - << d.DepType() << " " << d.TargetPkg().FullName() << " "; - if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp) - { - std::clog << " (" << d.CompType() << " " - << d.TargetVer() << ")"; - } - std::clog << ", provided by " - << prv.OwnerPkg().FullName() << " " - << prv.OwnerVer().VerStr() - << std::endl; - } - - MarkPackage(prv.OwnerPkg(), prv.OwnerVer(), - follow_recommends, follow_suggests); - } - } - } - } + auto const TV = (PkgState[T->ID].Install()) ? + PkgState[T->ID].InstVerIter(*this) : T.CurrentVer(); + if (unlikely(TV.end()) || D.IsSatisfied(TV) == false) + continue; + + if (debug_autoremove) + std::clog << "Following dep: " << APT::PrettyDep(this, D) << std::endl; + MarkPackage(T, TV, follow_recommends, follow_suggests); + } } /*}}}*/ bool pkgDepCache::Sweep() /*{{{*/ @@ -1982,7 +1993,7 @@ bool pkgDepCache::MarkAndSweep(InRootSetFunc &rootFunc) } bool pkgDepCache::MarkAndSweep() { - std::auto_ptr f(GetRootSetFunc()); + std::unique_ptr f(GetRootSetFunc()); if(f.get() != NULL) return MarkAndSweep(*f.get()); else