From 5bf15716398fdb767ca6249a0155219b88d7ae60 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 19 Dec 2009 16:25:56 +0100 Subject: Implement the first step toward Multi-Arch by setting up a Group infrastructor for packages. APT is now aware of the fact that a package A in architecture X can't satisfy a dependency on package A in architecture Y - to handle these packages are now identified by name and architecture, so different architectures of the same package are handled internally as completly different packages. This is great for pinning, dependency checking and in many other situations, but sometimes we need to know which archs are available for a given package: Here Groups come to our rescue! --- apt-pkg/pkgcachegen.cc | 111 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 33 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 68180c702..c37f6f48e 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -108,12 +108,12 @@ bool pkgCacheGenerator::MergeList(ListParser &List, while (List.Step() == true) { // Get a pointer to the package structure - string PackageName = List.Package(); + string const PackageName = List.Package(); if (PackageName.empty() == true) return false; - + pkgCache::PkgIterator Pkg; - if (NewPackage(Pkg,PackageName) == false) + if (NewPackage(Pkg, PackageName, List.Architecture()) == false) return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str()); Counter++; if (Counter % 100 == 0 && Progress != 0) @@ -323,33 +323,71 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List) return true; } /*}}}*/ +// CacheGenerator::NewGroup - Add a new group /*{{{*/ +// --------------------------------------------------------------------- +/* This creates a new group structure and adds it to the hash table */ +bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) { + Grp = Cache.FindGrp(Name); + if (Grp.end() == false) + return true; + + // Get a structure + unsigned long const Group = Map.Allocate(sizeof(pkgCache::Group)); + if (unlikely(Group == 0)) + return false; + + Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group); + Grp->Name = Map.WriteString(Name); + if (unlikely(Grp->Name == 0)) + return false; + + // Insert it into the hash table + unsigned long const Hash = Cache.Hash(Name); + Grp->Next = Cache.HeaderP->GrpHashTable[Hash]; + Cache.HeaderP->GrpHashTable[Hash] = Group; + + Cache.HeaderP->GroupCount++; + + return true; +} + /*}}}*/ // CacheGenerator::NewPackage - Add a new package /*{{{*/ // --------------------------------------------------------------------- /* This creates a new package structure and adds it to the hash table */ -bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name) -{ - Pkg = Cache.FindPkg(Name); - if (Pkg.end() == false) - return true; +bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name, + const string &Arch) { + pkgCache::GrpIterator Grp; + if (unlikely(NewGroup(Grp, Name) == false)) + return false; + + Pkg = Grp.FindPkg(Arch); + if (Pkg.end() == false) + return true; // Get a structure - unsigned long Package = Map.Allocate(sizeof(pkgCache::Package)); - if (Package == 0) + unsigned long const Package = Map.Allocate(sizeof(pkgCache::Package)); + if (unlikely(Package == 0)) return false; - Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package); - + // Insert it into the hash table - unsigned long Hash = Cache.Hash(Name); - Pkg->NextPackage = Cache.HeaderP->HashTable[Hash]; - Cache.HeaderP->HashTable[Hash] = Package; - - // Set the name and the ID - Pkg->Name = Map.WriteString(Name); - if (Pkg->Name == 0) + unsigned long const Hash = Cache.Hash(Name); + Pkg->NextPackage = Cache.HeaderP->PkgHashTable[Hash]; + Cache.HeaderP->PkgHashTable[Hash] = Package; + + // remember the packages in the group + Grp->FirstPackage = Package; + if (Grp->LastPackage == 0) + Grp->LastPackage = Package; + + // Set the name, arch and the ID + Pkg->Name = Grp->Name; + Pkg->Group = Grp.Index(); + Pkg->Arch = WriteUniqString(Arch.c_str()); + if (unlikely(Pkg->Arch == 0)) return false; Pkg->ID = Cache.HeaderP->PackageCount++; - + return true; } /*}}}*/ @@ -474,6 +512,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, 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) @@ -481,8 +520,8 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, pkgCache &Cache = Owner->Cache; // Get a structure - unsigned long Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency)); - if (Dependency == 0) + unsigned long const Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency)); + if (unlikely(Dependency == 0)) return false; // Fill it in @@ -492,11 +531,17 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, Dep->CompareOp = Op; Dep->ID = Cache.HeaderP->DependsCount++; - // Locate the target package - pkgCache::PkgIterator Pkg; - if (Owner->NewPackage(Pkg,PackageName) == false) + 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) { @@ -504,7 +549,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, if (I->Version != 0 && I.TargetVer() == Version) Dep->Version = I->Version;*/ if (Dep->Version == 0) - if ((Dep->Version = WriteString(Version)) == 0) + if (unlikely((Dep->Version = WriteString(Version)) == 0)) return false; } @@ -524,7 +569,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, } // Is it a file dependency? - if (PackageName[0] == '/') + if (unlikely(PackageName[0] == '/')) FoundFileDeps = true; Dep->NextDepends = *OldDepLast; @@ -544,12 +589,12 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, pkgCache &Cache = Owner->Cache; // We do not add self referencing provides - if (Ver.ParentPkg().Name() == PackageName) + if (unlikely(Ver.ParentPkg().Name() == PackageName)) return true; // Get a structure - unsigned long Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides)); - if (Provides == 0) + unsigned long const Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides)); + if (unlikely(Provides == 0)) return false; Cache.HeaderP->ProvidesCount++; @@ -558,12 +603,12 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, Prv->Version = Ver.Index(); Prv->NextPkgProv = Ver->ProvidesList; Ver->ProvidesList = Prv.Index(); - if (Version.empty() == false && (Prv->ProvideVersion = WriteString(Version)) == 0) + if (Version.empty() == false && unlikely((Prv->ProvideVersion = WriteString(Version)) == 0)) return false; // Locate the target package pkgCache::PkgIterator Pkg; - if (Owner->NewPackage(Pkg,PackageName) == false) + if (unlikely(Owner->NewPackage(Pkg,PackageName,string(Ver.Arch())) == false)) return false; // Link it to the package -- cgit v1.2.3-70-g09d2 From 25396fb06350344996a20d05423562f08a4165db Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 27 Dec 2009 19:39:47 +0100 Subject: Split ListParser::NewDepends into two methods to use these new method for creating the dependencies needed for our groups: For now for all groups only one package can be installed at the same time which conflicts with each other packages in the group. The exceptions are architecture all package. Also, the Multi-Arch field is now parsed, but not used for now. --- apt-pkg/cacheiterators.h | 14 ++++- apt-pkg/deb/deblistparser.cc | 24 ++++++++ apt-pkg/pkgcache.cc | 27 +++++++++ apt-pkg/pkgcache.h | 12 +++- apt-pkg/pkgcachegen.cc | 133 ++++++++++++++++++++++++++++++++----------- apt-pkg/pkgcachegen.h | 6 +- 6 files changed, 176 insertions(+), 40 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') 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 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 { + 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(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 { PkgIterator NextPkg(PkgIterator const &Pkg); // Constructors - inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator(Owner, Trg) { + inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator(Owner, Trg), HashIndex(0) { if (S == 0) S = OwnerPointer(); }; - inline GrpIterator() : Iterator() {}; + inline GrpIterator() : Iterator(), 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 +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 #include #include +#include #include #include #include @@ -38,7 +39,7 @@ typedef vector::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 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::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(); }; -- cgit v1.2.3-70-g09d2 From 8b32e9209ecfab776f064e3c4ccab249307ae49d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Feb 2010 17:42:39 +0100 Subject: Pre-MultiArch a package which depends on a package with architecture "all" can be sure that a package comeing in as a dependency of this package will be of the same architecture as itself (or all). We don't want to break this, so internal an arch all package is represented as many arch depending packages. The only problem we have now is that we only know that a arch all package is installed or not - we don't know for which architecture it was installed: So we will look at all these broken arch all pseudo packages and "remove" them. --- apt-pkg/depcache.cc | 93 +++++++++++++++++++++++++++++++++++++++++++++++--- apt-pkg/depcache.h | 12 ++++--- apt-pkg/pkgcachegen.cc | 16 +++++++-- 3 files changed, 110 insertions(+), 11 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 228750b74..b04181d76 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -596,6 +597,57 @@ void pkgDepCache::UpdateVerState(PkgIterator Pkg) } } /*}}}*/ +// DepCache::RemovePseudoInstalledPkg - MultiArch helper for Update() /*{{{*/ +// --------------------------------------------------------------------- +/* We "install" arch all packages for all archs if it is installed. Many + of these will be broken. This method will look at these broken Pkg and + "remove" it. */ +bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set &recheck) { + if (unlikely(Pkg->CurrentVer == 0)) + return false; + + VerIterator V = Pkg.CurrentVer(); + if (V->MultiArch != Version::All) + return false; + + unsigned char const DepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); + if ((DepState & DepInstMin) == DepInstMin) + return false; + + // Dependencies for this arch all are not statisfied + // so we installed it only for our convenience: get right of it now. + RemoveSizes(Pkg); + RemoveStates(Pkg); + + Pkg->CurrentVer = 0; + PkgState[Pkg->ID].InstallVer = 0; + + AddStates(Pkg); + Update(Pkg); + AddSizes(Pkg); + + // After the remove previously satisfied pseudo pkg could be now + // no longer satisfied, so we need to recheck the reverse dependencies + for (DepIterator d = Pkg.RevDependsList(); d.end() != true; ++d) + { + PkgIterator const P = d.ParentPkg(); + if (P->CurrentVer != 0) + recheck.insert(P.Index()); + } + + if (V.end() != true) + for (PrvIterator Prv = V.ProvidesList(); Prv.end() != true; Prv++) + for (DepIterator d = Prv.ParentPkg().RevDependsList(); + d.end() != true; ++d) + { + PkgIterator const P = d.ParentPkg(); + if (P->CurrentVer != 0) + recheck.insert(P.Index()); + } + + return true; +} + /*}}}*/ // DepCache::Update - Figure out all the state information /*{{{*/ // --------------------------------------------------------------------- /* This will figure out the state of all the packages and all the @@ -609,9 +661,13 @@ void pkgDepCache::Update(OpProgress *Prog) iKeepCount = 0; iBrokenCount = 0; iBadCount = 0; - + + std::set recheck; + // Perform the depends pass int Done = 0; + bool const checkMultiArch = APT::Configuration::getArchitectures().size() > 1; + unsigned long killed = 0; for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++) { if (Prog != 0 && Done%20 == 0) @@ -619,7 +675,7 @@ void pkgDepCache::Update(OpProgress *Prog) for (VerIterator V = I.VersionList(); V.end() != true; V++) { unsigned char Group = 0; - + for (DepIterator D = V.DependsList(); D.end() != true; D++) { // Build the dependency state. @@ -637,16 +693,43 @@ void pkgDepCache::Update(OpProgress *Prog) D->Type == Dep::DpkgBreaks || D->Type == Dep::Obsoletes) State = ~State; - } + } } - // Compute the pacakge dependency state and size additions + // Compute the package dependency state and size additions AddSizes(I); UpdateVerState(I); AddStates(I); + + if (checkMultiArch != true || I->CurrentVer == 0) + continue; + + VerIterator const V = I.CurrentVer(); + if (V->MultiArch != Version::All) + continue; + + recheck.insert(I.Index()); + --Done; // no progress if we need to recheck the package } - if (Prog != 0) + if (checkMultiArch == true) { + /* FIXME: recheck breaks proper progress reporting as we don't know + how many packages we need to recheck. To lower the effect + a bit we increase with a kill, but we should do something more clever… */ + for(std::set::const_iterator p = recheck.begin(); + p != recheck.end(); ++p) { + if (Prog != 0 && Done%20 == 0) + Prog->Progress(Done); + PkgIterator P = PkgIterator(*Cache, Cache->PkgP + *p); + if (RemovePseudoInstalledPkg(P, recheck) == true) { + ++killed; + ++Done; + } + recheck.erase(p); + } + } + + if (Prog != 0) Prog->Progress(Done); readStateFile(Prog); diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 0306861a1..63cd954ad 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -46,6 +46,7 @@ #include #include +#include class pkgDepCache : protected pkgCache::Namespace { @@ -442,9 +443,6 @@ class pkgDepCache : protected pkgCache::Namespace virtual bool IsDeleteOk(const PkgIterator &Pkg,bool Purge = false, unsigned long Depth = 0, bool FromUser = true); - // This is for debuging - void Update(OpProgress *Prog = 0); - // read persistent states bool readStateFile(OpProgress *prog); bool writeStateFile(OpProgress *prog, bool InstalledOnly=false); @@ -460,9 +458,15 @@ class pkgDepCache : protected pkgCache::Namespace inline unsigned long BadCount() {return iBadCount;}; bool Init(OpProgress *Prog); - + // Generate all state information + void Update(OpProgress *Prog = 0); + pkgDepCache(pkgCache *Cache,Policy *Plcy = 0); virtual ~pkgDepCache(); + + private: + // Helper for Update(OpProgress) to remove pseudoinstalled arch all packages + bool RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set &recheck); }; #endif diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 2a4a30349..a4ca9dfe4 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -108,13 +108,24 @@ bool pkgCacheGenerator::MergeList(ListParser &List, unsigned int Counter = 0; while (List.Step() == true) { - // Get a pointer to the package structure string const PackageName = List.Package(); if (PackageName.empty() == true) return false; + /* As we handle Arch all packages as architecture bounded + we add all information to every (simulated) arch package */ + std::vector genArch; + if (List.ArchitectureAll() == true) + genArch = APT::Configuration::getArchitectures(); + else + genArch.push_back(List.Architecture()); + + for (std::vector::const_iterator arch = genArch.begin(); + arch != genArch.end(); ++arch) + { + // Get a pointer to the package structure pkgCache::PkgIterator Pkg; - if (NewPackage(Pkg, PackageName, List.Architecture()) == false) + if (NewPackage(Pkg, PackageName, *arch) == false) return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str()); Counter++; if (Counter % 100 == 0 && Progress != 0) @@ -257,6 +268,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false) return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str()); + } } FoundFileDeps |= List.HasFileDeps(); -- cgit v1.2.3-70-g09d2 From 302578f3b286540a327c822d8be3ccbb4fa47d0a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Feb 2010 21:23:39 +0100 Subject: Create implicit dependencies needed for Multi-Arch handling --- apt-pkg/pkgcachegen.cc | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index a4ca9dfe4..037c0cb63 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -532,11 +532,14 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { 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; + /* MultiArch handling introduces a lot of implicit Dependencies: + - MultiArch: same → Co-Installable if they have the same version + - Architecture: all → Need to be Co-Installable for internal reasons + - All others conflict with all other group members */ + bool const coInstall = (V->MultiArch == pkgCache::Version::All || + V->MultiArch == pkgCache::Version::Same); for (vector::const_iterator A = archs.begin(); A != archs.end(); ++A) { if (*A == Arch) continue; @@ -546,10 +549,24 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { pkgCache::PkgIterator D = G.FindPkg(*A); if (D.end() == true) continue; - // Conflicts: ${self}:other - NewDepends(D, V, "", - pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, - OldDepLast); + if (coInstall == true) { + // Replaces: ${self}:other ( << ${binary:Version}) + NewDepends(D, V, V.VerStr(), + pkgCache::Dep::Less, pkgCache::Dep::Replaces, + OldDepLast); + // Breaks: ${self}:other (!= ${binary:Version}) + NewDepends(D, V, V.VerStr(), + pkgCache::Dep::Less, pkgCache::Dep::DpkgBreaks, + OldDepLast); + NewDepends(D, V, V.VerStr(), + pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks, + OldDepLast); + } else { + // Conflicts: ${self}:other + NewDepends(D, V, "", + pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, + OldDepLast); + } } } } -- cgit v1.2.3-70-g09d2 From 67e0766f0eab85ce1aeacee75fc6b200f36996c9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Feb 2010 22:45:58 +0100 Subject: Foreign Versions add an implicit Provides to the other packages in the group --- apt-pkg/deb/deblistparser.cc | 55 +++++++++++++++++++++++++++++--------------- apt-pkg/pkgcachegen.cc | 7 +++--- apt-pkg/pkgcachegen.h | 4 ++-- 3 files changed, 42 insertions(+), 24 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 26841d3d2..b6082cdd5 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -618,29 +618,46 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) { const char *Start; const char *Stop; - if (Section.Find("Provides",Start,Stop) == false) - return true; - - string Package; - string Version; - unsigned int Op; - - while (1) + if (Section.Find("Provides",Start,Stop) == true) { - Start = ParseDepends(Start,Stop,Package,Version,Op); - if (Start == 0) - return _error->Error("Problem parsing Provides line"); - if (Op != pkgCache::Dep::NoOp) { - _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str()); - } else { - if (NewProvides(Ver,Package,Version) == false) - return false; + string Package; + string Version; + string const Arch = Ver.Arch(); + unsigned int Op; + + while (1) + { + Start = ParseDepends(Start,Stop,Package,Version,Op); + if (Start == 0) + return _error->Error("Problem parsing Provides line"); + if (Op != pkgCache::Dep::NoOp) { + _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str()); + } else { + if (NewProvides(Ver, Package, Arch, Version) == false) + return false; + } + + if (Start == Stop) + break; } + } - if (Start == Stop) - break; + if (Ver->MultiArch != pkgCache::Version::Foreign) + return true; + + std::vector const archs = APT::Configuration::getArchitectures(); + if (archs.size() <= 1) + return true; + + string const Package = Ver.ParentPkg().Name(); + string const Version = Ver.VerStr(); + for (std::vector::const_iterator a = archs.begin(); + a != archs.end(); ++a) + { + if (NewProvides(Ver, Package, *a, Version) == false) + return false; } - + return true; } /*}}}*/ diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 037c0cb63..ebda325f7 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -668,13 +668,14 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, // --------------------------------------------------------------------- /* */ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, - const string &PackageName, + const string &PkgName, + const string &PkgArch, const string &Version) { pkgCache &Cache = Owner->Cache; // We do not add self referencing provides - if (unlikely(Ver.ParentPkg().Name() == PackageName)) + if (Ver.ParentPkg().Name() == PkgName && PkgArch == Ver.Arch()) return true; // Get a structure @@ -693,7 +694,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, // Locate the target package pkgCache::PkgIterator Pkg; - if (unlikely(Owner->NewPackage(Pkg,PackageName,string(Ver.Arch())) == false)) + if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) return false; // Link it to the package diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index ca5d74a9f..46d0cd893 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -104,8 +104,8 @@ class pkgCacheGenerator::ListParser bool NewDepends(pkgCache::VerIterator Ver,const string &Package, const string &Arch, const string &Version,unsigned int Op, unsigned int Type); - bool NewProvides(pkgCache::VerIterator Ver,const string &Package, - const string &Version); + bool NewProvides(pkgCache::VerIterator Ver,const string &PkgName, + const string &PkgArch, const string &Version); public: -- cgit v1.2.3-70-g09d2 From 803ea2a87f81252b2c0d541b8502ed206ce57c84 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Feb 2010 00:04:31 +0100 Subject: Add yet another pseudo package which isn't as pseudo as the others: Arch all packages are now represented by arch depending packages which all depend on a package with the same name and the special arch "all". This packages has NO dependencies, but beside this the same information. It is the only package which has a size, the arch depending ones all have a zero size. While the arch depending pseudo packages are used for dependency resolution the arch "all" package is used for downloading and ordering of the package. --- apt-pkg/algorithms.cc | 52 ++++++++++++++++++++++++++++++++++++++++---- apt-pkg/cacheiterators.h | 1 + apt-pkg/deb/deblistparser.cc | 22 +++++++++++++++++-- apt-pkg/depcache.cc | 4 ++++ apt-pkg/depcache.h | 1 + apt-pkg/orderlist.cc | 4 ++++ apt-pkg/packagemanager.cc | 23 +++++++++++++++----- apt-pkg/pkgcache.cc | 12 ++++++++++ apt-pkg/pkgcache.h | 2 +- apt-pkg/pkgcachegen.cc | 20 +++++++++++++---- cmdline/apt-cache.cc | 2 ++ cmdline/apt-get.cc | 14 +++++++++--- 12 files changed, 137 insertions(+), 20 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 34da745de..c905cffa9 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -83,13 +83,28 @@ void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candid bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) { // Adapt the iterator - PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); + PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); Flags[Pkg->ID] = 1; cout << "Inst "; Describe(Pkg,cout,true,true); Sim.MarkInstall(Pkg,false); - + + if (strcmp(Pkg.Arch(),"all") == 0) + { + pkgCache::GrpIterator G = Pkg.Group(); + pkgCache::GrpIterator iG = iPkg.Group(); + for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (iG.FindPkg(P.Arch())->CurrentVer == 0) + continue; + Flags[P->ID] = 1; + Sim.MarkInstall(P, false); + } + } + // Look for broken conflicts+predepends. for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++) { @@ -131,9 +146,22 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) bool pkgSimulate::Configure(PkgIterator iPkg) { // Adapt the iterator - PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); + PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); Flags[Pkg->ID] = 2; + + if (strcmp(Pkg.Arch(),"all") == 0) + { + pkgCache::GrpIterator G = Pkg.Group(); + for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (Flags[P->ID] == 1) + Flags[P->ID] = 2; + } + } + // Sim.MarkInstall(Pkg,false); if (Sim[Pkg].InstBroken() == true) { @@ -181,10 +209,26 @@ bool pkgSimulate::Configure(PkgIterator iPkg) bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge) { // Adapt the iterator - PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); + PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); Flags[Pkg->ID] = 3; Sim.MarkDelete(Pkg); + + if (strcmp(Pkg.Arch(),"all") == 0) + { + pkgCache::GrpIterator G = Pkg.Group(); + pkgCache::GrpIterator iG = iPkg.Group(); + for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (iG.FindPkg(P.Arch())->CurrentVer == 0) + continue; + Flags[P->ID] = 3; + Sim.MarkDelete(P); + } + } + if (Purge == true) cout << "Purg "; else diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index e8cf28496..43cbe1377 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -200,6 +200,7 @@ class pkgCache::VerIterator : public Iterator { string RelStr(); bool Automatic() const; + bool Pseudo() const; VerFileIterator NewestFile() const; inline VerIterator(pkgCache &Owner,Version *Trg = 0) : Iterator(Owner, Trg) { diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 3726a6a04..b3d95164a 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -148,6 +148,24 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) Ver->Priority = pkgCache::State::Extra; } + if (Ver->MultiArch == pkgCache::Version::All) + { + /* We maintain a "pseudo" arch=all package for architecture all versions + on which these versions can depend on. This pseudo package is many used + for downloading/installing: The other pseudo-packages will degenerate + to a NOP in the download/install step - this package will ensure that + it is downloaded only one time and installed only one time -- even if + the architecture bound versions coming in and out on regular basis. */ + if (strcmp(Ver.Arch(true),"all") == 0) + return true; + else + { + // our pseudo packages have no size to not confuse the fetcher + Ver->Size = 0; + Ver->InstalledSize = 0; + } + } + if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false) return false; if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false) @@ -593,7 +611,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, return true; string Package; - string const pkgArch = Ver.Arch(); + string const pkgArch = Ver.Arch(true); string Version; unsigned int Op; @@ -622,7 +640,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) { string Package; string Version; - string const Arch = Ver.Arch(); + string const Arch = Ver.Arch(true); unsigned int Op; while (1) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index b04181d76..e817adb77 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -896,6 +896,10 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, AddStates(Pkg); Update(Pkg); AddSizes(Pkg); + + // if we remove the pseudo package, we also need to remove the "real" + if (Pkg->CurrentVer != 0 && Pkg.CurrentVer().Pseudo() == true) + MarkDelete(Pkg.Group().FindPkg("all"), rPurge, Depth+1, FromUser); } /*}}}*/ // DepCache::IsDeleteOk - check if it is ok to remove this package /*{{{*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 63cd954ad..ab1021a44 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -333,6 +333,7 @@ class pkgDepCache : protected pkgCache::Namespace inline Header &Head() {return *Cache->HeaderP;}; inline PkgIterator PkgBegin() {return Cache->PkgBegin();}; inline PkgIterator FindPkg(string const &Name) {return Cache->FindPkg(Name);}; + inline PkgIterator FindPkg(string const &Name, string const &Arch) {return Cache->FindPkg(Name, Arch);}; inline pkgCache &GetCache() {return *Cache;}; inline pkgVersioningSystem &VS() {return *Cache->VS;}; diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc index 0ee2e2bc8..2e7618b55 100644 --- a/apt-pkg/orderlist.cc +++ b/apt-pkg/orderlist.cc @@ -126,6 +126,10 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg) if (FileList[Pkg->ID].empty() == false) return false; + + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true) + return false; + return true; } /*}}}*/ diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 1ab3203a1..08e7fc00f 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -80,7 +80,10 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, // Skip already processed packages if (List->IsNow(Pkg) == false) continue; - + + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true) + continue; + new pkgAcqArchive(Owner,Sources,Recs,Cache[Pkg].InstVerIter(Cache), FileNames[Pkg->ID]); } @@ -277,8 +280,10 @@ bool pkgPackageManager::ConfigureAll() for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++) { PkgIterator Pkg(Cache,*I); - - if (ConfigurePkgs == true && Configure(Pkg) == false) + + if (ConfigurePkgs == true && + pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false && + Configure(Pkg) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); @@ -310,7 +315,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) { PkgIterator Pkg(Cache,*I); - if (ConfigurePkgs == true && Configure(Pkg) == false) + if (ConfigurePkgs == true && + pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false && + Configure(Pkg) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); @@ -457,7 +464,10 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg) return true; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); - return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge); + + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false) + return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge); + return true; } /*}}}*/ // PM::SmartUnPack - Install helper /*{{{*/ @@ -565,7 +575,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) P.end() == false; P++) CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); - if (Install(Pkg,FileNames[Pkg->ID]) == false) + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false && + Install(Pkg,FileNames[Pkg->ID]) == false) return false; List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 2d4ee1010..04a2c7234 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -649,6 +649,18 @@ bool pkgCache::VerIterator::Automatic() const 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 +{ + return (S->MultiArch == pkgCache::Version::All && + strcmp(Arch(true),"all") != 0); +} + /*}}}*/ // VerIterator::NewestFile - Return the newest file version relation /*{{{*/ // --------------------------------------------------------------------- /* This looks at the version numbers associated with all of the sources diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 5edeedfd1..012caac76 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -357,7 +357,7 @@ inline pkgCache::PkgFileIterator pkgCache::FileEnd() class pkgCache::Namespace /*{{{*/ { public: - + typedef pkgCache::GrpIterator GrpIterator; typedef pkgCache::PkgIterator PkgIterator; typedef pkgCache::VerIterator VerIterator; typedef pkgCache::DescIterator DescIterator; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index ebda325f7..c1b546a00 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -115,9 +115,10 @@ bool pkgCacheGenerator::MergeList(ListParser &List, /* As we handle Arch all packages as architecture bounded we add all information to every (simulated) arch package */ std::vector genArch; - if (List.ArchitectureAll() == true) + if (List.ArchitectureAll() == true) { genArch = APT::Configuration::getArchitectures(); - else + genArch.push_back("all"); + } else genArch.push_back(List.Architecture()); for (std::vector::const_iterator arch = genArch.begin(); @@ -531,8 +532,11 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { 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)) { + if (strcmp(P.Arch(),"all") == 0) + continue; + pkgCache::PkgIterator allPkg; for (pkgCache::VerIterator V = P.VersionList(); V.end() != true; V++) { - string const Arch = V.Arch(); + string const Arch = V.Arch(true); map_ptrloc *OldDepLast = NULL; /* MultiArch handling introduces a lot of implicit Dependencies: - MultiArch: same → Co-Installable if they have the same version @@ -540,6 +544,8 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { - All others conflict with all other group members */ bool const coInstall = (V->MultiArch == pkgCache::Version::All || V->MultiArch == pkgCache::Version::Same); + if (V->MultiArch == pkgCache::Version::All && allPkg.end() == true) + allPkg = G.FindPkg("all"); for (vector::const_iterator A = archs.begin(); A != archs.end(); ++A) { if (*A == Arch) continue; @@ -561,6 +567,12 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { NewDepends(D, V, V.VerStr(), pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks, OldDepLast); + if (V->MultiArch == pkgCache::Version::All) { + // Depend on ${self}:all which does depend on nothing + NewDepends(allPkg, V, V.VerStr(), + pkgCache::Dep::Equals, pkgCache::Dep::Depends, + OldDepLast); + } } else { // Conflicts: ${self}:other NewDepends(D, V, "", @@ -675,7 +687,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, pkgCache &Cache = Owner->Cache; // We do not add self referencing provides - if (Ver.ParentPkg().Name() == PkgName && PkgArch == Ver.Arch()) + if (Ver.ParentPkg().Name() == PkgName && PkgArch == Ver.Arch(true)) return true; // Get a structure diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index cd806286c..275daa187 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1587,6 +1587,8 @@ bool Policy(CommandLine &CmdL) } for (; Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) { + if (strcmp(Pkg.Arch(),"all") == 0) + continue; if (myArch == Pkg.Arch()) cout << Pkg.Name() << ":" << endl; diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 2597a6acb..93065004c 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -233,7 +233,7 @@ bool ShowList(ostream &out,string Title,string List,string VersionsList) if it is not the main architecture */ string ShowPkg(pkgCache::PkgIterator const Pkg) { string p = Pkg.Name(); - if (_config->Find("APT::Architecture") != Pkg.Arch()) + if (strcmp(Pkg.Arch(),"all") != 0 && _config->Find("APT::Architecture") != Pkg.Arch()) p.append(":").append(Pkg.Arch()); return p; } @@ -385,6 +385,8 @@ void ShowNew(ostream &out,CacheFile &Cache) { pkgCache::PkgIterator I(Cache,Cache.List[J]); if (Cache[I].NewInstall() == true) { + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; List += ShowPkg(I) + " "; VersionsList += string(Cache[I].CandVersion) + "\n"; } @@ -407,6 +409,8 @@ void ShowDel(ostream &out,CacheFile &Cache) pkgCache::PkgIterator I(Cache,Cache.List[J]); if (Cache[I].Delete() == true) { + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) List += ShowPkg(I) + "* "; else @@ -455,7 +459,9 @@ void ShowUpgraded(ostream &out,CacheFile &Cache) // Not interesting if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) continue; - + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; + List += ShowPkg(I) + " "; VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; } @@ -476,7 +482,9 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache) // Not interesting if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) continue; - + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; + List += ShowPkg(I) + " "; VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; } -- cgit v1.2.3-70-g09d2 From 42d71ab5fe58953a680bd300a99d173e23430d7c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Feb 2010 17:17:16 +0100 Subject: In SingleArch environments we don't need the arch "all" pseudo package for handling arch:all packages, so we create only one package and stop calling it a pseudo package. --- apt-pkg/deb/deblistparser.cc | 2 +- apt-pkg/pkgcache.cc | 9 +++++++-- apt-pkg/pkgcachegen.cc | 3 ++- cmdline/apt-get.cc | 3 +++ 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'apt-pkg/pkgcachegen.cc') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index b3d95164a..1948aedf3 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -158,7 +158,7 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) the architecture bound versions coming in and out on regular basis. */ if (strcmp(Ver.Arch(true),"all") == 0) return true; - else + else if (Ver.Pseudo() == true) { // our pseudo packages have no size to not confuse the fetcher Ver->Size = 0; diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 04a2c7234..d4268b31c 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -657,8 +657,13 @@ bool pkgCache::VerIterator::Automatic() const are a problem everytime we need to download/install something. */ bool pkgCache::VerIterator::Pseudo() const { - return (S->MultiArch == pkgCache::Version::All && - strcmp(Arch(true),"all") != 0); + 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 /*{{{*/ diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index c1b546a00..6d103c6b6 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -117,7 +117,8 @@ bool pkgCacheGenerator::MergeList(ListParser &List, std::vector genArch; if (List.ArchitectureAll() == true) { genArch = APT::Configuration::getArchitectures(); - genArch.push_back("all"); + if (genArch.size() != 1) + genArch.push_back("all"); } else genArch.push_back(List.Architecture()); diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 93065004c..343226bc3 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -585,6 +585,9 @@ void Stats(ostream &out,pkgDepCache &Dep) unsigned long ReInstall = 0; for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++) { + if (pkgCache::VerIterator(Dep, Dep[I].CandidateVer).Pseudo() == true) + continue; + if (Dep[I].NewInstall() == true) Install++; else -- cgit v1.2.3-70-g09d2