##################################################################### */
/*}}}*/
// Include Files /*{{{*/
+#include<config.h>
+
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/policy.h>
#include <apt-pkg/version.h>
#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/macros.h>
-#include <apti18n.h>
-
#include <string>
#include <sys/stat.h>
#include <unistd.h>
-
#include <ctype.h>
+
+#include <apti18n.h>
/*}}}*/
using std::string;
/* Whenever the structures change the major version should be bumped,
whenever the generator changes the minor version should be bumped. */
- MajorVersion = 8;
+ MajorVersion = 9;
MinorVersion = 0;
Dirty = false;
{
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 /*{{{*/
// ---------------------------------------------------------------------
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);
}
// ---------------------------------------------------------------------
/* 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);
// 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);
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 /*{{{*/
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);
if they provide no new information (e.g. there is no newer version than candidate)
If no version and/or section can be found "none" is used. */
std::ostream&
-operator<<(ostream& out, pkgCache::PkgIterator Pkg)
+operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
{
if (Pkg.end() == true)
return out << "invalid package";
// 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;
// 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 (IsNegative() == true &&
- ParentPkg() == I.OwnerPkg())
+ if (IsSatisfied(I) == false)
continue;
-
+
Size++;
if (Res != 0)
*End++ = I.OwnerVer();
}
}
/*}}}*/
+// 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 /*{{{*/
// ---------------------------------------------------------------------
/* */
-std::ostream& operator<<(ostream& out, pkgCache::DepIterator D)
+std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D)
{
if (D.end() == true)
return out << "invalid dependency";
{
pkgCache::DescIterator Desc = DescriptionList();
for (; Desc.end() == false; ++Desc)
- if (*l == Desc.LanguageCode() ||
- (*l == "en" && strcmp(Desc.LanguageCode(),"") == 0))
+ if (*l == Desc.LanguageCode())
break;
if (Desc.end() == true)
- continue;
+ {
+ if (*l == "en")
+ {
+ Desc = DescriptionList();
+ for (; Desc.end() == false; ++Desc)
+ if (strcmp(Desc.LanguageCode(), "") == 0)
+ break;
+ if (Desc.end() == true)
+ continue;
+ }
+ else
+ continue;
+ }
return Desc;
}
for (pkgCache::DescIterator Desc = DescriptionList();
};
/*}}}*/
+// 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;
+}
+ /*}}}*/