From ecc138f858fab61e0b888d3d13854d1422c3432b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 16 Jul 2015 19:41:45 +0200 Subject: just-in-time creation for (implicit) Provides Expecting the worst is easy to code, but has its disadvantages e.g. by creating package structures which otherwise would have never existed. By creating the provides instead at the time a package structure is added we are well prepared for the introduction of partial architectures, massive amounts of M-A:foreign (and :allowed) and co as far as provides are concerned at least. We have something relatively similar for dependencies already. Many tests are added for both M-A states and the code cleaned to properly support implicit provides for foreign architectures and architectures we 'just' happen to parse. Git-Dch: Ignore --- apt-pkg/pkgcachegen.cc | 123 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 31 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 9acb2563a..c04320555 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -648,6 +648,16 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name return false; Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package); + // Set the name, arch and the ID + APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;) + Pkg->Group = Grp.Index(); + // all is mapped to the native architecture + map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch); + if (unlikely(idxArch == 0)) + return false; + Pkg->Arch = idxArch; + Pkg->ID = Cache.HeaderP->PackageCount++; + // Insert the package into our package list if (Grp->FirstPackage == 0) // the group is new { @@ -662,23 +672,36 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name } else // Group the Packages together { + // but first get implicit provides done + if (APT::Configuration::checkArchitecture(Pkg.Arch()) == true) + { + pkgCache::PkgIterator const M = Grp.FindPreferredPkg(false); // native or any foreign pkg will do + if (M.end() == false) + for (pkgCache::PrvIterator Prv = M.ProvidesList(); Prv.end() == false; ++Prv) + { + if ((Prv->Flags & pkgCache::Flag::ArchSpecific) != 0) + continue; + pkgCache::VerIterator Ver = Prv.OwnerVer(); + if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed || + ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign && + (Prv->Flags & pkgCache::Flag::MultiArchImplicit) == 0)) + if (NewProvides(Ver, Pkg, Prv->ProvideVersion, Prv->Flags) == false) + return false; + } + + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + for (pkgCache::VerIterator Ver = P.VersionList(); Ver.end() == false; ++Ver) + if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) + if (NewProvides(Ver, Pkg, Ver->VerStr, pkgCache::Flag::MultiArchImplicit) == false) + return false; + } + // this package is the new last package pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage); Pkg->NextPackage = LastPkg->NextPackage; LastPkg->NextPackage = Package; } Grp->LastPackage = Package; - - // Set the name, arch and the ID - APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;) - Pkg->Group = Grp.Index(); - // all is mapped to the native architecture - map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch); - if (unlikely(idxArch == 0)) - return false; - Pkg->Arch = idxArch; - Pkg->ID = Cache.HeaderP->PackageCount++; - return true; } /*}}}*/ @@ -1079,44 +1102,82 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, const string &Version, uint8_t const Flags) { - pkgCache &Cache = Owner->Cache; + pkgCache const &Cache = Owner->Cache; // We do not add self referencing provides if (Ver.ParentPkg().Name() == PkgName && (PkgArch == Ver.ParentPkg().Arch() || (PkgArch == "all" && strcmp((Cache.StrP + Cache.HeaderP->Architecture), Ver.ParentPkg().Arch()) == 0))) return true; - + + // Locate the target package + pkgCache::PkgIterator Pkg; + Dynamic DynPkg(Pkg); + if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) + return false; + + map_stringitem_t idxProvideVersion = 0; + if (Version.empty() == false) { + idxProvideVersion = StoreString(VERSIONNUMBER, Version); + if (unlikely(idxProvideVersion == 0)) + return false; + } + return Owner->NewProvides(Ver, Pkg, idxProvideVersion, Flags); +} +bool pkgCacheGenerator::NewProvides(pkgCache::VerIterator &Ver, + pkgCache::PkgIterator &Pkg, + map_pointer_t const ProvideVersion, + uint8_t const Flags) +{ // Get a structure - map_pointer_t const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); + map_pointer_t const Provides = AllocateInMap(sizeof(pkgCache::Provides)); if (unlikely(Provides == 0)) return false; - Cache.HeaderP->ProvidesCount++; - + ++Cache.HeaderP->ProvidesCount; + // Fill it in pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP); - Dynamic DynPrv(Prv); Prv->Version = Ver.Index(); + Prv->ProvideVersion = ProvideVersion; Prv->Flags = Flags; Prv->NextPkgProv = Ver->ProvidesList; Ver->ProvidesList = Prv.Index(); - if (Version.empty() == false) { - map_stringitem_t const idxProvideVersion = WriteString(Version); - Prv->ProvideVersion = idxProvideVersion; - if (unlikely(idxProvideVersion == 0)) - return false; - } - - // Locate the target package - pkgCache::PkgIterator Pkg; - Dynamic DynPkg(Pkg); - if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) - return false; - + // Link it to the package Prv->ParentPkg = Pkg.Index(); Prv->NextProvides = Pkg->ProvidesList; Pkg->ProvidesList = Prv.Index(); - + return true; +} + /*}}}*/ +// ListParser::NewProvidesAllArch - add provides for all architectures /*{{{*/ +bool pkgCacheGenerator::ListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package, + string const &Version, uint8_t const Flags) { + pkgCache &Cache = Owner->Cache; + pkgCache::GrpIterator const Grp = Cache.FindGrp(Package); + if (Grp.end() == true) + return NewProvides(Ver, Package, Cache.NativeArch(), Version, Flags); + else + { + map_stringitem_t idxProvideVersion = 0; + if (Version.empty() == false) { + idxProvideVersion = StoreString(VERSIONNUMBER, Version); + if (unlikely(idxProvideVersion == 0)) + return false; + } + + bool const isImplicit = (Flags & pkgCache::Flag::MultiArchImplicit) == pkgCache::Flag::MultiArchImplicit; + bool const isArchSpecific = (Flags & pkgCache::Flag::ArchSpecific) == pkgCache::Flag::ArchSpecific; + pkgCache::PkgIterator const OwnerPkg = Ver.ParentPkg(); + for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + { + if (isImplicit && OwnerPkg == Pkg) + continue; + if (isArchSpecific == false && APT::Configuration::checkArchitecture(OwnerPkg.Arch()) == false) + continue; + if (Owner->NewProvides(Ver, Pkg, idxProvideVersion, Flags) == false) + return false; + } + } return true; } /*}}}*/ -- cgit v1.2.3