summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/cacheiterators.h14
-rw-r--r--apt-pkg/deb/deblistparser.cc24
-rw-r--r--apt-pkg/pkgcache.cc27
-rw-r--r--apt-pkg/pkgcache.h12
-rw-r--r--apt-pkg/pkgcachegen.cc133
-rw-r--r--apt-pkg/pkgcachegen.h6
6 files changed, 176 insertions, 40 deletions
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index 35d3aa228..33d2ed6be 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -81,13 +81,21 @@ template<typename Str, typename Itr> class pkgCache::Iterator {
different architectures can be treated as of the "same" package
(apt internally treat them as totally different packages) */
class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
+ long HashIndex;
+
protected:
inline Group* OwnerPointer() const {
return Owner->GrpP;
};
public:
- void operator ++(int) {if (S != Owner->GrpP) S = Owner->GrpP + S->Next;};
+ // This constructor is the 'begin' constructor, never use it.
+ inline GrpIterator(pkgCache &Owner) : Iterator<Group, GrpIterator>(Owner), HashIndex(-1) {
+ S = OwnerPointer();
+ operator ++(0);
+ };
+
+ virtual void operator ++(int);
virtual void operator ++() {operator ++(0);};
inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
@@ -96,11 +104,11 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
PkgIterator NextPkg(PkgIterator const &Pkg);
// Constructors
- inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator<Group, GrpIterator>(Owner, Trg) {
+ inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator<Group, GrpIterator>(Owner, Trg), HashIndex(0) {
if (S == 0)
S = OwnerPointer();
};
- inline GrpIterator() : Iterator<Group, GrpIterator>() {};
+ inline GrpIterator() : Iterator<Group, GrpIterator>(), HashIndex(0) {};
};
/*}}}*/
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index b57eca813..f683de423 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -104,6 +104,30 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
// Parse the architecture
Ver->Arch = WriteUniqString(Architecture());
+ // Parse multi-arch
+ if (Section.FindS("Architecture") == "all")
+ /* Arch all packages can't have a Multi-Arch field,
+ but we need a special treatment for them nonetheless */
+ Ver->MultiArch = pkgCache::Version::All;
+ else
+ {
+ string const MultiArch = Section.FindS("Multi-Arch");
+ if (MultiArch.empty() == true)
+ Ver->MultiArch = pkgCache::Version::None;
+ else if (MultiArch == "same")
+ Ver->MultiArch = pkgCache::Version::Same;
+ else if (MultiArch == "foreign")
+ Ver->MultiArch = pkgCache::Version::Foreign;
+ else if (MultiArch == "allowed")
+ Ver->MultiArch = pkgCache::Version::Allowed;
+ else
+ {
+ _error->Warning("Unknown Multi-Arch type »%s« for package »%s«",
+ MultiArch.c_str(), Section.FindS("Package").c_str());
+ Ver->MultiArch = pkgCache::Version::None;
+ }
+ }
+
// Archive Size
Ver->Size = (unsigned)Section.FindI("Size");
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index c945c59bf..1e4c7edb3 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -182,6 +182,16 @@ unsigned long pkgCache::sHash(const char *Str) const
// Cache::FindPkg - Locate a package by name /*{{{*/
// ---------------------------------------------------------------------
/* Returns 0 on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
+ size_t const found = Name.find(':');
+ if (found == string::npos)
+ return FindPkg(Name, "native");
+ return FindPkg(Name.substr(0, found), Name.substr(found+1, string::npos));
+}
+ /*}}}*/
+// 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) {
/* We make a detour via the GrpIterator here as
on a multi-arch environment a group is easier to
@@ -322,6 +332,23 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const
return PkgIterator(*Owner, 0);
}
/*}}}*/
+// 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. */
diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h
index b3d2752d2..5f50001d0 100644
--- a/apt-pkg/pkgcache.h
+++ b/apt-pkg/pkgcache.h
@@ -125,9 +125,12 @@ class pkgCache /*{{{*/
// Accessors
GrpIterator FindGrp(const string &Name);
- PkgIterator FindPkg(const string &Name, string Arch = "native");
+ PkgIterator FindPkg(const string &Name);
+ PkgIterator FindPkg(const string &Name, string Arch);
Header &Head() {return *HeaderP;};
+ inline GrpIterator GrpBegin();
+ inline GrpIterator GrpEnd();
inline PkgIterator PkgBegin();
inline PkgIterator PkgEnd();
inline PkgFileIterator FileBegin();
@@ -274,7 +277,8 @@ struct pkgCache::Version /*{{{*/
map_ptrloc VerStr; // Stringtable
map_ptrloc Section; // StringTable (StringItem)
map_ptrloc Arch; // StringTable
-
+ enum {None, All, Foreign, Same, Allowed} MultiArch;
+
// Lists
map_ptrloc FileList; // VerFile
map_ptrloc NextVer; // Version
@@ -337,6 +341,10 @@ struct pkgCache::StringItem /*{{{*/
/*}}}*/
#include <apt-pkg/cacheiterators.h>
+inline pkgCache::GrpIterator pkgCache::GrpBegin()
+ {return GrpIterator(*this);};
+inline pkgCache::GrpIterator pkgCache::GrpEnd()
+ {return GrpIterator(*this,GrpP);};
inline pkgCache::PkgIterator pkgCache::PkgBegin()
{return PkgIterator(*this);};
inline pkgCache::PkgIterator pkgCache::PkgEnd()
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index c37f6f48e..2a4a30349 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -18,6 +18,7 @@
#include <apt-pkg/progress.h>
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/pkgsystem.h>
@@ -38,7 +39,7 @@ typedef vector<pkgIndexFile *>::iterator FileIterator;
// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
// ---------------------------------------------------------------------
-/* We set the diry flag and make sure that is written to the disk */
+/* We set the dirty flag and make sure that is written to the disk */
pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
Map(*pMap), Cache(pMap,false), Progress(Prog),
FoundFileDeps(0)
@@ -506,21 +507,58 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
return Description;
}
/*}}}*/
-// ListParser::NewDepends - Create a dependency element /*{{{*/
+// CacheGenerator::FinishCache - do various finish operations /*{{{*/
+// ---------------------------------------------------------------------
+/* This prepares the Cache for delivery */
+bool pkgCacheGenerator::FinishCache(OpProgress &Progress) {
+ // FIXME: add progress reporting for this operation
+ // Do we have different architectures in your groups ?
+ vector<string> archs = APT::Configuration::getArchitectures();
+ if (archs.size() > 1) {
+ // Create Conflicts in between the group
+ for (pkgCache::GrpIterator G = GetCache().GrpBegin(); G.end() != true; G++) {
+ string const PkgName = G.Name();
+ for (pkgCache::PkgIterator P = G.PackageList(); P.end() != true; P = G.NextPkg(P)) {
+ for (pkgCache::VerIterator V = P.VersionList(); V.end() != true; V++) {
+ // Arch all packages are "co-installable"
+ if (V->MultiArch == pkgCache::Version::All)
+ continue;
+ string const Arch = V.Arch();
+ map_ptrloc *OldDepLast = NULL;
+ for (vector<string>::const_iterator A = archs.begin(); A != archs.end(); ++A) {
+ if (*A == Arch)
+ continue;
+ /* We allow only one installed arch at the time
+ per group, therefore each group member conflicts
+ with all other group members */
+ pkgCache::PkgIterator D = G.FindPkg(*A);
+ if (D.end() == true)
+ continue;
+ // Conflicts: ${self}:other
+ NewDepends(D, V, "",
+ pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts,
+ OldDepLast);
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+ /*}}}*/
+// CacheGenerator::NewDepends - Create a dependency element /*{{{*/
// ---------------------------------------------------------------------
/* This creates a dependency element in the tree. It is linked to the
version and to the package that it is pointing to. */
-bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
- const string &PackageName,
- const string &Arch,
- const string &Version,
- unsigned int Op,
- unsigned int Type)
+bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
+ pkgCache::VerIterator &Ver,
+ string const &Version,
+ unsigned int const &Op,
+ unsigned int const &Type,
+ map_ptrloc *OldDepLast)
{
- pkgCache &Cache = Owner->Cache;
-
// Get a structure
- unsigned long const Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency));
+ unsigned long const Dependency = Map.Allocate(sizeof(pkgCache::Dependency));
if (unlikely(Dependency == 0))
return false;
@@ -530,17 +568,6 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
Dep->Type = Type;
Dep->CompareOp = Op;
Dep->ID = Cache.HeaderP->DependsCount++;
-
- pkgCache::GrpIterator Grp;
- if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
- return false;
-
- // Locate the target package
- pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch);
- if (Pkg.end() == true) {
- if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
- return false;
- }
// Probe the reverse dependency list for a version string that matches
if (Version.empty() == false)
@@ -549,29 +576,23 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
if (I->Version != 0 && I.TargetVer() == Version)
Dep->Version = I->Version;*/
if (Dep->Version == 0)
- if (unlikely((Dep->Version = WriteString(Version)) == 0))
+ if (unlikely((Dep->Version = Map.WriteString(Version)) == 0))
return false;
}
-
+
// Link it to the package
Dep->Package = Pkg.Index();
Dep->NextRevDepends = Pkg->RevDepends;
Pkg->RevDepends = Dep.Index();
-
- /* Link it to the version (at the end of the list)
- Caching the old end point speeds up generation substantially */
- if (OldDepVer != Ver)
+
+ // Do we know where to link the Dependency to?
+ if (OldDepLast == NULL)
{
OldDepLast = &Ver->DependsList;
for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
OldDepLast = &D->NextDepends;
- OldDepVer = Ver;
}
- // Is it a file dependency?
- if (unlikely(PackageName[0] == '/'))
- FoundFileDeps = true;
-
Dep->NextDepends = *OldDepLast;
*OldDepLast = Dep.Index();
OldDepLast = &Dep->NextDepends;
@@ -579,6 +600,41 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
return true;
}
/*}}}*/
+// ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
+// ---------------------------------------------------------------------
+/* This creates a Group and the Package to link this dependency to if
+ needed and handles also the caching of the old endpoint */
+bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
+ const string &PackageName,
+ const string &Arch,
+ const string &Version,
+ unsigned int Op,
+ unsigned int Type)
+{
+ pkgCache::GrpIterator Grp;
+ if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
+ return false;
+
+ // Locate the target package
+ pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch);
+ if (Pkg.end() == true) {
+ if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
+ return false;
+ }
+
+ // Is it a file dependency?
+ if (unlikely(PackageName[0] == '/'))
+ FoundFileDeps = true;
+
+ /* Caching the old end point speeds up generation substantially */
+ if (OldDepVer != Ver) {
+ OldDepLast = NULL;
+ OldDepVer = Ver;
+ }
+
+ return Owner->NewDepends(Pkg, Ver, Version, Op, Type, OldDepLast);
+}
+ /*}}}*/
// ListParser::NewProvides - Create a Provides element /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -925,6 +981,9 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
Files.begin()+EndOfSource,Files.end()) == false)
return false;
+
+ // FIXME: move me to a better place
+ Gen.FinishCache(Progress);
}
else
{
@@ -965,6 +1024,9 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
Files.begin()+EndOfSource,Files.end()) == false)
return false;
+
+ // FIXME: move me to a better place
+ Gen.FinishCache(Progress);
}
if (_error->PendingError() == true)
@@ -1010,7 +1072,10 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
Files.begin()+EndOfSource,Files.end()) == false)
return false;
-
+
+ // FIXME: move me to a better place
+ Gen.FinishCache(Progress);
+
if (_error->PendingError() == true)
return false;
*OutMap = Map.UnGuard();
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index 4a2419b24..53f09b991 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -55,6 +55,9 @@ class pkgCacheGenerator /*{{{*/
bool NewPackage(pkgCache::PkgIterator &Pkg,const string &Name, const string &Arch);
bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
+ bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
+ string const &Version, unsigned int const &Op,
+ unsigned int const &Type, map_ptrloc *OldDepLast);
unsigned long NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next);
map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const string &Lang,const MD5SumValue &md5sum,map_ptrloc Next);
@@ -73,7 +76,8 @@ class pkgCacheGenerator /*{{{*/
bool HasFileDeps() {return FoundFileDeps;};
bool MergeFileProvides(ListParser &List);
-
+ bool FinishCache(OpProgress &Progress);
+
pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
~pkgCacheGenerator();
};