// 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
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. */
// 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();
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
/*}}}*/
#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()
#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>
// 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)
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;
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)
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;
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 /*{{{*/
// ---------------------------------------------------------------------
/* */
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
{
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)
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();