X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/5f909b67fb903f700df1bd6242ada86d58c0b068..a86f851619f720b8c4a74d01274c5e2bf012d451:/apt-pkg/pkgcache.cc diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 5361696d0..d7725563b 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -52,7 +52,7 @@ pkgCache::Header::Header() /* Whenever the structures change the major version should be bumped, whenever the generator changes the minor version should be bumped. */ MajorVersion = 8; - MinorVersion = 0; + MinorVersion = 1; Dirty = false; HeaderSz = sizeof(pkgCache::Header); @@ -182,18 +182,17 @@ unsigned long pkgCache::sHash(const string &Str) const { unsigned long Hash = 0; for (string::const_iterator I = Str.begin(); I != Str.end(); ++I) - Hash = 5*Hash + tolower_ascii(*I); + Hash = 41 * Hash + tolower_ascii(*I); return Hash % _count(HeaderP->PkgHashTable); } unsigned long pkgCache::sHash(const char *Str) const { - unsigned long Hash = 0; - for (const char *I = Str; *I != 0; ++I) - Hash = 5*Hash + tolower_ascii(*I); + unsigned long Hash = tolower_ascii(*Str); + for (const char *I = Str + 1; *I != 0; ++I) + Hash = 41 * Hash + tolower_ascii(*I); return Hash % _count(HeaderP->PkgHashTable); } - /*}}}*/ // Cache::SingleArchFindPkg - Locate a package by name /*{{{*/ // --------------------------------------------------------------------- @@ -206,9 +205,14 @@ pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name) Package *Pkg = PkgP + HeaderP->PkgHashTable[Hash(Name)]; for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage) { - if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] && - stringcasecmp(Name,StrP + Pkg->Name) == 0) - return PkgIterator(*this,Pkg); + if (unlikely(Pkg->Name == 0)) + continue; + + int const cmp = strcasecmp(Name.c_str(), StrP + Pkg->Name); + if (cmp == 0) + return PkgIterator(*this, Pkg); + else if (cmp < 0) + break; } return PkgIterator(*this,0); } @@ -238,7 +242,7 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) { - if (MultiArchCache() == false) { + if (MultiArchCache() == false && Arch != "none") { if (Arch == "native" || Arch == "all" || Arch == "any" || Arch == NativeArch()) return SingleArchFindPkg(Name); @@ -265,9 +269,14 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) { // Look at the hash bucket for the group Group *Grp = GrpP + HeaderP->GrpHashTable[sHash(Name)]; for (; Grp != GrpP; Grp = GrpP + Grp->Next) { - if (Grp->Name != 0 && StrP[Grp->Name] == Name[0] && - stringcasecmp(Name, StrP + Grp->Name) == 0) + if (unlikely(Grp->Name == 0)) + continue; + + int const cmp = strcasecmp(Name.c_str(), StrP + Grp->Name); + if (cmp == 0) return GrpIterator(*this, Grp); + else if (cmp < 0) + break; } return GrpIterator(*this,0); @@ -279,22 +288,22 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) { type in the weird debian style.. */ const char *pkgCache::CompTypeDeb(unsigned char Comp) { - const char *Ops[] = {"","<=",">=","<<",">>","=","!="}; - if ((unsigned)(Comp & 0xF) < 7) - return Ops[Comp & 0xF]; - return ""; + const char * const Ops[] = {"","<=",">=","<<",">>","=","!="}; + if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0]))) + return ""; + return Ops[Comp & 0xF]; } /*}}}*/ // Cache::CompType - Return a string describing the compare type /*{{{*/ // --------------------------------------------------------------------- -/* This returns a string representation of the dependency compare +/* This returns a string representation of the dependency compare type */ const char *pkgCache::CompType(unsigned char Comp) { - const char *Ops[] = {"","<=",">=","<",">","=","!="}; - if ((unsigned)(Comp & 0xF) < 7) - return Ops[Comp & 0xF]; - return ""; + const char * const Ops[] = {"","<=",">=","<",">","=","!="}; + if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0]))) + return ""; + return Ops[Comp & 0xF]; } /*}}}*/ // Cache::DepType - Return a string describing the dep type /*{{{*/ @@ -376,6 +385,10 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &Prefer if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0)) return Pkg; } + // packages without an architecture + Pkg = FindPkg("none"); + if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0)) + return Pkg; if (PreferNonVirtual == true) return FindPreferredPkg(false); @@ -619,13 +632,11 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets() const // Walk along the actual package providing versions for (VerIterator I = DPkg.VersionList(); I.end() == false; ++I) { - if (Owner->VS->CheckDep(I.VerStr(),S->CompareOp,TargetVer()) == false) + if (IsIgnorable(I.ParentPkg()) == true) continue; - - if (IsNegative() == true && - ParentPkg() == I.ParentPkg()) + if (IsSatisfied(I) == false) continue; - + Size++; if (Res != 0) *End++ = I; @@ -634,19 +645,10 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets() const // Follow all provides for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; ++I) { - if (Owner->VS->CheckDep(I.ProvideVersion(),S->CompareOp,TargetVer()) == false) + if (IsIgnorable(I) == true) + continue; + if (IsSatisfied(I) == false) continue; - - if (IsNegative() == true) - { - /* Provides may never be applied against the same package (or group) - if it is a conflicts. See the comment above. */ - if (I.OwnerPkg()->Group == ParentPkg()->Group) - continue; - // Implicit group-conflicts should not be applied on providers of other groups - if (ParentPkg()->Group == TargetPkg()->Group && I.OwnerPkg()->Group != ParentPkg()->Group) - continue; - } Size++; if (Res != 0) @@ -689,6 +691,80 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End) } } /*}}}*/ +// DepIterator::IsIgnorable - should this packag/providr be ignored? /*{{{*/ +// --------------------------------------------------------------------- +/* Deps like self-conflicts should be ignored as well as implicit conflicts + on virtual packages. */ +bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &Pkg) const +{ + if (IsNegative() == false) + return false; + + pkgCache::PkgIterator PP = ParentPkg(); + pkgCache::PkgIterator PT = TargetPkg(); + if (PP->Group != PT->Group) + return false; + // self-conflict + if (PP == PT) + return true; + pkgCache::VerIterator PV = ParentVer(); + // ignore group-conflict on a M-A:same package - but not our implicit dependencies + // so that we can have M-A:same packages conflicting with their own real name + if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) + { + // Replaces: ${self}:other ( << ${binary:Version}) + if (S->Type == pkgCache::Dep::Replaces && S->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0) + return false; + // Breaks: ${self}:other (!= ${binary:Version}) + if (S->Type == pkgCache::Dep::DpkgBreaks && S->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0) + return false; + return true; + } + + return false; +} +bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const +{ + if (IsNegative() == false) + return false; + + PkgIterator const Pkg = ParentPkg(); + /* Provides may never be applied against the same package (or group) + if it is a conflicts. See the comment above. */ + if (Prv.OwnerPkg()->Group == Pkg->Group) + return true; + // Implicit group-conflicts should not be applied on providers of other groups + if (Pkg->Group == TargetPkg()->Group && Prv.OwnerPkg()->Group != Pkg->Group) + return true; + + return false; +} + /*}}}*/ +// DepIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/ +// --------------------------------------------------------------------- +/* MultiArch can be translated to SingleArch for an resolver and we did so, + by adding dependencies to help the resolver understand the problem, but + sometimes it is needed to identify these to ignore them… */ +bool pkgCache::DepIterator::IsMultiArchImplicit() const +{ + if (ParentPkg()->Arch != TargetPkg()->Arch && + (S->Type == pkgCache::Dep::Replaces || + S->Type == pkgCache::Dep::DpkgBreaks || + S->Type == pkgCache::Dep::Conflicts)) + return true; + return false; +} + /*}}}*/ +// DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/ +bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const +{ + return Owner->VS->CheckDep(Ver.VerStr(),S->CompareOp,TargetVer()); +} +bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const +{ + return Owner->VS->CheckDep(Prv.ProvideVersion(),S->CompareOp,TargetVer()); +} + /*}}}*/ // ostream operator to handle string representation of a dependecy /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -927,3 +1003,17 @@ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const }; /*}}}*/ +// PrvIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/ +// --------------------------------------------------------------------- +/* MultiArch can be translated to SingleArch for an resolver and we did so, + by adding provides to help the resolver understand the problem, but + sometimes it is needed to identify these to ignore them… */ +bool pkgCache::PrvIterator::IsMultiArchImplicit() const +{ + pkgCache::PkgIterator const Owner = OwnerPkg(); + pkgCache::PkgIterator const Parent = ParentPkg(); + if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner->Name == Parent->Name) + return true; + return false; +} + /*}}}*/