X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/5caefc9115860e1bc1fdff8971a9e45f96a1c4e5..ab640001ee772fa27ee789f6717805f9d46d5bce:/apt-pkg/policy.cc diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 4ae3b5f87..00693ce54 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -4,22 +4,12 @@ /* ###################################################################### Package Version Policy implementation - + This is just a really simple wrapper around pkgVersionMatch with some added goodies to manage the list of things.. - - Priority Table: - - 1000 -> inf = Downgradeable priorities - 1000 = The 'no downgrade' pseduo-status file - 100 -> 1000 = Standard priorities - 990 = Config file override package files - 989 = Start for preference auto-priorities - 500 = Default package files - 100 = The status file and ButAutomaticUpgrades sources - 0 -> 100 = NotAutomatic sources like experimental - -inf -> 0 = Never selected - + + See man apt_preferences for what value means what. + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -33,7 +23,15 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -48,7 +46,7 @@ using namespace std; file matches the V0 policy engine. */ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner) { - if (Owner == 0 || &(Owner->Head()) == 0) + if (Owner == 0) return; PFPriority = new signed short[Owner->Head().PackageFileCount]; Pins = new Pin[Owner->Head().PackageCount]; @@ -99,37 +97,29 @@ bool pkgPolicy::InitDefaults() // Apply the defaults.. SPtrArray Fixed = new bool[Cache->HeaderP->PackageFileCount]; memset(Fixed,0,sizeof(*Fixed)*Cache->HeaderP->PackageFileCount); - signed Cur = 989; StatusOverride = false; - for (vector::const_iterator I = Defaults.begin(); I != Defaults.end(); - ++I, --Cur) + for (vector::const_iterator I = Defaults.begin(); I != Defaults.end(); ++I) { pkgVersionMatch Match(I->Data,I->Type); for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) { - if (Match.FileMatch(F) == true && Fixed[F->ID] == false) + if (Fixed[F->ID] == false && Match.FileMatch(F) == true) { - if (I->Priority != 0 && I->Priority > 0) - Cur = I->Priority; - - if (I->Priority < 0) - PFPriority[F->ID] = I->Priority; - else - PFPriority[F->ID] = Cur; - - if (PFPriority[F->ID] > 1000) + PFPriority[F->ID] = I->Priority; + + if (PFPriority[F->ID] >= 1000) StatusOverride = true; - + Fixed[F->ID] = true; - } - } + } + } } if (_config->FindB("Debug::pkgPolicy",false) == true) for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) - std::clog << "Prio of " << F.FileName() << ' ' << PFPriority[F->ID] << std::endl; - - return true; + std::clog << "Prio of " << F.FileName() << ' ' << PFPriority[F->ID] << std::endl; + + return true; } /*}}}*/ // Policy::GetCandidateVer - Get the candidate install version /*{{{*/ @@ -158,19 +148,21 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk effectively excludes everything <= 0 which are the non-automatic priorities.. The status file is given a prio of 100 which will exclude not-automatic sources, except in a single shot not-installed mode. - The second pseduo-status file is at prio 1000, above which will permit - the user to force-downgrade things. - + The user pin is subject to the same priority rules as default selections. Thus there are two ways to create a pin - a pin that tracks the default when the default is taken away, and a permanent pin that stays at that setting. */ + 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); + 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 @@ -187,26 +179,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) { - /* Elevate our current selection (or the status file itself) - to the Pseudo-status priority. */ - if (Pref.end() == true) + /* 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; - Max = 1000; - + PrefSeen = true; + } + /* Elevate our current selection (or the status file itself) so that only + a downgrade can override it from now on */ + Max = 999; + // 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 @@ -314,19 +313,13 @@ pkgCache::VerIterator pkgPolicy::GetMatch(pkgCache::PkgIterator const &Pkg) // Policy::GetPriority - Get the priority of the package pin /*{{{*/ // --------------------------------------------------------------------- /* */ -signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg) +APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg) { if (Pins[Pkg->ID].Type != pkgVersionMatch::None) - { - // In this case 0 means default priority - if (Pins[Pkg->ID].Priority == 0) - return 989; return Pins[Pkg->ID].Priority; - } - return 0; } -signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) +APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) { return PFPriority[File->ID]; } @@ -338,7 +331,7 @@ signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) all over the place rather than forcing a special format */ class PreferenceSection : public pkgTagSection { - void TrimRecord(bool BeforeRecord, const char* &End) + void TrimRecord(bool /*BeforeRecord*/, const char* &End) { for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++) if (Stop[0] == '#') @@ -394,6 +387,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());