X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/c5ca2c52a98fcb50de6429cf370ed5b6b7602a00..545ba6bdd8cb77ceca6b9fdc935db2accbea3493:/apt-pkg/depcache.cc diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index e9527647e..2656e9b42 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -8,28 +8,35 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ +#include + #include #include #include #include #include #include - #include #include #include #include #include #include +#include +#include +#include #include -#include +#include #include #include -#include +#include /*}}}*/ + +using std::string; + // helper for Install-Recommends-Sections and Never-MarkAuto-Sections /*{{{*/ static bool ConfigValueInSubTree(const char* SubTree, const char *needle) @@ -169,14 +176,14 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ string const state = _config->FindFile("Dir::State::extended_states"); if(RealFileExists(state)) { state_file.Open(state, FileFd::ReadOnly); - int const file_size = state_file.Size(); + off_t const file_size = state_file.Size(); if(Prog != NULL) Prog->OverallProgress(0, file_size, 1, _("Reading state information")); pkgTagFile tagfile(&state_file); pkgTagSection section; - int amt = 0; + off_t amt = 0; bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); while(tagfile.Step(section)) { string const pkgname = section.FindS("Package"); @@ -364,14 +371,11 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) // Check the providing packages PrvIterator P = Dep.TargetPkg().ProvidesList(); - PkgIterator Pkg = Dep.ParentPkg(); for (; P.end() != true; ++P) { - /* Provides may never be applied against the same package (or group) - if it is a conflicts. See the comment above. */ - if (P.OwnerPkg()->Group == Pkg->Group && Dep.IsNegative() == true) + if (Dep.IsIgnorable(P) == true) continue; - + // Check if the provides is a hit if (Type == NowVersion) { @@ -935,6 +939,58 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, // DepCache::MarkInstall - Put the package in the install state /*{{{*/ // --------------------------------------------------------------------- /* */ +struct CompareProviders { + pkgCache::PkgIterator const Pkg; + 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 packages in the same group as the target; e.g. foo:i386, foo:amd64 + if (A->Group != B->Group) + { + if (A->Group == Pkg->Group && B->Group != Pkg->Group) + return false; + else if (B->Group == Pkg->Group && A->Group != Pkg->Group) + return true; + } + // we like essentials + if ((A->Flags & pkgCache::Flag::Essential) != (B->Flags & pkgCache::Flag::Essential)) + { + if ((A->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + return false; + else if ((B->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + return true; + } + if ((A->Flags & pkgCache::Flag::Important) != (B->Flags & pkgCache::Flag::Important)) + { + if ((A->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) + return false; + 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) + { + if (strcmp(A.Arch(), A.Cache()->NativeArch()) == 0) + return false; + else if (strcmp(B.Arch(), B.Cache()->NativeArch()) == 0) + return true; + std::vector archs = APT::Configuration::getArchitectures(); + for (std::vector::const_iterator a = archs.begin(); a != archs.end(); ++a) + if (*a == A.Arch()) + return false; + else if (*a == B.Arch()) + return true; + } + // unable to decide… + return A->ID < B->ID; + } +}; bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, unsigned long Depth, bool FromUser, bool ForceImportantDeps) @@ -1096,42 +1152,28 @@ bool 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 (Start->Type != Dep::DpkgBreaks && - (DepState[Start->ID] & DepCVer) == DepCVer) + fixing the problem for "positive" dependencies */ + if (Start.IsNegative() == false && (DepState[Start->ID] & DepCVer) == DepCVer) { - // Right, find the best version to install.. - Version **Cur = List; - PkgIterator P = Start.TargetPkg(); - PkgIterator InstPkg(*Cache,0); - - // See if there are direct matches (at the start of the list) - for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++) + 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) + verlist.insert(Cand); + for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv) { - PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg); - if (PkgState[Pkg->ID].CandidateVer != *Cur) + 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) continue; - InstPkg = Pkg; - break; + verlist.insert(Cand); } + CompareProviders comp(Start); + APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp); - // Select the highest priority providing package - if (InstPkg.end() == true) - { - pkgPrioSortList(*Cache,Cur); - for (; *Cur != 0; Cur++) - { - PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg); - if (PkgState[Pkg->ID].CandidateVer != *Cur) - continue; - InstPkg = Pkg; - break; - } - } - - if (InstPkg.end() == false) + if (InstVer != verlist.end()) { + pkgCache::PkgIterator InstPkg = InstVer.ParentPkg(); if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name() << " as " << Start.DepType() << " of " << Pkg.Name() @@ -1149,18 +1191,19 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, // mark automatic dependency MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps); // Set the autoflag, after MarkInstall because MarkInstall unsets it - if (P->CurrentVer == 0) + if (InstPkg->CurrentVer == 0) PkgState[InstPkg->ID].Flags |= Flag::Auto; } } continue; } - - /* For conflicts we just de-install the package and mark as auto, - Conflicts may not have or groups. For dpkg's Breaks we try to - upgrade the package. */ - if (Start.IsNegative() == true) + /* Negative dependencies have no or-group + If the dependency isn't versioned, we try if an upgrade might solve the problem. + Otherwise we remove the offender if needed */ + else if (Start.IsNegative() == true && Start->Type != pkgCache::Dep::Obsoletes) { + SPtrArray List = Start.AllTargets(); + pkgCache::PkgIterator TrgPkg = Start.TargetPkg(); for (Version **I = List; *I != 0; I++) { VerIterator Ver(*this,*I); @@ -1171,15 +1214,17 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, if (PkgState[Pkg->ID].InstallVer == 0) continue; - if (PkgState[Pkg->ID].CandidateVer != *I && - Start->Type == Dep::DpkgBreaks && + 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 (MarkDelete(Pkg,false,Depth + 1, false) == false) + else if ((Start->Type == pkgCache::Dep::Conflicts || Start->Type == pkgCache::Dep::DpkgBreaks) && + MarkDelete(Pkg,false,Depth + 1, false) == false) break; } continue; - } + } } return Dep.end() == true; @@ -1203,19 +1248,36 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To) if (unlikely(Pkg.end() == true)) return; + APT::PackageList pkglist; + if (Pkg->CurrentVer != 0 && + (Pkg.CurrentVer()-> MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) + { + pkgCache::GrpIterator Grp = Pkg.Group(); + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + { + if (P->CurrentVer != 0) + pkglist.insert(P); + } + } + else + pkglist.insert(Pkg); + ActionGroup group(*this); - RemoveSizes(Pkg); - RemoveStates(Pkg); - - StateCache &P = PkgState[Pkg->ID]; - if (To == true) - P.iFlags |= ReInstall; - else - P.iFlags &= ~ReInstall; - - AddStates(Pkg); - AddSizes(Pkg); + for (APT::PackageList::const_iterator Pkg = pkglist.begin(); Pkg != pkglist.end(); ++Pkg) + { + RemoveSizes(Pkg); + RemoveStates(Pkg); + + StateCache &P = PkgState[Pkg->ID]; + if (To == true) + P.iFlags |= ReInstall; + else + P.iFlags &= ~ReInstall; + + AddStates(Pkg); + AddSizes(Pkg); + } } /*}}}*/ // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/ @@ -1587,6 +1649,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) { 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