X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/5bf15716398fdb767ca6249a0155219b88d7ae60..0c1a7101fda38ad9e43ef4c6757bfc9c0191a30c:/apt-pkg/pkgcache.cc?ds=sidebyside diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 2b5f53f6f..324445fa7 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -35,7 +36,6 @@ #include #include -#include /*}}}*/ using std::string; @@ -55,6 +55,7 @@ pkgCache::Header::Header() Dirty = false; HeaderSz = sizeof(pkgCache::Header); + GroupSz = sizeof(pkgCache::Group); PackageSz = sizeof(pkgCache::Package); PackageFileSz = sizeof(pkgCache::PackageFile); VersionSz = sizeof(pkgCache::Version); @@ -64,6 +65,7 @@ pkgCache::Header::Header() VerFileSz = sizeof(pkgCache::VerFile); DescFileSz = sizeof(pkgCache::DescFile); + GroupCount = 0; PackageCount = 0; VersionCount = 0; DescriptionCount = 0; @@ -90,6 +92,7 @@ pkgCache::Header::Header() bool pkgCache::Header::CheckSizes(Header &Against) const { if (HeaderSz == Against.HeaderSz && + GroupSz == Against.GroupSz && PackageSz == Against.PackageSz && PackageFileSz == Against.PackageFileSz && VersionSz == Against.VersionSz && @@ -108,6 +111,10 @@ bool pkgCache::Header::CheckSizes(Header &Against) const /* */ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) { + // call getArchitectures() with cached=false to ensure that the + // architectures cache is re-evaulated. this is needed in cases + // when the APT::Architecture field changes between two cache creations + MultiArchEnabled = APT::Configuration::getArchitectures(false).size() > 1; if (DoMap == true) ReMap(); } @@ -115,7 +122,7 @@ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) // Cache::ReMap - Reopen the cache file /*{{{*/ // --------------------------------------------------------------------- /* If the file is already closed then this will open it open it. */ -bool pkgCache::ReMap() +bool pkgCache::ReMap(bool const &Errorchecks) { // Apply the typecasts. HeaderP = (Header *)Map.Data(); @@ -131,6 +138,9 @@ bool pkgCache::ReMap() StringItemP = (StringItem *)Map.Data(); StrP = (char *)Map.Data(); + if (Errorchecks == false) + return true; + if (Map.Size() == 0 || HeaderP == 0) return _error->Error(_("Empty package cache")); @@ -178,11 +188,51 @@ unsigned long pkgCache::sHash(const char *Str) const return Hash % _count(HeaderP->PkgHashTable); } + /*}}}*/ +// Cache::SingleArchFindPkg - Locate a package by name /*{{{*/ +// --------------------------------------------------------------------- +/* Returns 0 on error, pointer to the package otherwise + The multiArch enabled methods will fallback to this one as it is (a bit) + faster for single arch environments and realworld is mostly singlearch… */ +pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name) +{ + // Look at the hash bucket + 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); + } + return PkgIterator(*this,0); +} /*}}}*/ // Cache::FindPkg - Locate a package by name /*{{{*/ // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ -pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string Arch) { +pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { + if (MultiArchCache() == false) + return SingleArchFindPkg(Name); + size_t const found = Name.find(':'); + if (found == string::npos) + return FindPkg(Name, "native"); + string const Arch = Name.substr(found+1); + if (Arch == "any") + return FindPkg(Name, "any"); + return FindPkg(Name.substr(0, found), Arch); +} + /*}}}*/ +// Cache::FindPkg - Locate a package by name /*{{{*/ +// --------------------------------------------------------------------- +/* Returns 0 on error, pointer to the package otherwise */ +pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) { + if (MultiArchCache() == false) { + if (Arch == "native" || Arch == "all" || Arch == "any" || + Arch == _config->Find("APT::Architecture")) + return SingleArchFindPkg(Name); + else + return PkgIterator(*this,0); + } /* We make a detour via the GrpIterator here as on a multi-arch environment a group is easier to find than a package (less entries in the buckets) */ @@ -263,7 +313,7 @@ const char *pkgCache::Priority(unsigned char Prio) // GrpIterator::FindPkg - Locate a package by arch /*{{{*/ // --------------------------------------------------------------------- /* Returns an End-Pointer on error, pointer to the package otherwise */ -pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) { +pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { if (unlikely(IsGood() == false || S->FirstPackage == 0)) return PkgIterator(*Owner, 0); @@ -299,29 +349,60 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) { return PkgIterator(*Owner, 0); } /*}}}*/ +// GrpIterator::FindPreferredPkg - Locate the "best" package /*{{{*/ +// --------------------------------------------------------------------- +/* Returns an End-Pointer on error, pointer to the package otherwise */ +pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const { + pkgCache::PkgIterator Pkg = FindPkg("native"); + if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0)) + return Pkg; + + std::vector const archs = APT::Configuration::getArchitectures(); + for (std::vector::const_iterator a = archs.begin(); + a != archs.end(); ++a) { + Pkg = FindPkg(*a); + if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0)) + return Pkg; + } + + if (PreferNonVirtual == true) + return FindPreferredPkg(false); + return PkgIterator(*Owner, 0); +} + /*}}}*/ // GrpIterator::NextPkg - Locate the next package in the group /*{{{*/ // --------------------------------------------------------------------- /* Returns an End-Pointer on error, pointer to the package otherwise. - We can't simply ++ to the next as the list of packages includes - "package noise" (= packages with the same hash value but different name) */ -pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) { + We can't simply ++ to the next as the next package of the last will + be from a different group (with the same hash value) */ +pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const { if (unlikely(IsGood() == false || S->FirstPackage == 0 || LastPkg.end() == true)) return PkgIterator(*Owner, 0); - // Iterate over the list to find the next package - pkgCache::Package *Pkg = Owner->PkgP + LastPkg.Index(); - Pkg = Owner->PkgP + Pkg->NextPackage; - for (; Pkg != Owner->PkgP; Pkg = Owner->PkgP + Pkg->NextPackage) { - if (S->Name == Pkg->Name) - return PkgIterator(*Owner, Pkg); - if ((Owner->PkgP + S->LastPackage) == Pkg) - break; - } + if (S->LastPackage == LastPkg.Index()) + return PkgIterator(*Owner, 0); - return PkgIterator(*Owner, 0); + return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage); } /*}}}*/ +// GrpIterator::operator ++ - Postfix incr /*{{{*/ +// --------------------------------------------------------------------- +/* This will advance to the next logical group in the hash table. */ +void pkgCache::GrpIterator::operator ++(int) +{ + // Follow the current links + if (S != Owner->GrpP) + S = Owner->GrpP + S->Next; + + // Follow the hash table + while (S == Owner->GrpP && (HashIndex+1) < (signed)_count(Owner->HeaderP->GrpHashTable)) + { + HashIndex++; + S = Owner->GrpP + Owner->HeaderP->GrpHashTable[HashIndex]; + } +}; + /*}}}*/ // PkgIterator::operator ++ - Postfix incr /*{{{*/ // --------------------------------------------------------------------- /* This will advance to the next logical package in the hash table. */ @@ -372,7 +453,7 @@ const char * pkgCache::PkgIterator::CandVersion() const { //TargetVer is empty, so don't use it. - VerIterator version = pkgPolicy::pkgPolicy(Owner).GetCandidateVer(*this); + VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this); if (version.IsGood()) return version.VerStr(); return 0; @@ -406,7 +487,7 @@ operator<<(ostream& out, pkgCache::PkgIterator Pkg) string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion()); string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr()); - out << Pkg.Name() << " < " << current; + out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current; if (current != candidate) out << " -> " << candidate; if ( newest != "none" && candidate != newest) @@ -415,11 +496,23 @@ operator<<(ostream& out, pkgCache::PkgIterator Pkg) return out; } /*}}}*/ +// PkgIterator::FullName - Returns Name and (maybe) Architecture /*{{{*/ +// --------------------------------------------------------------------- +/* Returns a name:arch string */ +std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const +{ + string fullname = Name(); + if (Pretty == false || + (strcmp(Arch(), "all") != 0 && _config->Find("APT::Architecture") != Arch())) + return fullname.append(":").append(Arch()); + return fullname; +} + /*}}}*/ // DepIterator::IsCritical - Returns true if the dep is important /*{{{*/ // --------------------------------------------------------------------- /* Currently critical deps are defined as depends, predepends and conflicts (including dpkg's Breaks fields). */ -bool pkgCache::DepIterator::IsCritical() +bool pkgCache::DepIterator::IsCritical() const { if (S->Type == pkgCache::Dep::Conflicts || S->Type == pkgCache::Dep::DpkgBreaks || @@ -443,7 +536,7 @@ bool pkgCache::DepIterator::IsCritical() In Conjunction with the DepCache the value of Result may not be super-good since the policy may have made it uninstallable. Using AllTargets is better in this case. */ -bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) +bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const { Result = TargetPkg(); @@ -492,7 +585,7 @@ bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) provides. It includes every possible package-version that could satisfy the dependency. The last item in the list has a 0. The resulting pointer must be delete [] 'd */ -pkgCache::Version **pkgCache::DepIterator::AllTargets() +pkgCache::Version **pkgCache::DepIterator::AllTargets() const { Version **Res = 0; unsigned long Size =0; @@ -571,6 +664,30 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End) } } /*}}}*/ +// ostream operator to handle string representation of a dependecy /*{{{*/ +// --------------------------------------------------------------------- +/* */ +std::ostream& operator<<(ostream& out, pkgCache::DepIterator D) +{ + if (D.end() == true) + return out << "invalid dependency"; + + pkgCache::PkgIterator P = D.ParentPkg(); + pkgCache::PkgIterator T = D.TargetPkg(); + + out << (P.end() ? "invalid pkg" : P.FullName(false)) << " " << D.DepType() + << " on "; + if (T.end() == true) + out << "invalid pkg"; + else + out << T; + + if (D->Version != 0) + out << " (" << D.CompType() << " " << D.TargetVer() << ")"; + + return out; +} + /*}}}*/ // VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/ // --------------------------------------------------------------------- /* This just looks over the version list to see if B is listed before A. In @@ -614,11 +731,29 @@ bool pkgCache::VerIterator::Automatic() const { VerFileIterator Files = FileList(); for (; Files.end() == false; Files++) + // Do not check ButAutomaticUpgrades here as it is kind of automatic… if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic) return true; return false; } /*}}}*/ +// VerIterator::Pseudo - Check if this version is a pseudo one /*{{{*/ +// --------------------------------------------------------------------- +/* Sometimes you have the need to express dependencies with versions + which doesn't really exist or exist multiply times for "different" + packages. We need these versions for dependency resolution but they + are a problem everytime we need to download/install something. */ +bool pkgCache::VerIterator::Pseudo() const +{ + if (S->MultiArch == pkgCache::Version::All && + strcmp(Arch(true),"all") != 0) + { + GrpIterator const Grp = ParentPkg().Group(); + return (Grp->LastPackage != Grp->FirstPackage); + } + return false; +} + /*}}}*/ // VerIterator::NewestFile - Return the newest file version relation /*{{{*/ // --------------------------------------------------------------------- /* This looks at the version numbers associated with all of the sources @@ -640,7 +775,7 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const // --------------------------------------------------------------------- /* This describes the version from a release-centric manner. The output is a list of Label:Version/Archive */ -string pkgCache::VerIterator::RelStr() +string pkgCache::VerIterator::RelStr() const { bool First = true; string Res; @@ -699,7 +834,9 @@ string pkgCache::VerIterator::RelStr() else Res += File.Site(); } - } + } + if (S->ParentPkg != 0) + Res.append(" [").append(Arch()).append("]"); return Res; } /*}}}*/ @@ -738,6 +875,8 @@ string pkgCache::PkgFileIterator::RelStr() Res = Res + (Res.empty() == true?"l=":",l=") + Label(); if (Component() != 0) Res = Res + (Res.empty() == true?"c=":",c=") + Component(); + if (Architecture() != 0) + Res = Res + (Res.empty() == true?"b=":",b=") + Architecture(); return Res; } /*}}}*/ @@ -756,7 +895,8 @@ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const pkgCache::DescIterator Desc = DescDefault; for (; Desc.end() == false; Desc++) - if (*l == Desc.LanguageCode()) + if (*l == Desc.LanguageCode() || + (*l == "en" && strcmp(Desc.LanguageCode(),"") == 0)) break; if (Desc.end() == true) Desc = DescDefault;