X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/eef7133842d6fe5847daa0ab4846b5e8be892d61..75ab11ae3880530c5354cc90c8d1ff0998f8146b:/apt-pkg/policy.cc diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index bd213e0ce..d0f97441d 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -23,18 +23,21 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ +#include + #include #include +#include #include #include #include #include #include -#include - #include #include + +#include /*}}}*/ using namespace std; @@ -56,8 +59,23 @@ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner) // The config file has a master override. string DefRel = _config->Find("APT::Default-Release"); if (DefRel.empty() == false) - CreatePin(pkgVersionMatch::Release,"",DefRel,990); - + { + bool found = false; + // FIXME: make ExpressionMatches static to use it here easily + pkgVersionMatch vm("", pkgVersionMatch::None); + for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) + { + if ((F->Archive != 0 && vm.ExpressionMatches(DefRel, F.Archive()) == true) || + (F->Codename != 0 && vm.ExpressionMatches(DefRel, F.Codename()) == true) || + (F->Version != 0 && vm.ExpressionMatches(DefRel, F.Version()) == true) || + (DefRel.length() > 2 && DefRel[1] == '=')) + found = true; + } + if (found == false) + _error->Error(_("The value '%s' is invalid for APT::Default-Release as such a release is not available in the sources"), DefRel.c_str()); + else + CreatePin(pkgVersionMatch::Release,"",DefRel,990); + } InitDefaults(); } /*}}}*/ @@ -67,7 +85,7 @@ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner) bool pkgPolicy::InitDefaults() { // Initialize the priorities based on the status of the package file - for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I != Cache->FileEnd(); I++) + for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I != Cache->FileEnd(); ++I) { PFPriority[I->ID] = 500; if ((I->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource) @@ -84,10 +102,10 @@ bool pkgPolicy::InitDefaults() signed Cur = 989; StatusOverride = false; for (vector::const_iterator I = Defaults.begin(); I != Defaults.end(); - I++, Cur--) + ++I, --Cur) { pkgVersionMatch Match(I->Data,I->Type); - for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); F++) + for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) { if (Match.FileMatch(F) == true && Fixed[F->ID] == false) { @@ -108,7 +126,7 @@ bool pkgPolicy::InitDefaults() } if (_config->FindB("Debug::pkgPolicy",false) == true) - for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); F++) + for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) std::clog << "Prio of " << F.FileName() << ' ' << PFPriority[F->ID] << std::endl; return true; @@ -148,12 +166,16 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk tracks the default when the default is taken away, and a permanent pin that stays at that setting. */ - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; Ver++) + bool PrefSeen = false; + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) { /* Lets see if this version is the installed version */ bool instVer = (Pkg.CurrentVer() == Ver); - for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; VF++) + if (Pref == Ver) + PrefSeen = true; + + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) { /* If this is the status file, and the current version is not the version in the status file (ie it is not installed, or somesuch) @@ -169,26 +191,33 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk { Pref = Ver; Max = Prio; + PrefSeen = true; } if (Prio > MaxAlt) { PrefAlt = Ver; MaxAlt = Prio; - } - } - + } + } + if (instVer == true && Max < 1000) { + /* Not having seen the Pref yet means we have a specific pin below 1000 + on a version below the current installed one, so ignore the specific pin + as this would be a downgrade otherwise */ + if (PrefSeen == false || Pref.end() == true) + { + Pref = Ver; + PrefSeen = true; + } /* Elevate our current selection (or the status file itself) to the Pseudo-status priority. */ - if (Pref.end() == true) - Pref = Ver; Max = 1000; - + // Fast path optimize. if (StatusOverride == false) break; - } + } } // If we do not find our candidate, use the one with the highest pin. // This means that if there is a version available with pin > 0; there @@ -242,17 +271,33 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, } // find the package (group) this pin applies to - pkgCache::GrpIterator Grp; - pkgCache::PkgIterator Pkg; - if (Arch.empty() == false) - Pkg = Cache->FindPkg(Name, Arch); - else { - Grp = Cache->FindGrp(Name); - if (Grp.end() == false) - Pkg = Grp.PackageList(); + pkgCache::GrpIterator Grp = Cache->FindGrp(Name); + bool matched = false; + if (Grp.end() == false) + { + std::string MatchingArch; + if (Arch.empty() == true) + MatchingArch = Cache->NativeArch(); + else + MatchingArch = Arch; + APT::CacheFilter::PackageArchitectureMatchesSpecification pams(MatchingArch); + for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) + { + if (pams(Pkg.Arch()) == false) + continue; + Pin *P = Pins + Pkg->ID; + // the first specific stanza for a package is the ruler, + // all others need to be ignored + if (P->Type != pkgVersionMatch::None) + P = &*Unmatched.insert(Unmatched.end(),PkgPin(Pkg.FullName())); + P->Type = Type; + P->Priority = Priority; + P->Data = Data; + matched = true; + } } - if (Pkg.end() == true) + if (matched == false) { PkgPin *P = &*Unmatched.insert(Unmatched.end(),PkgPin(Name)); if (Arch.empty() == false) @@ -262,20 +307,6 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, P->Data = Data; return; } - - for (; Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) - { - Pin *P = Pins + Pkg->ID; - // the first specific stanza for a package is the ruler, - // all others need to be ignored - if (P->Type != pkgVersionMatch::None) - P = &*Unmatched.insert(Unmatched.end(),PkgPin(Pkg.FullName())); - P->Type = Type; - P->Priority = Priority; - P->Data = Data; - if (Grp.end() == true) - break; - } } /*}}}*/ // Policy::GetMatch - Get the matching version for a package pin /*{{{*/ @@ -305,6 +336,10 @@ signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg) } return 0; +} +signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) +{ + return PFPriority[File->ID]; } /*}}}*/ // PreferenceSection class - Overriding the default TrimRecord method /*{{{*/ @@ -342,7 +377,7 @@ bool ReadPinDir(pkgPolicy &Plcy,string Dir) vector const List = GetListOfFilesInDir(Dir, "pref", true, true); // Read the files - for (vector::const_iterator I = List.begin(); I != List.end(); I++) + for (vector::const_iterator I = List.begin(); I != List.end(); ++I) if (ReadPinFile(Plcy, *I) == false) return false; return true; @@ -370,6 +405,10 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) PreferenceSection Tags; while (TF.Step(Tags) == true) { + // can happen when there are only comments in a record + if (Tags.Count() == 0) + continue; + string Name = Tags.FindS("Package"); if (Name.empty() == true) return _error->Error(_("Invalid record in the preferences file %s, no Package header"), File.c_str());