X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/fd23676e809b7fa87ae138cc22d2c683d212950e..d27daedb6a0bf672508072100f20233d08ccf0e0:/apt-pkg/pkgcache.cc diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 897f1ee2a..e65e37bca 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -34,7 +34,8 @@ #include #include -#include +#include +#include #include #include #include @@ -50,31 +51,35 @@ using std::string; /* Simply initialize the header */ pkgCache::Header::Header() { - Signature = 0x98FE76DC; - +#define APT_HEADER_SET(X,Y) X = Y; static_assert(std::numeric_limits::max() > Y, "Size violation detected in pkgCache::Header") + APT_HEADER_SET(Signature, 0x98FE76DC); + /* Whenever the structures change the major version should be bumped, whenever the generator changes the minor version should be bumped. */ - MajorVersion = 10; - MinorVersion = 0; - Dirty = false; - - HeaderSz = sizeof(pkgCache::Header); - GroupSz = sizeof(pkgCache::Group); - PackageSz = sizeof(pkgCache::Package); - ReleaseFileSz = sizeof(pkgCache::ReleaseFile); - PackageFileSz = sizeof(pkgCache::PackageFile); - VersionSz = sizeof(pkgCache::Version); - DescriptionSz = sizeof(pkgCache::Description); - DependencySz = sizeof(pkgCache::Dependency); - ProvidesSz = sizeof(pkgCache::Provides); - VerFileSz = sizeof(pkgCache::VerFile); - DescFileSz = sizeof(pkgCache::DescFile); - + APT_HEADER_SET(MajorVersion, 10); + APT_HEADER_SET(MinorVersion, 2); + APT_HEADER_SET(Dirty, false); + + APT_HEADER_SET(HeaderSz, sizeof(pkgCache::Header)); + APT_HEADER_SET(GroupSz, sizeof(pkgCache::Group)); + APT_HEADER_SET(PackageSz, sizeof(pkgCache::Package)); + APT_HEADER_SET(ReleaseFileSz, sizeof(pkgCache::ReleaseFile)); + APT_HEADER_SET(PackageFileSz, sizeof(pkgCache::PackageFile)); + APT_HEADER_SET(VersionSz, sizeof(pkgCache::Version)); + APT_HEADER_SET(DescriptionSz, sizeof(pkgCache::Description)); + APT_HEADER_SET(DependencySz, sizeof(pkgCache::Dependency)); + APT_HEADER_SET(DependencyDataSz, sizeof(pkgCache::DependencyData)); + APT_HEADER_SET(ProvidesSz, sizeof(pkgCache::Provides)); + APT_HEADER_SET(VerFileSz, sizeof(pkgCache::VerFile)); + APT_HEADER_SET(DescFileSz, sizeof(pkgCache::DescFile)); +#undef APT_HEADER_SET + GroupCount = 0; PackageCount = 0; VersionCount = 0; DescriptionCount = 0; DependsCount = 0; + DependsDataCount = 0; ReleaseFileCount = 0; PackageFileCount = 0; VerFileCount = 0; @@ -82,12 +87,9 @@ pkgCache::Header::Header() ProvidesCount = 0; MaxVerFileSize = 0; MaxDescFileSize = 0; - + FileList = 0; RlsFileList = 0; -#if APT_PKG_ABI < 413 - APT_IGNORE_DEPRECATED(StringList = 0;) -#endif VerSysName = 0; Architecture = 0; SetArchitectures(0); @@ -110,6 +112,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const VersionSz == Against.VersionSz && DescriptionSz == Against.DescriptionSz && DependencySz == Against.DependencySz && + DependencyDataSz == Against.DependencyDataSz && VerFileSz == Against.VerFileSz && DescFileSz == Against.DescFileSz && ProvidesSz == Against.ProvidesSz) @@ -150,6 +153,7 @@ bool pkgCache::ReMap(bool const &Errorchecks) DescP = (Description *)Map.Data(); ProvideP = (Provides *)Map.Data(); DepP = (Dependency *)Map.Data(); + DepDataP = (DependencyData *)Map.Data(); StrP = (char *)Map.Data(); if (Errorchecks == false) @@ -213,26 +217,6 @@ map_id_t pkgCache::sHash(const char *Str) const return Hash % HeaderP->GetHashTableSize(); } /*}}}*/ -// 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->PkgHashTableP()[Hash(Name)]; - for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage) - { - int const cmp = strcmp(Name.c_str(), StrP + (GrpP + Pkg->Group)->Name); - if (cmp == 0) - return PkgIterator(*this, Pkg); - else if (cmp < 0) - break; - } - return PkgIterator(*this,0); -} - /*}}}*/ // Cache::FindPkg - Locate a package by name /*{{{*/ // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ @@ -241,9 +225,9 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { if (found == string::npos) return FindPkg(Name, "native"); string const Arch = Name.substr(found+1); - /* Beware: This is specialcased to handle pkg:any in dependencies as - these are linked to virtual pkg:any named packages with all archs. - If you want any arch from a given pkg, use FindPkg(pkg,arch) */ + /* Beware: This is specialcased to handle pkg:any in dependencies + as these are linked to virtual pkg:any named packages. + If you want any arch from a pkg, use FindPkg(pkg,"any") */ if (Arch == "any") return FindPkg(Name, "any"); return FindPkg(Name.substr(0, found), Arch); @@ -325,7 +309,7 @@ const char *pkgCache::DepType(unsigned char Type) /* */ const char *pkgCache::Priority(unsigned char Prio) { - const char *Mapping[] = {0,_("important"),_("required"),_("standard"), + const char *Mapping[] = {0,_("required"),_("important"),_("standard"), _("optional"),_("extra")}; if (Prio < _count(Mapping)) return Mapping[Prio]; @@ -340,20 +324,11 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { return PkgIterator(*Owner, 0); /* If we accept any package we simply return the "first" - package in this group (the last one added). */ + package in this group */ if (Arch == "any") return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage); - - char const* const myArch = Owner->NativeArch(); - /* Most of the time the package for our native architecture is - the one we add at first to the cache, but this would be the - last one we check, so we do it now. */ - if (Arch == "native" || Arch == myArch || Arch == "all") { - pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage; - if (strcmp(myArch, Owner->StrP + Pkg->Arch) == 0) - return PkgIterator(*Owner, Pkg); - Arch = myArch; - } + if (Arch == "native" || Arch == "all") + Arch = Owner->NativeArch(); // Iterate over the list to find the matching arch for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP; @@ -408,7 +383,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage); } /*}}}*/ -// GrpIterator::operator ++ - Postfix incr /*{{{*/ +// GrpIterator::operator++ - Prefix incr /*{{{*/ // --------------------------------------------------------------------- /* This will advance to the next logical group in the hash table. */ pkgCache::GrpIterator& pkgCache::GrpIterator::operator++() @@ -420,16 +395,16 @@ pkgCache::GrpIterator& pkgCache::GrpIterator::operator++() // Follow the hash table while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize()) { - HashIndex++; + ++HashIndex; S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex]; } return *this; } /*}}}*/ -// PkgIterator::operator ++ - Postfix incr /*{{{*/ +// PkgIterator::operator++ - Prefix incr /*{{{*/ // --------------------------------------------------------------------- /* This will advance to the next logical package in the hash table. */ -pkgCache::PkgIterator& pkgCache::PkgIterator::operator ++() +pkgCache::PkgIterator& pkgCache::PkgIterator::operator++() { // Follow the current links if (S != Owner->PkgP) @@ -438,12 +413,24 @@ pkgCache::PkgIterator& pkgCache::PkgIterator::operator ++() // Follow the hash table while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize()) { - HashIndex++; + ++HashIndex; S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex]; } return *this; } /*}}}*/ +pkgCache::DepIterator& pkgCache::DepIterator::operator++() /*{{{*/ +{ + if (S == Owner->DepP) + return *this; + S = Owner->DepP + (Type == DepVer ? S->NextDepends : S->NextRevDepends); + if (S == Owner->DepP) + S2 = Owner->DepDataP; + else + S2 = Owner->DepDataP + S->DependencyData; + return *this; +} + /*}}}*/ // PkgIterator::State - Check the State of the package /*{{{*/ // --------------------------------------------------------------------- /* By this we mean if it is either cleanly installed or cleanly removed. */ @@ -530,7 +517,7 @@ std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const { string fullname = Name(); if (Pretty == false || - (strcmp(Arch(), "all") != 0 && + (strcmp(Arch(), "all") != 0 && strcmp(Arch(), "any") != 0 && strcmp(Owner->NativeArch(), Arch()) != 0)) return fullname.append(":").append(Arch()); return fullname; @@ -543,8 +530,8 @@ std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const bool pkgCache::DepIterator::IsCritical() const { if (IsNegative() == true || - S->Type == pkgCache::Dep::Depends || - S->Type == pkgCache::Dep::PreDepends) + S2->Type == pkgCache::Dep::Depends || + S2->Type == pkgCache::Dep::PreDepends) return true; return false; } @@ -555,9 +542,9 @@ bool pkgCache::DepIterator::IsCritical() const are negative like Conflicts which can and should be handled differently */ bool pkgCache::DepIterator::IsNegative() const { - return S->Type == Dep::DpkgBreaks || - S->Type == Dep::Conflicts || - S->Type == Dep::Obsoletes; + return S2->Type == Dep::DpkgBreaks || + S2->Type == Dep::Conflicts || + S2->Type == Dep::Obsoletes; } /*}}}*/ // DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/ @@ -686,7 +673,7 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End) End = *this; for (bool LastOR = true; end() == false && LastOR == true;) { - LastOR = (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + LastOR = (S2->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; ++(*this); if (LastOR == true) End = (*this); @@ -712,21 +699,7 @@ bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &PT) const // 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) - { - if (S->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; - } - // Breaks: ${self}:other (!= ${binary:Version}) - else if (S->Type == pkgCache::Dep::DpkgBreaks) - { - if (S->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; - } - return true; - } + return IsMultiArchImplicit() == false; return false; } @@ -741,35 +714,34 @@ bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const 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) + if (IsMultiArchImplicit() && 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()); + return Owner->VS->CheckDep(Ver.VerStr(),S2->CompareOp,TargetVer()); } bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const { - return Owner->VS->CheckDep(Prv.ProvideVersion(),S->CompareOp,TargetVer()); + return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer()); +} + /*}}}*/ +// DepIterator::IsImplicit - added by the cache generation /*{{{*/ +bool pkgCache::DepIterator::IsImplicit() const +{ + if (IsMultiArchImplicit() == true) + return true; + if (IsNegative() || S2->Type == pkgCache::Dep::Replaces) + { + if ((S2->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific && + strcmp(ParentPkg().Arch(), TargetPkg().Arch()) != 0) + return true; + } + return false; } /*}}}*/ // ostream operator to handle string representation of a dependecy /*{{{*/ @@ -866,10 +838,32 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const // --------------------------------------------------------------------- /* This describes the version from a release-centric manner. The output is a list of Label:Version/Archive */ +static std::string PkgFileIteratorToRelString(pkgCache::PkgFileIterator const &File) +{ + std::string Res; + if (File.Label() != 0) + Res = Res + File.Label() + ':'; + + if (File.Archive() != 0) + { + if (File.Version() == 0) + Res += File.Archive(); + else + Res = Res + File.Version() + '/' + File.Archive(); + } + else + { + // No release file, print the host name that this came from + if (File.Site() == 0 || File.Site()[0] == 0) + Res += "localhost"; + else + Res += File.Site(); + } + return Res; +} string pkgCache::VerIterator::RelStr() const { - bool First = true; - string Res; + std::vector RelStrs; for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I) { // Do not print 'not source' entries' @@ -877,58 +871,21 @@ string pkgCache::VerIterator::RelStr() const if (File.Flagged(pkgCache::Flag::NotSource)) continue; - // See if we have already printed this out.. - bool Seen = false; - for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J) - { - pkgCache::PkgFileIterator const File2 = J.File(); - if (File2.Label() == 0 || File.Label() == 0) - continue; - - if (strcmp(File.Label(),File2.Label()) != 0) - continue; - - if (File2.Version() == File.Version()) - { - Seen = true; - break; - } - if (File2.Version() == 0 || File.Version() == 0) - break; - if (strcmp(File.Version(),File2.Version()) == 0) - Seen = true; - } - - if (Seen == true) + std::string const RS = PkgFileIteratorToRelString(File); + if (std::find(RelStrs.begin(), RelStrs.end(), RS) != RelStrs.end()) continue; - - if (First == false) - Res += ", "; - else - First = false; - - if (File.Label() != 0) - Res = Res + File.Label() + ':'; - if (File.Archive() != 0) - { - if (File.Version() == 0) - Res += File.Archive(); - else - Res = Res + File.Version() + '/' + File.Archive(); - } - else - { - // No release file, print the host name that this came from - if (File.Site() == 0 || File.Site()[0] == 0) - Res += "localhost"; - else - Res += File.Site(); - } + RelStrs.push_back(RS); + } + std::ostringstream os; + if (likely(RelStrs.empty() == false)) + { + std::copy(RelStrs.begin(), RelStrs.end()-1, std::ostream_iterator(os, ", ")); + os << *RelStrs.rbegin(); } if (S->ParentPkg != 0) - Res.append(" [").append(Arch()).append("]"); - return Res; + os << " [" << Arch() << "]"; + return os.str(); } /*}}}*/ // VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/ @@ -1052,19 +1009,5 @@ 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.Group()->Name == Parent.Group()->Name) - return true; - return false; -} - /*}}}*/ pkgCache::~pkgCache() {}