file matches the V0 policy engine. */
pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner)
{
+ if (Owner == 0 || &(Owner->Head()) == 0)
+ return;
PFPriority = new signed short[Owner->Head().PackageFileCount];
Pins = new Pin[Owner->Head().PackageCount];
// 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))
+ 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();
}
/*}}}*/
{
/* Lets see if this version is the installed version */
bool instVer = (Pkg.CurrentVer() == Ver);
- if (Ver.Pseudo() == true && instVer == false)
- {
- pkgCache::PkgIterator const allPkg = Ver.ParentPkg().Group().FindPkg("all");
- if (allPkg->CurrentVer != 0 && allPkg.CurrentVer()->Hash == Ver->Hash &&
- strcmp(allPkg.CurVersion(), Ver.VerStr()) == 0)
- instVer = true;
- }
for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; VF++)
{
{
if (Name.empty() == true)
{
- Pin *P = &*Defaults.insert(Defaults.end(),PkgPin());
+ Pin *P = &*Defaults.insert(Defaults.end(),Pin());
P->Type = Type;
P->Priority = Priority;
P->Data = Data;
return;
}
- // Get a spot to put the pin
- pkgCache::GrpIterator Grp = Cache->FindGrp(Name);
- for (pkgCache::PkgIterator Pkg = Grp.FindPkg("any");
- Pkg.end() != true; Pkg = Grp.NextPkg(Pkg))
+ size_t found = Name.rfind(':');
+ string Arch;
+ if (found != string::npos) {
+ Arch = Name.substr(found+1);
+ Name.erase(found);
+ }
+
+ // Allow pinning by wildcards
+ // TODO: Maybe we should always prefer specific pins over non-
+ // specific ones.
+ if (Name[0] == '/' || Name.find_first_of("*[?") != string::npos)
{
- Pin *P = 0;
- if (Pkg.end() == false)
- P = Pins + Pkg->ID;
- else
- {
- // Check the unmatched table
- for (vector<PkgPin>::iterator I = Unmatched.begin();
- I != Unmatched.end() && P == 0; I++)
- if (I->Pkg == Name)
- P = &*I;
+ pkgVersionMatch match(Data, Type);
+ for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() != true; ++G)
+ if (match.ExpressionMatches(Name, G.Name()))
+ {
+ if (Arch.empty() == false)
+ CreatePin(Type, string(G.Name()).append(":").append(Arch), Data, Priority);
+ else
+ CreatePin(Type, G.Name(), Data, Priority);
+ }
+ return;
+ }
- if (P == 0)
- P = &*Unmatched.insert(Unmatched.end(),PkgPin());
- }
+ // 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();
+ }
+
+ if (Pkg.end() == true)
+ {
+ PkgPin *P = &*Unmatched.insert(Unmatched.end(),PkgPin(Name));
+ if (Arch.empty() == false)
+ P->Pkg.append(":").append(Arch);
+ P->Type = Type;
+ P->Priority = Priority;
+ 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;
}
}
/*}}}*/
if (File.empty() == true)
File = _config->FindFile("Dir::Etc::Preferences");
- if (FileExists(File) == false)
+ if (RealFileExists(File) == false)
return true;
FileFd Fd(File,FileFd::ReadOnly);