From 773e2c1fe5fd1a315ffaaf79f2f2e4a9e975649a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 9 Dec 2009 19:24:03 +0100 Subject: Refactor the cache iterators by using a common base class This should not change the public interface, but it removes the friend connection between the iterators and pkgcache as it is unused. --- apt-pkg/cacheiterators.h | 673 +++++++++++++++++++++-------------------------- apt-pkg/pkgcache.cc | 56 ++-- apt-pkg/pkgcache.h | 9 +- 3 files changed, 320 insertions(+), 418 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 28466cd40..1da5c6f02 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: cacheiterators.h,v 1.18.2.1 2004/05/08 22:44:27 mdz Exp $ /* ###################################################################### Cache Iterators - Iterators for navigating the cache structure @@ -30,417 +29,333 @@ /*}}}*/ #ifndef PKGLIB_CACHEITERATORS_H #define PKGLIB_CACHEITERATORS_H - - +// abstract Iterator template /*{{{*/ +/* This template provides the very basic iterator methods we + need to have for doing some walk-over-the-cache magic, */ +template class pkgCache::Iterator { + __attribute__ ((deprecated)) void _dummy(); // FIXME: Who on earth uses this method ??? + + protected: + Str *S; + pkgCache *Owner; + + /** \brief Returns the Pointer for this struct in the owner + * The implementation of this method should be pretty short + * as it will only return the Pointer into the mmap stored + * in the owner but the name of this pointer is different for + * each stucture and we want to abstract here at least for the + * basic methods from the actual structure. + * \return Pointer to the first structure of this type + */ + virtual Str* OwnerPointer() const = 0; + + public: + // Iteration + virtual void operator ++(int) = 0; + virtual void operator ++() = 0; // Should be {operator ++(0);}; + inline bool end() const {return Owner == 0 || S == OwnerPointer();}; + + // Comparison + inline bool operator ==(const Itr &B) const {return S == B.S;}; + inline bool operator !=(const Itr &B) const {return S != B.S;}; + + // Accessors + inline Str *operator ->() {return S;}; + inline Str const *operator ->() const {return S;}; + inline operator Str *() {return S == OwnerPointer() ? 0 : S;}; + inline operator Str const *() const {return S == OwnerPointer() ? 0 : S;}; + inline Str const &operator *() const {return *S;}; + inline pkgCache *Cache() {return Owner;}; + + // Mixed stuff + inline void operator =(const Itr &B) {S = B.S; Owner = B.Owner;}; + inline bool IsGood() const { return S && Owner && ! end();}; + inline unsigned long Index() const {return S - OwnerPointer();}; + + // Constructors - look out for the variable assigning + inline Iterator() : S(0), Owner(0) {}; + inline Iterator(pkgCache &Owner,Str *T = 0) : S(T), Owner(&Owner) {}; +}; + /*}}}*/ // Package Iterator /*{{{*/ -class pkgCache::PkgIterator -{ - friend class pkgCache; - Package *Pkg; - pkgCache *Owner; - long HashIndex; - - protected: - - // This constructor is the 'begin' constructor, never use it. - inline PkgIterator(pkgCache &Owner) : Owner(&Owner), HashIndex(-1) - { - Pkg = Owner.PkgP; - operator ++(0); - }; - - public: - - enum OkState {NeedsNothing,NeedsUnpack,NeedsConfigure}; - - // Iteration - void operator ++(int); - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || Pkg == Owner->PkgP?true:false;}; - - // Comparison - inline bool operator ==(const PkgIterator &B) const {return Pkg == B.Pkg;}; - inline bool operator !=(const PkgIterator &B) const {return Pkg != B.Pkg;}; - - // Accessors - inline Package *operator ->() {return Pkg;}; - inline Package const *operator ->() const {return Pkg;}; - inline Package const &operator *() const {return *Pkg;}; - inline operator Package *() {return Pkg == Owner->PkgP?0:Pkg;}; - inline operator Package const *() const {return Pkg == Owner->PkgP?0:Pkg;}; - inline pkgCache *Cache() {return Owner;}; - - inline const char *Name() const {return Pkg->Name == 0?0:Owner->StrP + Pkg->Name;}; - inline const char *Section() const {return Pkg->Section == 0?0:Owner->StrP + Pkg->Section;}; - inline bool Purge() const {return Pkg->CurrentState == pkgCache::State::Purge || - (Pkg->CurrentVer == 0 && Pkg->CurrentState == pkgCache::State::NotInstalled);}; - inline VerIterator VersionList() const; - inline VerIterator CurrentVer() const; - inline DepIterator RevDependsList() const; - inline PrvIterator ProvidesList() const; - inline unsigned long Index() const {return Pkg - Owner->PkgP;}; - OkState State() const; - - //Nice printable representation - friend std::ostream& operator<<(std::ostream& out, pkgCache::PkgIterator Pkg); - - const char *CandVersion() const; - const char *CurVersion() const; - - // Constructors - inline PkgIterator(pkgCache &Owner,Package *Trg) : Pkg(Trg), Owner(&Owner), - HashIndex(0) - { - if (Pkg == 0) - Pkg = Owner.PkgP; - }; - inline PkgIterator() : Pkg(0), Owner(0), HashIndex(0) {}; +class pkgCache::PkgIterator: public Iterator { + long HashIndex; + + protected: + inline Package* OwnerPointer() const { + return Owner->PkgP; + }; + + public: + // This constructor is the 'begin' constructor, never use it. + inline PkgIterator(pkgCache &Owner) : Iterator(Owner), HashIndex(-1) { + S = OwnerPointer(); + operator ++(0); + }; + + virtual void operator ++(int); + virtual void operator ++() {operator ++(0);}; + + enum OkState {NeedsNothing,NeedsUnpack,NeedsConfigure}; + + // Accessors + inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;}; + inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}; + inline bool Purge() const {return S->CurrentState == pkgCache::State::Purge || + (S->CurrentVer == 0 && S->CurrentState == pkgCache::State::NotInstalled);}; + + inline VerIterator VersionList() const; + inline VerIterator CurrentVer() const; + inline DepIterator RevDependsList() const; + inline PrvIterator ProvidesList() const; + OkState State() const; + const char *CandVersion() const; + const char *CurVersion() const; + + //Nice printable representation + friend std::ostream& operator <<(std::ostream& out, PkgIterator i); + + // Constructors + inline PkgIterator(pkgCache &Owner,Package *Trg) : Iterator(Owner, Trg), HashIndex(0) { + if (S == 0) + S = OwnerPointer(); + }; + inline PkgIterator() : Iterator(), HashIndex(0) {}; }; /*}}}*/ // Version Iterator /*{{{*/ -class pkgCache::VerIterator -{ - Version *Ver; - pkgCache *Owner; - - void _dummy(); - - public: - - // Iteration - void operator ++(int) {if (Ver != Owner->VerP) Ver = Owner->VerP + Ver->NextVer;}; - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || (Ver == Owner->VerP?true:false);}; - inline void operator =(const VerIterator &B) {Ver = B.Ver; Owner = B.Owner;}; - - // Comparison - inline bool operator ==(const VerIterator &B) const {return Ver == B.Ver;}; - inline bool operator !=(const VerIterator &B) const {return Ver != B.Ver;}; - int CompareVer(const VerIterator &B) const; - - // Testing - inline bool IsGood() const { return Ver && Owner && ! end();}; - - // Accessors - inline Version *operator ->() {return Ver;}; - inline Version const *operator ->() const {return Ver;}; - inline Version &operator *() {return *Ver;}; - inline Version const &operator *() const {return *Ver;}; - inline operator Version *() {return Ver == Owner->VerP?0:Ver;}; - inline operator Version const *() const {return Ver == Owner->VerP?0:Ver;}; - inline pkgCache *Cache() {return Owner;}; - - inline const char *VerStr() const {return Ver->VerStr == 0?0:Owner->StrP + Ver->VerStr;}; - inline const char *Section() const {return Ver->Section == 0?0:Owner->StrP + Ver->Section;}; - inline const char *Arch() const {return Ver->Arch == 0?0:Owner->StrP + Ver->Arch;}; - inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Ver->ParentPkg);}; - inline DescIterator DescriptionList() const; - DescIterator TranslatedDescription() const; - inline DepIterator DependsList() const; - inline PrvIterator ProvidesList() const; - inline VerFileIterator FileList() const; - inline unsigned long Index() const {return Ver - Owner->VerP;}; - bool Downloadable() const; - inline const char *PriorityType() {return Owner->Priority(Ver->Priority);}; - string RelStr(); - - bool Automatic() const; - VerFileIterator NewestFile() const; - - inline VerIterator() : Ver(0), Owner(0) {}; - inline VerIterator(pkgCache &Owner,Version *Trg = 0) : Ver(Trg), - Owner(&Owner) - { - if (Ver == 0) - Ver = Owner.VerP; - }; +class pkgCache::VerIterator : public Iterator { + protected: + inline Version* OwnerPointer() const { + return Owner->VerP; + }; + + public: + // Iteration + void operator ++(int) {if (S != Owner->VerP) S = Owner->VerP + S->NextVer;}; + inline void operator ++() {operator ++(0);}; + + // Comparison + int CompareVer(const VerIterator &B) const; + + // Accessors + inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}; + inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}; + inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;}; + inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}; + + inline DescIterator DescriptionList() const; + DescIterator TranslatedDescription() const; + inline DepIterator DependsList() const; + inline PrvIterator ProvidesList() const; + inline VerFileIterator FileList() const; + bool Downloadable() const; + inline const char *PriorityType() {return Owner->Priority(S->Priority);}; + string RelStr(); + + bool Automatic() const; + VerFileIterator NewestFile() const; + + inline VerIterator(pkgCache &Owner,Version *Trg = 0) : Iterator(Owner, Trg) { + if (S == 0) + S = OwnerPointer(); + }; + inline VerIterator() : Iterator() {}; }; /*}}}*/ // Description Iterator /*{{{*/ -class pkgCache::DescIterator -{ - Description *Desc; - pkgCache *Owner; - - void _dummy(); - - public: - - // Iteration - void operator ++(int) {if (Desc != Owner->DescP) Desc = Owner->DescP + Desc->NextDesc;}; - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || Desc == Owner->DescP?true:false;}; - inline void operator =(const DescIterator &B) {Desc = B.Desc; Owner = B.Owner;}; - - // Comparison - inline bool operator ==(const DescIterator &B) const {return Desc == B.Desc;}; - inline bool operator !=(const DescIterator &B) const {return Desc != B.Desc;}; - int CompareDesc(const DescIterator &B) const; - - // Accessors - inline Description *operator ->() {return Desc;}; - inline Description const *operator ->() const {return Desc;}; - inline Description &operator *() {return *Desc;}; - inline Description const &operator *() const {return *Desc;}; - inline operator Description *() {return Desc == Owner->DescP?0:Desc;}; - inline operator Description const *() const {return Desc == Owner->DescP?0:Desc;}; - inline pkgCache *Cache() {return Owner;}; - - inline const char *LanguageCode() const {return Owner->StrP + Desc->language_code;}; - inline const char *md5() const {return Owner->StrP + Desc->md5sum;}; - inline DescFileIterator FileList() const; - inline unsigned long Index() const {return Desc - Owner->DescP;}; - - inline DescIterator() : Desc(0), Owner(0) {}; - inline DescIterator(pkgCache &Owner,Description *Trg = 0) : Desc(Trg), - Owner(&Owner) - { - if (Desc == 0) - Desc = Owner.DescP; - }; +class pkgCache::DescIterator : public Iterator { + protected: + inline Description* OwnerPointer() const { + return Owner->DescP; + }; + + public: + // Iteration + void operator ++(int) {if (S != Owner->DescP) S = Owner->DescP + S->NextDesc;}; + inline void operator ++() {operator ++(0);}; + + // Comparison + int CompareDesc(const DescIterator &B) const; + + // Accessors + inline const char *LanguageCode() const {return Owner->StrP + S->language_code;}; + inline const char *md5() const {return Owner->StrP + S->md5sum;}; + inline DescFileIterator FileList() const; + + inline DescIterator() : Iterator() {}; + inline DescIterator(pkgCache &Owner,Description *Trg = 0) : Iterator(Owner, Trg) { + if (S == 0) + S = Owner.DescP; + }; }; /*}}}*/ // Dependency iterator /*{{{*/ -class pkgCache::DepIterator -{ - Dependency *Dep; - enum {DepVer, DepRev} Type; - pkgCache *Owner; - - void _dummy(); - - public: - - // Iteration - void operator ++(int) {if (Dep != Owner->DepP) Dep = Owner->DepP + - (Type == DepVer?Dep->NextDepends:Dep->NextRevDepends);}; - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || Dep == Owner->DepP?true:false;}; - - // Comparison - inline bool operator ==(const DepIterator &B) const {return Dep == B.Dep;}; - inline bool operator !=(const DepIterator &B) const {return Dep != B.Dep;}; - - // Accessors - inline Dependency *operator ->() {return Dep;}; - inline Dependency const *operator ->() const {return Dep;}; - inline Dependency &operator *() {return *Dep;}; - inline Dependency const &operator *() const {return *Dep;}; - inline operator Dependency *() {return Dep == Owner->DepP?0:Dep;}; - inline operator Dependency const *() const {return Dep == Owner->DepP?0:Dep;}; - inline pkgCache *Cache() {return Owner;}; - - inline const char *TargetVer() const {return Dep->Version == 0?0:Owner->StrP + Dep->Version;}; - inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + Dep->Package);}; - inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;}; - inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + Dep->ParentVer);}; - inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Dep->ParentVer].ParentPkg);}; - inline bool Reverse() {return Type == DepRev;}; - inline unsigned long Index() const {return Dep - Owner->DepP;}; - bool IsCritical(); - void GlobOr(DepIterator &Start,DepIterator &End); - Version **AllTargets(); - bool SmartTargetPkg(PkgIterator &Result); - inline const char *CompType() {return Owner->CompType(Dep->CompareOp);}; - inline const char *DepType() {return Owner->DepType(Dep->Type);}; - - inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) : - Dep(Trg), Type(DepVer), Owner(&Owner) - { - if (Dep == 0) - Dep = Owner.DepP; - }; - inline DepIterator(pkgCache &Owner,Dependency *Trg,Package *) : - Dep(Trg), Type(DepRev), Owner(&Owner) - { - if (Dep == 0) - Dep = Owner.DepP; - }; - inline DepIterator() : Dep(0), Type(DepVer), Owner(0) {}; +class pkgCache::DepIterator : public Iterator { + enum {DepVer, DepRev} Type; + + protected: + inline Dependency* OwnerPointer() const { + return Owner->DepP; + }; + + public: + // Iteration + void operator ++(int) {if (S != Owner->DepP) S = Owner->DepP + + (Type == DepVer ? S->NextDepends : S->NextRevDepends);}; + inline void operator ++() {operator ++(0);}; + + // Accessors + inline const char *TargetVer() const {return S->Version == 0?0:Owner->StrP + S->Version;}; + inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + S->Package);}; + inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;}; + inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + S->ParentVer);}; + inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);}; + inline bool Reverse() {return Type == DepRev;}; + bool IsCritical(); + void GlobOr(DepIterator &Start,DepIterator &End); + Version **AllTargets(); + bool SmartTargetPkg(PkgIterator &Result); + inline const char *CompType() {return Owner->CompType(S->CompareOp);}; + inline const char *DepType() {return Owner->DepType(S->Type);}; + + inline DepIterator(pkgCache &Owner, Dependency *Trg, Version* = 0) : + Iterator(Owner, Trg), Type(DepVer) { + if (S == 0) + S = Owner.DepP; + }; + inline DepIterator(pkgCache &Owner, Dependency *Trg, Package*) : + Iterator(Owner, Trg), Type(DepRev) { + if (S == 0) + S = Owner.DepP; + }; + inline DepIterator() : Iterator(), Type(DepVer) {}; }; /*}}}*/ // Provides iterator /*{{{*/ -class pkgCache::PrvIterator -{ - Provides *Prv; - enum {PrvVer, PrvPkg} Type; - pkgCache *Owner; - - void _dummy(); - - public: - - // Iteration - void operator ++(int) {if (Prv != Owner->ProvideP) Prv = Owner->ProvideP + - (Type == PrvVer?Prv->NextPkgProv:Prv->NextProvides);}; - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || Prv == Owner->ProvideP?true:false;}; - - // Comparison - inline bool operator ==(const PrvIterator &B) const {return Prv == B.Prv;}; - inline bool operator !=(const PrvIterator &B) const {return Prv != B.Prv;}; - - // Accessors - inline Provides *operator ->() {return Prv;}; - inline Provides const *operator ->() const {return Prv;}; - inline Provides &operator *() {return *Prv;}; - inline Provides const &operator *() const {return *Prv;}; - inline operator Provides *() {return Prv == Owner->ProvideP?0:Prv;}; - inline operator Provides const *() const {return Prv == Owner->ProvideP?0:Prv;}; - inline pkgCache *Cache() {return Owner;}; - - inline const char *Name() const {return Owner->StrP + Owner->PkgP[Prv->ParentPkg].Name;}; - inline const char *ProvideVersion() const {return Prv->ProvideVersion == 0?0:Owner->StrP + Prv->ProvideVersion;}; - inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Prv->ParentPkg);}; - inline VerIterator OwnerVer() {return VerIterator(*Owner,Owner->VerP + Prv->Version);}; - inline PkgIterator OwnerPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);}; - inline unsigned long Index() const {return Prv - Owner->ProvideP;}; - - inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0) {}; - - inline PrvIterator(pkgCache &Owner,Provides *Trg,Version *) : - Prv(Trg), Type(PrvVer), Owner(&Owner) - { - if (Prv == 0) - Prv = Owner.ProvideP; - }; - inline PrvIterator(pkgCache &Owner,Provides *Trg,Package *) : - Prv(Trg), Type(PrvPkg), Owner(&Owner) - { - if (Prv == 0) - Prv = Owner.ProvideP; - }; +class pkgCache::PrvIterator : public Iterator { + enum {PrvVer, PrvPkg} Type; + + protected: + inline Provides* OwnerPointer() const { + return Owner->ProvideP; + }; + + public: + // Iteration + void operator ++(int) {if (S != Owner->ProvideP) S = Owner->ProvideP + + (Type == PrvVer?S->NextPkgProv:S->NextProvides);}; + inline void operator ++() {operator ++(0);}; + + // Accessors + inline const char *Name() const {return Owner->StrP + Owner->PkgP[S->ParentPkg].Name;}; + inline const char *ProvideVersion() const {return S->ProvideVersion == 0?0:Owner->StrP + S->ProvideVersion;}; + inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}; + inline VerIterator OwnerVer() {return VerIterator(*Owner,Owner->VerP + S->Version);}; + inline PkgIterator OwnerPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);}; + + inline PrvIterator() : Iterator(), Type(PrvVer) {}; + + inline PrvIterator(pkgCache &Owner, Provides *Trg, Version*) : + Iterator(Owner, Trg), Type(PrvVer) { + if (S == 0) + S = Owner.ProvideP; + }; + inline PrvIterator(pkgCache &Owner, Provides *Trg, Package*) : + Iterator(Owner, Trg), Type(PrvPkg) { + if (S == 0) + S = Owner.ProvideP; + }; }; /*}}}*/ // Package file /*{{{*/ -class pkgCache::PkgFileIterator -{ - pkgCache *Owner; - PackageFile *File; - - public: - - // Iteration - void operator ++(int) {if (File!= Owner->PkgFileP) File = Owner->PkgFileP + File->NextFile;}; - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || File == Owner->PkgFileP?true:false;}; - - // Comparison - inline bool operator ==(const PkgFileIterator &B) const {return File == B.File;}; - inline bool operator !=(const PkgFileIterator &B) const {return File != B.File;}; - - // Accessors - inline PackageFile *operator ->() {return File;}; - inline PackageFile const *operator ->() const {return File;}; - inline PackageFile const &operator *() const {return *File;}; - inline operator PackageFile *() {return File == Owner->PkgFileP?0:File;}; - inline operator PackageFile const *() const {return File == Owner->PkgFileP?0:File;}; - inline pkgCache *Cache() {return Owner;}; - - inline const char *FileName() const {return File->FileName == 0?0:Owner->StrP + File->FileName;}; - inline const char *Archive() const {return File->Archive == 0?0:Owner->StrP + File->Archive;}; - inline const char *Component() const {return File->Component == 0?0:Owner->StrP + File->Component;}; - inline const char *Version() const {return File->Version == 0?0:Owner->StrP + File->Version;}; - inline const char *Origin() const {return File->Origin == 0?0:Owner->StrP + File->Origin;}; - inline const char *Codename() const {return File->Codename ==0?0:Owner->StrP + File->Codename;}; - inline const char *Label() const {return File->Label == 0?0:Owner->StrP + File->Label;}; - inline const char *Site() const {return File->Site == 0?0:Owner->StrP + File->Site;}; - inline const char *Architecture() const {return File->Architecture == 0?0:Owner->StrP + File->Architecture;}; - inline const char *IndexType() const {return File->IndexType == 0?0:Owner->StrP + File->IndexType;}; - - inline unsigned long Index() const {return File - Owner->PkgFileP;}; - - bool IsOk(); - string RelStr(); - - // Constructors - inline PkgFileIterator() : Owner(0), File(0) {}; - inline PkgFileIterator(pkgCache &Owner) : Owner(&Owner), File(Owner.PkgFileP) {}; - inline PkgFileIterator(pkgCache &Owner,PackageFile *Trg) : Owner(&Owner), File(Trg) {}; +class pkgCache::PkgFileIterator : public Iterator { + protected: + inline PackageFile* OwnerPointer() const { + return Owner->PkgFileP; + }; + + public: + // Iteration + void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;}; + inline void operator ++() {operator ++(0);}; + + // Accessors + inline const char *FileName() const {return S->FileName == 0?0:Owner->StrP + S->FileName;}; + inline const char *Archive() const {return S->Archive == 0?0:Owner->StrP + S->Archive;}; + inline const char *Component() const {return S->Component == 0?0:Owner->StrP + S->Component;}; + inline const char *Version() const {return S->Version == 0?0:Owner->StrP + S->Version;}; + inline const char *Origin() const {return S->Origin == 0?0:Owner->StrP + S->Origin;}; + inline const char *Codename() const {return S->Codename ==0?0:Owner->StrP + S->Codename;}; + inline const char *Label() const {return S->Label == 0?0:Owner->StrP + S->Label;}; + inline const char *Site() const {return S->Site == 0?0:Owner->StrP + S->Site;}; + inline const char *Architecture() const {return S->Architecture == 0?0:Owner->StrP + S->Architecture;}; + inline const char *IndexType() const {return S->IndexType == 0?0:Owner->StrP + S->IndexType;}; + + bool IsOk(); + string RelStr(); + + // Constructors + inline PkgFileIterator() : Iterator() {}; + inline PkgFileIterator(pkgCache &Owner,PackageFile *Trg = 0) : Iterator(Owner, Trg) {}; }; /*}}}*/ // Version File /*{{{*/ -class pkgCache::VerFileIterator -{ - pkgCache *Owner; - VerFile *FileP; - - public: - - // Iteration - void operator ++(int) {if (FileP != Owner->VerFileP) FileP = Owner->VerFileP + FileP->NextFile;}; - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || FileP == Owner->VerFileP?true:false;}; - - // Comparison - inline bool operator ==(const VerFileIterator &B) const {return FileP == B.FileP;}; - inline bool operator !=(const VerFileIterator &B) const {return FileP != B.FileP;}; - - // Accessors - inline VerFile *operator ->() {return FileP;}; - inline VerFile const *operator ->() const {return FileP;}; - inline VerFile const &operator *() const {return *FileP;}; - inline operator VerFile *() {return FileP == Owner->VerFileP?0:FileP;}; - inline operator VerFile const *() const {return FileP == Owner->VerFileP?0:FileP;}; - inline pkgCache *Cache() {return Owner;}; - - inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);}; - inline unsigned long Index() const {return FileP - Owner->VerFileP;}; - - inline VerFileIterator() : Owner(0), FileP(0) {}; - inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(Trg) {}; +class pkgCache::VerFileIterator : public pkgCache::Iterator { + protected: + inline VerFile* OwnerPointer() const { + return Owner->VerFileP; + }; + + public: + // Iteration + void operator ++(int) {if (S != Owner->VerFileP) S = Owner->VerFileP + S->NextFile;}; + inline void operator ++() {operator ++(0);}; + + // Accessors + inline PkgFileIterator File() const {return PkgFileIterator(*Owner,S->File + Owner->PkgFileP);}; + + inline VerFileIterator() : Iterator() {}; + inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Iterator(Owner, Trg) {}; }; /*}}}*/ // Description File /*{{{*/ -class pkgCache::DescFileIterator -{ - pkgCache *Owner; - DescFile *FileP; - - public: - - // Iteration - void operator ++(int) {if (FileP != Owner->DescFileP) FileP = Owner->DescFileP + FileP->NextFile;}; - inline void operator ++() {operator ++(0);}; - inline bool end() const {return Owner == 0 || FileP == Owner->DescFileP?true:false;}; - - // Comparison - inline bool operator ==(const DescFileIterator &B) const {return FileP == B.FileP;}; - inline bool operator !=(const DescFileIterator &B) const {return FileP != B.FileP;}; - - // Accessors - inline DescFile *operator ->() {return FileP;}; - inline DescFile const *operator ->() const {return FileP;}; - inline DescFile const &operator *() const {return *FileP;}; - inline operator DescFile *() {return FileP == Owner->DescFileP?0:FileP;}; - inline operator DescFile const *() const {return FileP == Owner->DescFileP?0:FileP;}; - inline pkgCache *Cache() {return Owner;}; - - inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);}; - inline unsigned long Index() const {return FileP - Owner->DescFileP;}; - - inline DescFileIterator() : Owner(0), FileP(0) {}; - inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Owner(&Owner), FileP(Trg) {}; +class pkgCache::DescFileIterator : public Iterator { + protected: + inline DescFile* OwnerPointer() const { + return Owner->DescFileP; + }; + + public: + // Iteration + void operator ++(int) {if (S != Owner->DescFileP) S = Owner->DescFileP + S->NextFile;}; + inline void operator ++() {operator ++(0);}; + + // Accessors + inline PkgFileIterator File() const {return PkgFileIterator(*Owner,S->File + Owner->PkgFileP);}; + + inline DescFileIterator() : Iterator() {}; + inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Iterator(Owner, Trg) {}; }; /*}}}*/ // Inlined Begin functions cant be in the class because of order problems /*{{{*/ inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const - {return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);}; + {return VerIterator(*Owner,Owner->VerP + S->VersionList);}; inline pkgCache::VerIterator pkgCache::PkgIterator::CurrentVer() const - {return VerIterator(*Owner,Owner->VerP + Pkg->CurrentVer);}; + {return VerIterator(*Owner,Owner->VerP + S->CurrentVer);}; inline pkgCache::DepIterator pkgCache::PkgIterator::RevDependsList() const - {return DepIterator(*Owner,Owner->DepP + Pkg->RevDepends,Pkg);}; + {return DepIterator(*Owner,Owner->DepP + S->RevDepends,S);}; inline pkgCache::PrvIterator pkgCache::PkgIterator::ProvidesList() const - {return PrvIterator(*Owner,Owner->ProvideP + Pkg->ProvidesList,Pkg);}; + {return PrvIterator(*Owner,Owner->ProvideP + S->ProvidesList,S);}; inline pkgCache::DescIterator pkgCache::VerIterator::DescriptionList() const - {return DescIterator(*Owner,Owner->DescP + Ver->DescriptionList);}; + {return DescIterator(*Owner,Owner->DescP + S->DescriptionList);}; inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const - {return PrvIterator(*Owner,Owner->ProvideP + Ver->ProvidesList,Ver);}; + {return PrvIterator(*Owner,Owner->ProvideP + S->ProvidesList,S);}; inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const - {return DepIterator(*Owner,Owner->DepP + Ver->DependsList,Ver);}; + {return DepIterator(*Owner,Owner->DepP + S->DependsList,S);}; inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const - {return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);}; + {return VerFileIterator(*Owner,Owner->VerFileP + S->FileList);}; inline pkgCache::DescFileIterator pkgCache::DescIterator::FileList() const - {return DescFileIterator(*Owner,Owner->DescFileP + Desc->FileList);}; + {return DescFileIterator(*Owner,Owner->DescFileP + S->FileList);}; /*}}}*/ #endif diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 997ff51fe..2f8bde6f7 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -242,26 +242,20 @@ const char *pkgCache::Priority(unsigned char Prio) return 0; } /*}}}*/ -// Bases for iterator classes /*{{{*/ -void pkgCache::VerIterator::_dummy() {} -void pkgCache::DepIterator::_dummy() {} -void pkgCache::PrvIterator::_dummy() {} -void pkgCache::DescIterator::_dummy() {} - /*}}}*/ // PkgIterator::operator ++ - Postfix incr /*{{{*/ // --------------------------------------------------------------------- /* This will advance to the next logical package in the hash table. */ void pkgCache::PkgIterator::operator ++(int) { // Follow the current links - if (Pkg != Owner->PkgP) - Pkg = Owner->PkgP + Pkg->NextPackage; + if (S != Owner->PkgP) + S = Owner->PkgP + S->NextPackage; // Follow the hash table - while (Pkg == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->HashTable)) + while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->HashTable)) { HashIndex++; - Pkg = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex]; + S = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex]; } }; /*}}}*/ @@ -270,12 +264,12 @@ void pkgCache::PkgIterator::operator ++(int) /* By this we mean if it is either cleanly installed or cleanly removed. */ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const { - if (Pkg->InstState == pkgCache::State::ReInstReq || - Pkg->InstState == pkgCache::State::HoldReInstReq) + if (S->InstState == pkgCache::State::ReInstReq || + S->InstState == pkgCache::State::HoldReInstReq) return NeedsUnpack; - if (Pkg->CurrentState == pkgCache::State::UnPacked || - Pkg->CurrentState == pkgCache::State::HalfConfigured) + if (S->CurrentState == pkgCache::State::UnPacked || + S->CurrentState == pkgCache::State::HalfConfigured) // we leave triggers alone complettely. dpkg deals with // them in a hard-to-predict manner and if they get // resolved by dpkg before apt run dpkg --configure on @@ -284,8 +278,8 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const //Pkg->CurrentState == pkgCache::State::TriggersPending) return NeedsConfigure; - if (Pkg->CurrentState == pkgCache::State::HalfInstalled || - Pkg->InstState != pkgCache::State::Ok) + if (S->CurrentState == pkgCache::State::HalfInstalled || + S->InstState != pkgCache::State::Ok) return NeedsUnpack; return NeedsNothing; @@ -347,11 +341,11 @@ operator<<(ostream& out, pkgCache::PkgIterator Pkg) conflicts (including dpkg's Breaks fields). */ bool pkgCache::DepIterator::IsCritical() { - if (Dep->Type == pkgCache::Dep::Conflicts || - Dep->Type == pkgCache::Dep::DpkgBreaks || - Dep->Type == pkgCache::Dep::Obsoletes || - Dep->Type == pkgCache::Dep::Depends || - Dep->Type == pkgCache::Dep::PreDepends) + if (S->Type == pkgCache::Dep::Conflicts || + S->Type == pkgCache::Dep::DpkgBreaks || + S->Type == pkgCache::Dep::Obsoletes || + S->Type == pkgCache::Dep::Depends || + S->Type == pkgCache::Dep::PreDepends) return true; return false; } @@ -430,12 +424,12 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets() // Walk along the actual package providing versions for (VerIterator I = DPkg.VersionList(); I.end() == false; I++) { - if (Owner->VS->CheckDep(I.VerStr(),Dep->CompareOp,TargetVer()) == false) + if (Owner->VS->CheckDep(I.VerStr(),S->CompareOp,TargetVer()) == false) continue; - if ((Dep->Type == pkgCache::Dep::Conflicts || - Dep->Type == pkgCache::Dep::DpkgBreaks || - Dep->Type == pkgCache::Dep::Obsoletes) && + if ((S->Type == pkgCache::Dep::Conflicts || + S->Type == pkgCache::Dep::DpkgBreaks || + S->Type == pkgCache::Dep::Obsoletes) && ParentPkg() == I.ParentPkg()) continue; @@ -447,12 +441,12 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets() // Follow all provides for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++) { - if (Owner->VS->CheckDep(I.ProvideVersion(),Dep->CompareOp,TargetVer()) == false) + if (Owner->VS->CheckDep(I.ProvideVersion(),S->CompareOp,TargetVer()) == false) continue; - if ((Dep->Type == pkgCache::Dep::Conflicts || - Dep->Type == pkgCache::Dep::DpkgBreaks || - Dep->Type == pkgCache::Dep::Obsoletes) && + if ((S->Type == pkgCache::Dep::Conflicts || + S->Type == pkgCache::Dep::DpkgBreaks || + S->Type == pkgCache::Dep::Obsoletes) && ParentPkg() == I.OwnerPkg()) continue; @@ -490,7 +484,7 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End) End = *this; for (bool LastOR = true; end() == false && LastOR == true;) { - LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + LastOR = (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; (*this)++; if (LastOR == true) End = (*this); @@ -640,7 +634,7 @@ bool pkgCache::PkgFileIterator::IsOk() if (stat(FileName(),&Buf) != 0) return false; - if (Buf.st_size != (signed)File->Size || Buf.st_mtime != File->mtime) + if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime) return false; return true; diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index e8a3e1064..359f8a590 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -43,6 +43,7 @@ class pkgCache /*{{{*/ struct DescFile; // Iterators + template class Iterator; class PkgIterator; class VerIterator; class DescIterator; @@ -51,14 +52,6 @@ class pkgCache /*{{{*/ class PkgFileIterator; class VerFileIterator; class DescFileIterator; - friend class PkgIterator; - friend class VerIterator; - friend class DescInterator; - friend class DepIterator; - friend class PrvIterator; - friend class PkgFileIterator; - friend class VerFileIterator; - friend class DescFileIterator; class Namespace; -- cgit v1.2.3 From 7d15572bc3124b15c043e38bdc3d90bcc94f108a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 19 Dec 2009 14:25:20 +0100 Subject: add optional gcc features as deprecated, unused and (un)likely --- apt-pkg/contrib/system.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/system.h b/apt-pkg/contrib/system.h index 7ec3d7feb..f68df6265 100644 --- a/apt-pkg/contrib/system.h +++ b/apt-pkg/contrib/system.h @@ -55,4 +55,26 @@ #define CLRFLAG(v,f) ((v) &=~FLAG(f)) #define CHKFLAG(v,f) ((v) & FLAG(f) ? true : false) +// some nice optional GNUC features +#if __GNUC__ >= 3 + #define __must_check __attribute__ ((warn_unused_result)) + #define __deprecated __attribute__ ((deprecated)) + /* likely() and unlikely() can be used to mark boolean expressions + as (not) likely true which will help the compiler to optimise */ + #define likely(x) __builtin_expect (!!(x), 1) + #define unlikely(x) __builtin_expect (!!(x), 0) +#else + #define __must_check /* no warn_unused_result */ + #define __deprecated /* no deprecated */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif + +// cold functions are unlikely() to be called +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 + #define __cold __attribute__ ((__cold__)) +#else + #define __cold /* no cold marker */ +#endif + #endif -- cgit v1.2.3 From 201d1fa0d25deeda77c2570ee5342eaf18499699 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 19 Dec 2009 14:27:21 +0100 Subject: mark the Error/Warning method as __cold --- apt-pkg/contrib/error.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index a3be6a575..d92e40e9c 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -52,6 +52,7 @@ #endif #include +#include using std::string; @@ -71,13 +72,13 @@ class GlobalError public: // Call to generate an error from a library call. - bool Errno(const char *Function,const char *Description,...) APT_MFORMAT2; - bool WarningE(const char *Function,const char *Description,...) APT_MFORMAT2; + bool Errno(const char *Function,const char *Description,...) APT_MFORMAT2 __cold; + bool WarningE(const char *Function,const char *Description,...) APT_MFORMAT2 __cold; /* A warning should be considered less severe than an error, and may be ignored by the client. */ - bool Error(const char *Description,...) APT_MFORMAT1; - bool Warning(const char *Description,...) APT_MFORMAT1; + bool Error(const char *Description,...) APT_MFORMAT1 __cold; + bool Warning(const char *Description,...) APT_MFORMAT1 __cold; // Simple accessors inline bool PendingError() {return PendingFlag;}; -- cgit v1.2.3 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/cacheiterators.h | 37 ++++++++++++-- apt-pkg/deb/deblistparser.cc | 40 +++++++++++----- apt-pkg/deb/deblistparser.h | 1 + apt-pkg/pkgcache.cc | 112 ++++++++++++++++++++++++++++++++++++------- apt-pkg/pkgcache.h | 30 ++++++++++-- apt-pkg/pkgcachegen.cc | 111 +++++++++++++++++++++++++++++------------- apt-pkg/pkgcachegen.h | 6 ++- 7 files changed, 267 insertions(+), 70 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 1da5c6f02..35d3aa228 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -31,10 +31,8 @@ #define PKGLIB_CACHEITERATORS_H // abstract Iterator template /*{{{*/ /* This template provides the very basic iterator methods we - need to have for doing some walk-over-the-cache magic, */ + need to have for doing some walk-over-the-cache magic */ template class pkgCache::Iterator { - __attribute__ ((deprecated)) void _dummy(); // FIXME: Who on earth uses this method ??? - protected: Str *S; pkgCache *Owner; @@ -75,6 +73,35 @@ template class pkgCache::Iterator { // Constructors - look out for the variable assigning inline Iterator() : S(0), Owner(0) {}; inline Iterator(pkgCache &Owner,Str *T = 0) : S(T), Owner(&Owner) {}; +}; + /*}}}*/ +// Group Iterator /*{{{*/ +/* Packages with the same name are collected in a Group so someone only + interest in package names can iterate easily over the names, so the + different architectures can be treated as of the "same" package + (apt internally treat them as totally different packages) */ +class pkgCache::GrpIterator: public Iterator { + protected: + inline Group* OwnerPointer() const { + return Owner->GrpP; + }; + + public: + void operator ++(int) {if (S != Owner->GrpP) S = Owner->GrpP + S->Next;}; + virtual void operator ++() {operator ++(0);}; + + inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;}; + inline PkgIterator PackageList() const; + PkgIterator FindPkg(string Arch = "any"); + PkgIterator NextPkg(PkgIterator const &Pkg); + + // Constructors + inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator(Owner, Trg) { + if (S == 0) + S = OwnerPointer(); + }; + inline GrpIterator() : Iterator() {}; + }; /*}}}*/ // Package Iterator /*{{{*/ @@ -103,6 +130,8 @@ class pkgCache::PkgIterator: public Iterator { inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}; inline bool Purge() const {return S->CurrentState == pkgCache::State::Purge || (S->CurrentVer == 0 && S->CurrentState == pkgCache::State::NotInstalled);}; + inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;}; + inline GrpIterator Group() const { return GrpIterator(*Owner, Owner->GrpP + S->Group);}; inline VerIterator VersionList() const; inline VerIterator CurrentVer() const; @@ -339,6 +368,8 @@ class pkgCache::DescFileIterator : public Iterator { }; /*}}}*/ // Inlined Begin functions cant be in the class because of order problems /*{{{*/ +inline pkgCache::PkgIterator pkgCache::GrpIterator::PackageList() const + {return PkgIterator(*Owner,Owner->PkgP + S->FirstPackage);}; inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const {return VerIterator(*Owner,Owner->VerP + S->VersionList);}; inline pkgCache::VerIterator pkgCache::PkgIterator::CurrentVer() const diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 25a1df3f9..fe68aec0b 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -53,12 +53,25 @@ unsigned long debListParser::UniqFindTagWrite(const char *Tag) // ListParser::Package - Return the package name /*{{{*/ // --------------------------------------------------------------------- /* This is to return the name of the package this section describes */ -string debListParser::Package() -{ - string Result = Section.FindS("Package"); - if (Result.empty() == true) - _error->Error("Encountered a section with no Package: header"); - return Result; +string debListParser::Package() { + string const Result = Section.FindS("Package"); + if(unlikely(Result.empty() == true)) + _error->Error("Encountered a section with no Package: header"); + return Result; +} + /*}}}*/ +// ListParser::Architecture - Return the package arch /*{{{*/ +// --------------------------------------------------------------------- +/* This will return the Architecture of the package this section describes + Note that architecture "all" packages will get the architecture of the + Packages file parsed here */ +string debListParser::Architecture() { + string const Result = Section.FindS("Architecture"); + if (Result.empty() == true) + return Arch; + if (Result == "all") + return Arch; + return Result; } /*}}}*/ // ListParser::Version - Return the version string /*{{{*/ @@ -78,8 +91,10 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) { // Parse the section Ver->Section = UniqFindTagWrite("Section"); - Ver->Arch = UniqFindTagWrite("Architecture"); - + + // Parse the architecture + Ver->Arch = WriteUniqString(Architecture()); + // Archive Size Ver->Size = (unsigned)Section.FindI("Size"); @@ -537,6 +552,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, return true; string Package; + string const pkgArch = Ver.Arch(); string Version; unsigned int Op; @@ -546,7 +562,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, if (Start == 0) return _error->Error("Problem parsing dependency %s",Tag); - if (NewDepends(Ver,Package,Version,Op,Type) == false) + if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) return false; if (Start == Stop) break; @@ -619,6 +635,7 @@ bool debListParser::Step() if (Section.Find("Architecture",Start,Stop) == false) return true; + //FIXME: Accept different Architectures here if (stringcmp(Arch,Start,Stop) == 0) return true; @@ -641,8 +658,9 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, if (Tags.Step(Section) == false) return false; - //mvo: I don't think we need to fill that in (it's unused since apt-0.6) - //FileI->Architecture = WriteUniqString(Arch); + // FIXME: Do we need it now for multi-arch? + // mvo: I don't think we need to fill that in (it's unused since apt-0.6) +// FileI->Architecture = WriteUniqString(Arch); // apt-secure does no longer download individual (per-section) Release // file. to provide Component pinning we use the section name now diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 1c709229f..5f91e073e 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -46,6 +46,7 @@ class debListParser : public pkgCacheGenerator::ListParser // These all operate against the current section virtual string Package(); + virtual string Architecture(); virtual string Version(); virtual bool NewVersion(pkgCache::VerIterator Ver); virtual string Description(); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 2f8bde6f7..2b5f53f6f 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -79,7 +79,8 @@ pkgCache::Header::Header() StringList = 0; VerSysName = 0; Architecture = 0; - memset(HashTable,0,sizeof(HashTable)); + memset(PkgHashTable,0,sizeof(PkgHashTable)); + memset(GrpHashTable,0,sizeof(GrpHashTable)); memset(Pools,0,sizeof(Pools)); } /*}}}*/ @@ -118,6 +119,7 @@ bool pkgCache::ReMap() { // Apply the typecasts. HeaderP = (Header *)Map.Data(); + GrpP = (Group *)Map.Data(); PkgP = (Package *)Map.Data(); VerFileP = (VerFile *)Map.Data(); DescFileP = (DescFile *)Map.Data(); @@ -165,7 +167,7 @@ unsigned long pkgCache::sHash(const string &Str) const unsigned long Hash = 0; for (string::const_iterator I = Str.begin(); I != Str.end(); I++) Hash = 5*Hash + tolower_ascii(*I); - return Hash % _count(HeaderP->HashTable); + return Hash % _count(HeaderP->PkgHashTable); } unsigned long pkgCache::sHash(const char *Str) const @@ -173,24 +175,40 @@ 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); - return Hash % _count(HeaderP->HashTable); + return Hash % _count(HeaderP->PkgHashTable); } /*}}}*/ // Cache::FindPkg - Locate a package by name /*{{{*/ // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ -pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) -{ - // Look at the hash bucket - Package *Pkg = PkgP + HeaderP->HashTable[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); - } - return PkgIterator(*this,0); +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 + find than a package (less entries in the buckets) */ + pkgCache::GrpIterator Grp = FindGrp(Name); + if (Grp.end() == true) + return PkgIterator(*this,0); + + return Grp.FindPkg(Arch); +} + /*}}}*/ +// Cache::FindGrp - Locate a group by name /*{{{*/ +// --------------------------------------------------------------------- +/* Returns End-Pointer on error, pointer to the group otherwise */ +pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) { + if (unlikely(Name.empty() == true)) + return GrpIterator(*this,0); + + // 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) + return GrpIterator(*this, Grp); + } + + return GrpIterator(*this,0); } /*}}}*/ // Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/ @@ -242,6 +260,68 @@ const char *pkgCache::Priority(unsigned char Prio) return 0; } /*}}}*/ +// GrpIterator::FindPkg - Locate a package by arch /*{{{*/ +// --------------------------------------------------------------------- +/* Returns an End-Pointer on error, pointer to the package otherwise */ +pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) { + if (unlikely(IsGood() == false || S->FirstPackage == 0)) + return PkgIterator(*Owner, 0); + + static string const myArch = _config->Find("APT::Architecture"); + /* 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 = myArch; + pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage; + if (stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0) + return PkgIterator(*Owner, Pkg); + } + + /* If we accept any package we simply return the "first" + package in this group (the last one added). */ + if (Arch == "any") + return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage); + + /* Iterate over the list to find the matching arch + unfortunately this list includes "package noise" + (= different packages with same calculated hash), + so we need to check the name also */ + for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP; + Pkg = Owner->PkgP + Pkg->NextPackage) { + if (S->Name == Pkg->Name && + stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0) + return PkgIterator(*Owner, Pkg); + if ((Owner->PkgP + S->LastPackage) == Pkg) + break; + } + + return PkgIterator(*Owner, 0); +} + /*}}}*/ +// GrpIterator::NextPkg - Locate the next package in the group /*{{{*/ +// --------------------------------------------------------------------- +/* Returns an End-Pointer on error, pointer to the package otherwise. + We can't simply ++ to the next as the list of packages includes + "package noise" (= packages with the same hash value but different name) */ +pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) { + if (unlikely(IsGood() == false || S->FirstPackage == 0 || + LastPkg.end() == true)) + return PkgIterator(*Owner, 0); + + // Iterate over the list to find the next package + pkgCache::Package *Pkg = Owner->PkgP + LastPkg.Index(); + Pkg = Owner->PkgP + Pkg->NextPackage; + for (; Pkg != Owner->PkgP; Pkg = Owner->PkgP + Pkg->NextPackage) { + if (S->Name == Pkg->Name) + return PkgIterator(*Owner, Pkg); + if ((Owner->PkgP + S->LastPackage) == Pkg) + break; + } + + return PkgIterator(*Owner, 0); +} + /*}}}*/ // PkgIterator::operator ++ - Postfix incr /*{{{*/ // --------------------------------------------------------------------- /* This will advance to the next logical package in the hash table. */ @@ -252,10 +332,10 @@ void pkgCache::PkgIterator::operator ++(int) S = Owner->PkgP + S->NextPackage; // Follow the hash table - while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->HashTable)) + while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->PkgHashTable)) { HashIndex++; - S = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex]; + S = Owner->PkgP + Owner->HeaderP->PkgHashTable[HashIndex]; } }; /*}}}*/ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 359f8a590..b3d2752d2 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -32,6 +32,7 @@ class pkgCache /*{{{*/ public: // Cache element predeclarations struct Header; + struct Group; struct Package; struct PackageFile; struct Version; @@ -44,6 +45,7 @@ class pkgCache /*{{{*/ // Iterators template class Iterator; + class GrpIterator; class PkgIterator; class VerIterator; class DescIterator; @@ -97,6 +99,7 @@ class pkgCache /*{{{*/ // Pointers to the arrays of items Header *HeaderP; + Group *GrpP; Package *PkgP; VerFile *VerFileP; DescFile *DescFileP; @@ -121,7 +124,9 @@ class pkgCache /*{{{*/ const char *Priority(unsigned char Priority); // Accessors - PkgIterator FindPkg(const string &Name); + GrpIterator FindGrp(const string &Name); + PkgIterator FindPkg(const string &Name, string Arch = "native"); + Header &Head() {return *HeaderP;}; inline PkgIterator PkgBegin(); inline PkgIterator PkgEnd(); @@ -161,6 +166,7 @@ struct pkgCache::Header unsigned short DescFileSz; // Structure counts + unsigned long GroupCount; unsigned long PackageCount; unsigned long VersionCount; unsigned long DescriptionCount; @@ -180,22 +186,36 @@ struct pkgCache::Header /* Allocation pools, there should be one of these for each structure excluding the header */ - DynamicMMap::Pool Pools[8]; + DynamicMMap::Pool Pools[9]; - // Rapid package name lookup - map_ptrloc HashTable[2*1048]; + // Rapid package and group name lookup + // Notice: Increase only both table sizes as the + // hashmethod assume the size of the Pkg one + map_ptrloc PkgHashTable[2*1048]; + map_ptrloc GrpHashTable[2*1048]; bool CheckSizes(Header &Against) const; Header(); }; /*}}}*/ +struct pkgCache::Group { /*{{{*/ + map_ptrloc Name; // Stringtable + + // Linked List + map_ptrloc FirstPackage;// Package + map_ptrloc LastPackage; // Package + map_ptrloc Next; // Group +}; + /*}}}*/ struct pkgCache::Package /*{{{*/ { // Pointers map_ptrloc Name; // Stringtable + map_ptrloc Arch; // StringTable (StringItem) map_ptrloc VersionList; // Version map_ptrloc CurrentVer; // Version map_ptrloc Section; // StringTable (StringItem) + map_ptrloc Group; // Group the Package belongs to // Linked list map_ptrloc NextPackage; // Package @@ -254,7 +274,7 @@ struct pkgCache::Version /*{{{*/ map_ptrloc VerStr; // Stringtable map_ptrloc Section; // StringTable (StringItem) map_ptrloc Arch; // StringTable - + // Lists map_ptrloc FileList; // VerFile map_ptrloc NextVer; // Version 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 diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 108b34207..4a2419b24 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -51,7 +51,8 @@ class pkgCacheGenerator /*{{{*/ // Flag file dependencies bool FoundFileDeps; - bool NewPackage(pkgCache::PkgIterator &Pkg,const string &PkgName); + bool NewGroup(pkgCache::GrpIterator &Grp,const string &Name); + 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); unsigned long NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next); @@ -96,7 +97,7 @@ class pkgCacheGenerator::ListParser inline unsigned long WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; inline unsigned long WriteString(const string &S) {return Owner->Map.WriteString(S);}; inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->Map.WriteString(S,Size);}; - bool NewDepends(pkgCache::VerIterator Ver,const string &Package, + 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, @@ -106,6 +107,7 @@ class pkgCacheGenerator::ListParser // These all operate against the current section virtual string Package() = 0; + virtual string Architecture() = 0; virtual string Version() = 0; virtual bool NewVersion(pkgCache::VerIterator Ver) = 0; virtual string Description() = 0; -- cgit v1.2.3 From 5dd4c8b811d9c7bc33e50254811f5bc0fc37f872 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 23 Dec 2009 12:38:19 +0100 Subject: merge Goswin Brederlow "support download of index files for different archs" patch which includes the following big changes: - Declare the unused [vendor] field in sources.list as option field, e.g. deb [arch=amd64,i386 lang=en_GB have=fun] http://example.org - When fetching index files download them for all APT::Architectures (overrideable with the options field above) - Allow all architectures of APT::Architectures to be in the Cache - Add the architecture to status and progress informations - Add b= (Binary architecture) to policy This commit doesn't incude the "pin-hack" as the Group structure will take care of this (and does it already to some extend). --- apt-pkg/aptconfiguration.cc | 25 ++++ apt-pkg/aptconfiguration.h | 16 +++ apt-pkg/cdrom.cc | 34 ++--- apt-pkg/clean.cc | 6 +- apt-pkg/contrib/strutl.cc | 17 +++ apt-pkg/contrib/strutl.h | 1 + apt-pkg/deb/debindexfile.cc | 15 ++- apt-pkg/deb/debindexfile.h | 4 +- apt-pkg/deb/deblistparser.cc | 57 ++++++--- apt-pkg/deb/deblistparser.h | 2 +- apt-pkg/deb/debmetaindex.cc | 292 +++++++++++++++++++++++++++---------------- apt-pkg/deb/debmetaindex.h | 28 +++-- apt-pkg/metaindex.h | 4 +- apt-pkg/pkgcache.cc | 8 +- apt-pkg/sourcelist.cc | 81 ++++++------ apt-pkg/sourcelist.h | 8 +- apt-pkg/versionmatch.cc | 8 +- apt-pkg/versionmatch.h | 2 + 18 files changed, 394 insertions(+), 214 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 899004d9f..1ec526646 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -223,4 +224,28 @@ std::vector const Configuration::getLanguages(bool const &All, return codes; } /*}}}*/ +// getArchitectures - Return Vector of prefered Architectures /*{{{*/ +std::vector const Configuration::getArchitectures(bool const &Cached) { + using std::string; + + std::vector static archs; + if (likely(Cached == true) && archs.empty() == false) + return archs; + + string const arch = _config->Find("APT::Architecture"); + archs = _config->FindVector("APT::Architectures"); + if (archs.empty() == true || + std::find(archs.begin(), archs.end(), arch) == archs.end()) + archs.push_back(arch); + return archs; +} + /*}}}*/ +// checkArchitecture - are we interested in the given Architecture? /*{{{*/ +bool const Configuration::checkArchitecture(std::string const &Arch) { + if (Arch == "all") + return true; + std::vector const archs = getArchitectures(true); + return (std::find(archs.begin(), archs.end(), Arch) != archs.end()); +} + /*}}}*/ } diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index f2f04a39b..b6650e20c 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -66,6 +66,22 @@ public: /*{{{*/ std::vector static const getLanguages(bool const &All = false, bool const &Cached = true, char const * const Locale = 0); + /** \brief Returns a vector of Architectures we support + * + * \param Cached saves the result so we need to calculated it only once + * this parameter should ony be used for testing purposes. + * + * \return a vector of Architectures in prefered order + */ + std::vector static const getArchitectures(bool const &Cached = true); + + /** \brief Are we interested in the given Architecture? + * + * \param Arch we want to check + * \return true if we are interested, false otherwise + */ + bool static const checkArchitecture(std::string const &Arch); + /*}}}*/ }; /*}}}*/ diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 72d8e4d41..271bca409 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -6,6 +6,8 @@ #include #include #include +#include + #include #include #include @@ -216,33 +218,23 @@ int pkgCdrom::Score(string Path) /* Here we drop everything that is not this machines arch */ bool pkgCdrom::DropBinaryArch(vector &List) { - char S[300]; - snprintf(S,sizeof(S),"/binary-%s/", - _config->Find("Apt::Architecture").c_str()); - + for (unsigned int I = 0; I < List.size(); I++) { const char *Str = List[I].c_str(); - - const char *Res; - if ((Res = strstr(Str,"/binary-")) == 0) + const char *Start, *End; + if ((Start = strstr(Str,"/binary-")) == 0) continue; - // Weird, remove it. - if (strlen(Res) < strlen(S)) - { - List.erase(List.begin() + I); - I--; - continue; - } - - // See if it is our arch - if (stringcmp(Res,Res + strlen(S),S) == 0) - continue; - - // Erase it + // Between Start and End is the architecture + Start += 8; + if ((End = strstr(Start,"/")) != 0 && Start != End && + APT::Configuration::checkArchitecture(string(Start, --End)) == true) + continue; // okay, architecture is accepted + + // not accepted -> Erase it List.erase(List.begin() + I); - I--; + --I; // the next entry is at the same index after the erase } return true; diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 0d1dfbf74..629afd7cf 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -26,7 +27,6 @@ bool pkgArchiveCleaner::Go(string Dir,pkgCache &Cache) { bool CleanInstalled = _config->FindB("APT::Clean-Installed",true); - string MyArch = _config->Find("APT::Architecture"); DIR *D = opendir(Dir.c_str()); if (D == 0) @@ -75,9 +75,9 @@ bool pkgArchiveCleaner::Go(string Dir,pkgCache &Cache) for (I = Start; *I != 0 && *I != '.' ;I++); if (*I != '.') continue; - string Arch = DeQuoteString(string(Start,I-Start)); + string const Arch = DeQuoteString(string(Start,I-Start)); - if (Arch != "all" && Arch != MyArch) + if (APT::Configuration::checkArchitecture(Arch) == false) continue; // Lookup the package diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 4c05f2df8..bed51881f 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -983,6 +983,23 @@ bool TokSplitString(char Tok,char *Input,char **List, return true; } /*}}}*/ +// ExplodeString - Split a string up into a vector /*{{{*/ +// --------------------------------------------------------------------- +/* This can be used to split a given string up into a vector, so the + propose is the same as in the method above and this one is a bit slower + also, but the advantage is that we an iteratable vector */ +vector ExplodeString(string const &haystack, char const &split) { + string::const_iterator start = haystack.begin(); + string::const_iterator end = start; + vector exploded; + do { + for (; end != haystack.end() && *end != split; ++end); + exploded.push_back(string(start, end)); + start = end; + } while (end != haystack.end() && (++end) != haystack.end()); + return exploded; +} + /*}}}*/ // RegexChoice - Simple regex list/list matcher /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 2b2e147fb..3bdb65b4d 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -59,6 +59,7 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0) bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length); bool TokSplitString(char Tok,char *Input,char **List, unsigned long ListMax); +vector ExplodeString(string const &haystack, char const &split=','); void ioprintf(ostream &out,const char *format,...) APT_FORMAT2; void strprintf(string &out,const char *format,...) APT_FORMAT2; char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 5beb83665..73d72c729 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -149,9 +149,12 @@ unsigned long debSourcesIndex::Size() const // PackagesIndex::debPackagesIndex - Contructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debPackagesIndex::debPackagesIndex(string URI,string Dist,string Section,bool Trusted) : - pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section) +debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section, + bool const &Trusted, string const &Arch) : + pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch) { + if (Architecture == "native") + Architecture = _config->Find("APT::Architecture"); } /*}}}*/ // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/ @@ -171,6 +174,8 @@ string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const Res += " "; Res += Ver.ParentPkg().Name(); Res += " "; + Res += Ver.Arch(); + Res += " "; Res += Ver.VerStr(); return Res; } @@ -204,6 +209,8 @@ string debPackagesIndex::Info(const char *Type) const else Info += Dist + '/' + Section; Info += " "; + Info += Architecture; + Info += " "; Info += Type; return Info; } @@ -227,7 +234,7 @@ string debPackagesIndex::IndexURI(const char *Type) const } else Res = URI + "dists/" + Dist + '/' + Section + - "/binary-" + _config->Find("APT::Architecture") + '/'; + "/binary-" + Architecture + '/'; Res += Type; return Res; @@ -259,7 +266,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const { string PackageFile = IndexFile("Packages"); FileFd Pkg(PackageFile,FileFd::ReadOnly); - debListParser Parser(&Pkg); + debListParser Parser(&Pkg, Architecture); if (_error->PendingError() == true) return _error->Error("Problem opening %s",PackageFile.c_str()); diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index c0e8d7d8e..766e8b214 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -46,6 +46,7 @@ class debPackagesIndex : public pkgIndexFile string URI; string Dist; string Section; + string Architecture; string Info(const char *Type) const; string IndexFile(const char *Type) const; @@ -69,7 +70,8 @@ class debPackagesIndex : public pkgIndexFile virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; - debPackagesIndex(string URI,string Dist,string Section,bool Trusted); + debPackagesIndex(string const &URI, string const &Dist, string const &Section, + bool const &Trusted, string const &Arch = "native"); }; class debTranslationsIndex : public pkgIndexFile diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index fe68aec0b..b57eca813 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -32,10 +32,13 @@ static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Impor // ListParser::debListParser - Constructor /*{{{*/ // --------------------------------------------------------------------- -/* */ -debListParser::debListParser(FileFd *File) : Tags(File) -{ - Arch = _config->Find("APT::architecture"); +/* Provide an architecture and only this one and "all" will be accepted + in Step(), if no Architecture is given we will accept every arch + we would accept in general with checkArchitecture() */ +debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File), + Arch(Arch) { + if (Arch == "native") + this->Arch = _config->Find("APT::Architecture"); } /*}}}*/ // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ @@ -64,13 +67,19 @@ string debListParser::Package() { // --------------------------------------------------------------------- /* This will return the Architecture of the package this section describes Note that architecture "all" packages will get the architecture of the - Packages file parsed here */ + Packages file parsed here. */ string debListParser::Architecture() { string const Result = Section.FindS("Architecture"); - if (Result.empty() == true) - return Arch; - if (Result == "all") - return Arch; + if (Result.empty() == true || Result == "all") { + if (Arch.empty() == true) + /* FIXME: this is a problem for installed arch all + packages as we don't know from which arch this + package was installed - and therefore which + dependency this package resolves. */ + return _config->Find("APT::Architecture"); + else + return Arch; + } return Result; } /*}}}*/ @@ -199,8 +208,12 @@ bool debListParser::UsePackage(pkgCache::PkgIterator Pkg, { if (Pkg->Section == 0) Pkg->Section = UniqFindTagWrite("Section"); - if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false) - return false; + + // Packages which are not from "our" arch doesn't get the essential flag + string const static myArch = _config->Find("APT::Architecture"); + if (Pkg->Arch != 0 && myArch == Pkg.Arch()) + if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false) + return false; if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false) return false; @@ -630,17 +643,23 @@ bool debListParser::Step() /* See if this is the correct Architecture, if it isn't then we drop the whole section. A missing arch tag only happens (in theory) inside the Status file, so that is a positive return */ - const char *Start; - const char *Stop; - if (Section.Find("Architecture",Start,Stop) == false) + string const Architecture = Section.FindS("Architecture"); + if (Architecture.empty() == true) return true; - //FIXME: Accept different Architectures here - if (stringcmp(Arch,Start,Stop) == 0) - return true; + if (Arch.empty() == true) + { + if (APT::Configuration::checkArchitecture(Architecture) == true) + return true; + } + else + { + if (Architecture == Arch) + return true; - if (stringcmp(Start,Stop,"all") == 0) - return true; + if (Architecture == "all") + return true; + } iOffset = Tags.Offset(); } diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 5f91e073e..cba4f8e5d 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -69,7 +69,7 @@ class debListParser : public pkgCacheGenerator::ListParser bool const &StripMultiArch = false); static const char *ConvertRelation(const char *I,unsigned int &Op); - debListParser(FileFd *File); + debListParser(FileFd *File, string const &Arch = ""); }; #endif diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 8f28f053b..eb01a0156 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -8,9 +8,11 @@ #include #include +#include + using namespace std; -string debReleaseIndex::Info(const char *Type, const string Section) const +string debReleaseIndex::Info(const char *Type, string const &Section, string const &Arch) const { string Info = ::URI::SiteOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') @@ -19,7 +21,11 @@ string debReleaseIndex::Info(const char *Type, const string Section) const Info += Dist; } else - Info += Dist + '/' + Section; + { + Info += Dist + '/' + Section; + if (Arch.empty() == true) + Info += " " + Arch; + } Info += " "; Info += Type; return Info; @@ -61,16 +67,21 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const return Res; } -string debReleaseIndex::IndexURISuffix(const char *Type, const string Section) const +string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const { string Res =""; if (Dist[Dist.size() - 1] != '/') - Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/'; + { + if (Arch == "native") + Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/'; + else + Res += Section + "/binary-" + Arch + '/'; + } return Res + Type; } -string debReleaseIndex::IndexURI(const char *Type, const string Section) const +string debReleaseIndex::IndexURI(const char *Type, string const &Section, string const &Arch) const { if (Dist[Dist.size() - 1] == '/') { @@ -82,10 +93,10 @@ string debReleaseIndex::IndexURI(const char *Type, const string Section) const return Res + Type; } else - return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section); + return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section, Arch); } -string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string Section) const +string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string &Section) const { string Res =""; if (Dist[Dist.size() - 1] != '/') @@ -93,7 +104,7 @@ string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string Sect return Res + Type; } -string debReleaseIndex::SourceIndexURI(const char *Type, const string Section) const +string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section) const { string Res; if (Dist[Dist.size() - 1] == '/') @@ -108,44 +119,61 @@ string debReleaseIndex::SourceIndexURI(const char *Type, const string Section) c return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section); } -debReleaseIndex::debReleaseIndex(string URI,string Dist) -{ - this->URI = URI; - this->Dist = Dist; - this->Indexes = NULL; - this->Type = "deb"; +debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) { + this->URI = URI; + this->Dist = Dist; + this->Indexes = NULL; + this->Type = "deb"; } -debReleaseIndex::~debReleaseIndex() -{ - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); I++) - delete *I; +debReleaseIndex::~debReleaseIndex() { + for (map >::const_iterator A = ArchEntries.begin(); + A != ArchEntries.end(); ++A) + for (vector::const_iterator S = A->second.begin(); + S != A->second.end(); ++S) + delete *S; } -vector * debReleaseIndex::ComputeIndexTargets() const -{ - vector * IndexTargets = new vector ; - for (vector ::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); - I++) - { - IndexTarget * Target = new IndexTarget(); - Target->ShortDesc = (*I)->IsSrc ? "Sources" : "Packages"; - Target->MetaKey - = (*I)->IsSrc ? SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section) - : IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section); - Target->URI - = (*I)->IsSrc ? SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section) - : IndexURI(Target->ShortDesc.c_str(), (*I)->Section); - - Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section); - IndexTargets->push_back (Target); - } - return IndexTargets; +vector * debReleaseIndex::ComputeIndexTargets() const { + vector * IndexTargets = new vector ; + + map >::const_iterator const src = ArchEntries.find("source"); + if (src != ArchEntries.end()) { + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); + I != SectionEntries.end(); ++I) { + IndexTarget * Target = new IndexTarget(); + Target->ShortDesc = "Sources"; + Target->MetaKey = SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section); + Target->URI = SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section); + Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section); + IndexTargets->push_back (Target); + } + } + + // Only source release + if (IndexTargets->empty() == false && ArchEntries.size() == 1) + return IndexTargets; + + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + if (a->first == "source") + continue; + for (vector ::const_iterator I = a->second.begin(); + I != a->second.end(); ++I) { + IndexTarget * Target = new IndexTarget(); + Target->ShortDesc = "Packages"; + Target->MetaKey = IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section, a->first); + Target->URI = IndexURI(Target->ShortDesc.c_str(), (*I)->Section, a->first); + Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section, a->first); + IndexTargets->push_back (Target); + } + } + + return IndexTargets; } /*}}}*/ -bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const +bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const { // special case for --print-uris if (GetAll) { @@ -170,23 +198,27 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const ComputeIndexTargets(), new indexRecords (Dist)); - // Queue the translations - std::vector const lang = APT::Configuration::getLanguages(true); - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); I++) { - - if((*I)->IsSrc) - continue; - - for (vector::const_iterator l = lang.begin(); - l != lang.end(); l++) - { - debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str()); - i.GetIndexes(Owner); - } - } - - return true; + // Queue the translations + std::vector const lang = APT::Configuration::getLanguages(true); + map > sections; + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + if (a->first == "source") + continue; + for (vector::const_iterator I = a->second.begin(); + I != a->second.end(); I++) + sections[(*I)->Section].insert(lang.begin(), lang.end()); + } + + for (map >::const_iterator s = sections.begin(); + s != sections.end(); ++s) + for (set::const_iterator l = s->second.begin(); + l != s->second.end(); l++) { + debTranslationsIndex i = debTranslationsIndex(URI,Dist,s->first,(*l).c_str()); + i.GetIndexes(Owner); + } + + return true; } bool debReleaseIndex::IsTrusted() const @@ -203,71 +235,111 @@ bool debReleaseIndex::IsTrusted() const return false; } -vector *debReleaseIndex::GetIndexFiles() -{ - if (Indexes != NULL) - return Indexes; - - Indexes = new vector ; - std::vector const lang = APT::Configuration::getLanguages(true); - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); I++) { - if ((*I)->IsSrc) - Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted())); - else - { - Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted())); - - for (vector::const_iterator l = lang.begin(); - l != lang.end(); l++) - Indexes->push_back(new debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str())); - } - } +vector *debReleaseIndex::GetIndexFiles() { + if (Indexes != NULL) + return Indexes; + + Indexes = new vector ; + map >::const_iterator const src = ArchEntries.find("source"); + if (src != ArchEntries.end()) { + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); + I != SectionEntries.end(); I++) + Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted())); + } + + // Only source release + if (Indexes->empty() == false && ArchEntries.size() == 1) + return Indexes; + + std::vector const lang = APT::Configuration::getLanguages(true); + map > sections; + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + if (a->first == "source") + continue; + for (vector::const_iterator I = a->second.begin(); + I != a->second.end(); I++) { + Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted(), a->first)); + sections[(*I)->Section].insert(lang.begin(), lang.end()); + } + } + + for (map >::const_iterator s = sections.begin(); + s != sections.end(); ++s) + for (set::const_iterator l = s->second.begin(); + l != s->second.end(); l++) + Indexes->push_back(new debTranslationsIndex(URI,Dist,s->first,(*l).c_str())); + + return Indexes; +} - return Indexes; +void debReleaseIndex::PushSectionEntry(vector const &Archs, const debSectionEntry *Entry) { + for (vector::const_iterator a = Archs.begin(); + a != Archs.end(); ++a) + ArchEntries[*a].push_back(new debSectionEntry(Entry->Section, Entry->IsSrc)); + delete Entry; } -void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) -{ - SectionEntries.push_back(Entry); +void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry *Entry) { + ArchEntries[Arch].push_back(Entry); } -debReleaseIndex::debSectionEntry::debSectionEntry (string Section, bool IsSrc): Section(Section) -{ - this->IsSrc = IsSrc; +void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) { + if (Entry->IsSrc == true) + PushSectionEntry("source", Entry); + else { + for (map >::iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + a->second.push_back(Entry); + } + } } +debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, + bool const &IsSrc): Section(Section), IsSrc(IsSrc) +{} + class debSLTypeDebian : public pkgSourceList::Type { protected: - bool CreateItemInternal(vector &List,string URI, - string Dist,string Section, - bool IsSrc) const + bool CreateItemInternal(vector &List, string const &URI, + string const &Dist, string const &Section, + bool const &IsSrc, map const &Options) const { - for (vector::const_iterator I = List.begin(); + map::const_iterator const arch = Options.find("arch"); + vector const Archs = + (arch != Options.end()) ? ExplodeString(arch->second) : + APT::Configuration::getArchitectures(); + + for (vector::const_iterator I = List.begin(); I != List.end(); I++) { - // This check insures that there will be only one Release file - // queued for all the Packages files and Sources files it - // corresponds to. - if (strcmp((*I)->GetType(), "deb") == 0) + // We only worry about debian entries here + if (strcmp((*I)->GetType(), "deb") != 0) + continue; + + debReleaseIndex *Deb = (debReleaseIndex *) (*I); + /* This check insures that there will be only one Release file + queued for all the Packages files and Sources files it + corresponds to. */ + if (Deb->GetURI() == URI && Deb->GetDist() == Dist) { - debReleaseIndex *Deb = (debReleaseIndex *) (*I); - // This check insures that there will be only one Release file - // queued for all the Packages files and Sources files it - // corresponds to. - if (Deb->GetURI() == URI && Deb->GetDist() == Dist) - { - Deb->PushSectionEntry(new debReleaseIndex::debSectionEntry(Section, IsSrc)); - return true; - } + if (IsSrc == true) + Deb->PushSectionEntry("source", new debReleaseIndex::debSectionEntry(Section, IsSrc)); + else + Deb->PushSectionEntry(Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); + return true; } } // No currently created Release file indexes this entry, so we create a new one. // XXX determine whether this release is trusted or not - debReleaseIndex *Deb = new debReleaseIndex(URI,Dist); - Deb->PushSectionEntry (new debReleaseIndex::debSectionEntry(Section, IsSrc)); + debReleaseIndex *Deb = new debReleaseIndex(URI, Dist); + if (IsSrc == true) + Deb->PushSectionEntry ("source", new debReleaseIndex::debSectionEntry(Section, IsSrc)); + else + Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); List.push_back(Deb); return true; } @@ -277,10 +349,11 @@ class debSLTypeDeb : public debSLTypeDebian { public: - bool CreateItem(vector &List,string URI, - string Dist,string Section) const + bool CreateItem(vector &List, string const &URI, + string const &Dist, string const &Section, + std::map const &Options) const { - return CreateItemInternal(List, URI, Dist, Section, false); + return CreateItemInternal(List, URI, Dist, Section, false, Options); } debSLTypeDeb() @@ -294,10 +367,11 @@ class debSLTypeDebSrc : public debSLTypeDebian { public: - bool CreateItem(vector &List,string URI, - string Dist,string Section) const + bool CreateItem(vector &List, string const &URI, + string const &Dist, string const &Section, + std::map const &Options) const { - return CreateItemInternal(List, URI, Dist, Section, true); + return CreateItemInternal(List, URI, Dist, Section, true, Options); } debSLTypeDebSrc() diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 8e6a1463b..360fa5419 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -5,40 +5,44 @@ #include #include +#include + class debReleaseIndex : public metaIndex { public: class debSectionEntry { public: - debSectionEntry (string Section, bool IsSrc); - bool IsSrc; - string Section; + debSectionEntry (string const &Section, bool const &IsSrc); + string const Section; + bool const IsSrc; }; private: - vector SectionEntries; + std::map > ArchEntries; public: - debReleaseIndex(string URI, string Dist); + debReleaseIndex(string const &URI, string const &Dist); ~debReleaseIndex(); - virtual string ArchiveURI(string File) const {return URI + File;}; - virtual bool GetIndexes(pkgAcquire *Owner, bool GetAll=false) const; + virtual string ArchiveURI(string const &File) const {return URI + File;}; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; vector * ComputeIndexTargets() const; - string Info(const char *Type, const string Section) const; + string Info(const char *Type, string const &Section, string const &Arch="") const; string MetaIndexInfo(const char *Type) const; string MetaIndexFile(const char *Types) const; string MetaIndexURI(const char *Type) const; - string IndexURI(const char *Type, const string Section) const; - string IndexURISuffix(const char *Type, const string Section) const; - string SourceIndexURI(const char *Type, const string Section) const; - string SourceIndexURISuffix(const char *Type, const string Section) const; + string IndexURI(const char *Type, string const &Section, string const &Arch="native") const; + string IndexURISuffix(const char *Type, string const &Section, string const &Arch="native") const; + string SourceIndexURI(const char *Type, const string &Section) const; + string SourceIndexURISuffix(const char *Type, const string &Section) const; virtual vector *GetIndexFiles(); virtual bool IsTrusted() const; + void PushSectionEntry(vector const &Archs, const debSectionEntry *Entry); + void PushSectionEntry(string const &Arch, const debSectionEntry *Entry); void PushSectionEntry(const debSectionEntry *Entry); }; diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 779b6ab14..1d2140799 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -33,8 +33,8 @@ class metaIndex virtual const char* GetType() const {return Type;} // Interface for acquire - virtual string ArchiveURI(string /*File*/) const = 0; - virtual bool GetIndexes(pkgAcquire *Owner, bool GetAll=false) const = 0; + virtual string ArchiveURI(string const& /*File*/) const = 0; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0; virtual vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 2b5f53f6f..c945c59bf 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -406,7 +406,7 @@ operator<<(ostream& out, pkgCache::PkgIterator Pkg) string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion()); string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr()); - out << Pkg.Name() << " < " << current; + out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current; if (current != candidate) out << " -> " << candidate; if ( newest != "none" && candidate != newest) @@ -699,7 +699,9 @@ string pkgCache::VerIterator::RelStr() else Res += File.Site(); } - } + } + if (S->Arch != 0) + Res.append(" [").append(Arch()).append("]"); return Res; } /*}}}*/ @@ -738,6 +740,8 @@ string pkgCache::PkgFileIterator::RelStr() Res = Res + (Res.empty() == true?"l=":",l=") + Label(); if (Component() != 0) Res = Res + (Res.empty() == true?"c=":",c=") + Component(); + if (Architecture() != 0) + Res = Res + (Res.empty() == true?"b=":",b=") + Architecture(); return Res; } /*}}}*/ diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 4b3abe918..6b7a299d6 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -79,13 +79,51 @@ bool pkgSourceList::Type::FixupURI(string &URI) const Weird types may override this. */ bool pkgSourceList::Type::ParseLine(vector &List, const char *Buffer, - unsigned long CurLine, - string File) const + unsigned long const &CurLine, + string const &File) const { + for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces + + // Parse option field if it exists + // e.g.: [ option1=value1 option2=value2 ] + map Options; + if (Buffer != 0 && Buffer[0] == '[') + { + ++Buffer; // ignore the [ + for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces + while (*Buffer != ']') + { + // get one option, e.g. option1=value1 + string option; + if (ParseQuoteWord(Buffer,option) == false) + return _error->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine,File.c_str()); + + if (option.length() < 3) + return _error->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine,File.c_str()); + + size_t const needle = option.find('='); + if (needle == string::npos) + return _error->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine,File.c_str(), option.c_str()); + + string const key = string(option, 0, needle); + string const value = string(option, needle + 1, option.length()); + + if (key.empty() == true) + return _error->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine,File.c_str(), option.c_str()); + + if (value.empty() == true) + return _error->Error(_("Malformed line %lu in source list %s ([%s] key %s has no value)"),CurLine,File.c_str(),option.c_str(),key.c_str()); + + Options[key] = value; + } + ++Buffer; // ignore the ] + for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces + } + string URI; string Dist; - string Section; - + string Section; + if (ParseQuoteWord(Buffer,URI) == false) return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str()); if (ParseQuoteWord(Buffer,Dist) == false) @@ -100,7 +138,7 @@ bool pkgSourceList::Type::ParseLine(vector &List, if (ParseQuoteWord(Buffer,Section) == true) return _error->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine,File.c_str()); Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture")); - return CreateItem(List,URI,Dist,Section); + return CreateItem(List, URI, Dist, Section, Options); } // Grab the rest of the dists @@ -109,7 +147,7 @@ bool pkgSourceList::Type::ParseLine(vector &List, do { - if (CreateItem(List,URI,Dist,Section) == false) + if (CreateItem(List, URI, Dist, Section, Options) == false) return false; } while (ParseQuoteWord(Buffer,Section) == true); @@ -246,36 +284,7 @@ bool pkgSourceList::ReadAppend(string File) if (Parse == 0) return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str()); - // Vendor name specified - if (C[0] == '[') - { - string VendorID; - - if (ParseQuoteWord(C,VendorID) == false) - return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str()); - - if (VendorID.length() < 2 || VendorID.end()[-1] != ']') - return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str()); - VendorID = string(VendorID,1,VendorID.size()-2); - -// for (vector::const_iterator iter = VendorList.begin(); -// iter != VendorList.end(); iter++) -// { -// if ((*iter)->GetVendorID() == VendorID) -// { -// if (_config->FindB("Debug::sourceList", false)) -// std::cerr << "Comparing VendorID \"" << VendorID << "\" with \"" << (*iter)->GetVendorID() << '"' << std::endl; -// Verifier = *iter; -// break; -// } -// } - -// if (Verifier == 0) -// return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"), -// VendorID.c_str(),CurLine,File.c_str()); - } - - if (Parse->ParseLine(SrcList,C,CurLine,File) == false) + if (Parse->ParseLine(SrcList, C, CurLine, File) == false) return false; } return true; diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index b9e4389ed..e15314a5e 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -57,9 +58,10 @@ class pkgSourceList bool FixupURI(string &URI) const; virtual bool ParseLine(vector &List, const char *Buffer, - unsigned long CurLine,string File) const; - virtual bool CreateItem(vector &List,string URI, - string Dist,string Section) const = 0; + unsigned long const &CurLine,string const &File) const; + virtual bool CreateItem(vector &List,string const &URI, + string const &Dist,string const &Section, + std::map const &Options) const = 0; Type(); virtual ~Type() {}; }; diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index b4d1d4696..e5f0fafd2 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -100,6 +100,8 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type) RelLabel = Fragments[J]+2; else if (stringcasecmp(Fragments[J],Fragments[J]+2,"c=") == 0) RelComponent = Fragments[J]+2; + else if (stringcasecmp(Fragments[J],Fragments[J]+2,"b=") == 0) + RelArchitecture = Fragments[J]+2; } if (RelVerStr.end()[-1] == '*') @@ -178,7 +180,7 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (RelVerStr.empty() == true && RelOrigin.empty() == true && RelArchive.empty() == true && RelLabel.empty() == true && RelRelease.empty() == true && RelCodename.empty() == true && - RelComponent.empty() == true) + RelComponent.empty() == true && RelArchitecture.empty() == true) return false; if (RelVerStr.empty() == false) @@ -211,6 +213,10 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (File->Component == 0 || stringcasecmp(RelComponent,File.Component()) != 0) return false; + if (RelArchitecture.empty() == false) + if (File->Architecture == 0 || + stringcasecmp(RelArchitecture,File.Architecture()) != 0) + return false; return true; } diff --git a/apt-pkg/versionmatch.h b/apt-pkg/versionmatch.h index a8f3c84ac..a8da072ae 100644 --- a/apt-pkg/versionmatch.h +++ b/apt-pkg/versionmatch.h @@ -23,6 +23,7 @@ Codename (n=) e.g. etch, lenny, squeeze, sid Label (l=) Component (c=) + Binary Architecture (b=) If there are no equals signs in the string then it is scanned in short form - if it starts with a number it is Version otherwise it is an Archive or a Codename. @@ -55,6 +56,7 @@ class pkgVersionMatch string RelArchive; string RelLabel; string RelComponent; + string RelArchitecture; bool MatchAll; // Origin Matching -- cgit v1.2.3 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') 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 From 857e9c13d8d9808fcd1ac8ff3469f6c0b90b7fea Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 7 Feb 2010 12:38:13 +0100 Subject: Drop the Arch information from the Version structure as we can get the information from the parent package now --- apt-pkg/cacheiterators.h | 2 +- apt-pkg/deb/deblistparser.cc | 10 +++++++--- apt-pkg/deb/deblistparser.h | 1 + apt-pkg/pkgcache.cc | 4 ++-- apt-pkg/pkgcache.h | 1 - apt-pkg/pkgcachegen.h | 1 + 6 files changed, 12 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 33d2ed6be..d8e044f88 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -178,7 +178,7 @@ class pkgCache::VerIterator : public Iterator { // Accessors inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}; inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}; - inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;}; + inline const char *Arch() const {return S->ParentPkg == 0?0:Owner->StrP + ParentPkg()->Arch;}; inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}; inline DescIterator DescriptionList() const; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index f683de423..26841d3d2 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -83,6 +83,13 @@ string debListParser::Architecture() { return Result; } /*}}}*/ +// ListParser::ArchitectureAll /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debListParser::ArchitectureAll() { + return Section.FindS("Architecture") == "all"; +} + /*}}}*/ // ListParser::Version - Return the version string /*{{{*/ // --------------------------------------------------------------------- /* This is to return the string describing the version in debian form, @@ -101,9 +108,6 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) // Parse the section Ver->Section = UniqFindTagWrite("Section"); - // 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, diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index cba4f8e5d..8da051530 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -47,6 +47,7 @@ class debListParser : public pkgCacheGenerator::ListParser // These all operate against the current section virtual string Package(); virtual string Architecture(); + virtual bool ArchitectureAll(); virtual string Version(); virtual bool NewVersion(pkgCache::VerIterator Ver); virtual string Description(); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 1e4c7edb3..7d98869ea 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -399,7 +399,7 @@ const char * pkgCache::PkgIterator::CandVersion() const { //TargetVer is empty, so don't use it. - VerIterator version = pkgPolicy::pkgPolicy(Owner).GetCandidateVer(*this); + VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this); if (version.IsGood()) return version.VerStr(); return 0; @@ -727,7 +727,7 @@ string pkgCache::VerIterator::RelStr() Res += File.Site(); } } - if (S->Arch != 0) + if (S->ParentPkg != 0) Res.append(" [").append(Arch()).append("]"); return Res; } diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 5f50001d0..5edeedfd1 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -276,7 +276,6 @@ struct pkgCache::Version /*{{{*/ { map_ptrloc VerStr; // Stringtable map_ptrloc Section; // StringTable (StringItem) - map_ptrloc Arch; // StringTable enum {None, All, Foreign, Same, Allowed} MultiArch; // Lists diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 53f09b991..ca5d74a9f 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -112,6 +112,7 @@ class pkgCacheGenerator::ListParser // These all operate against the current section virtual string Package() = 0; virtual string Architecture() = 0; + virtual bool ArchitectureAll() = 0; virtual string Version() = 0; virtual bool NewVersion(pkgCache::VerIterator Ver) = 0; virtual string Description() = 0; -- cgit v1.2.3 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') 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 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') 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 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') 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 From 4d174dc84ea184b5afa81abb3b94e2ef3380ece8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Feb 2010 12:19:48 +0100 Subject: Add Multi-Arch: allowed support by creating an implicit provide of name:any for such packages, so dependencies in this style can be easily resolved. --- apt-pkg/deb/deblistparser.cc | 6 ++++++ apt-pkg/pkgcache.cc | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index b6082cdd5..3726a6a04 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -642,6 +642,12 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) } } + if (Ver->MultiArch == pkgCache::Version::Allowed) + { + string const Package = string(Ver.ParentPkg().Name()).append(":").append("any"); + NewProvides(Ver, Package, "any", Ver.VerStr()); + } + if (Ver->MultiArch != pkgCache::Version::Foreign) return true; diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 7d98869ea..2d4ee1010 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -186,7 +186,10 @@ 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)); + string const Arch = Name.substr(found+1); + if (Arch == "any") + return FindPkg(Name, "any"); + return FindPkg(Name.substr(0, found), Arch); } /*}}}*/ // Cache::FindPkg - Locate a package by name /*{{{*/ -- cgit v1.2.3 From c5dac10c3dd6d8f54d97d3105803d07fa891fcd4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Feb 2010 18:20:02 +0100 Subject: Arch() on a MultiArch:all version should return "all" to be compatible with previous usecases. You now need to requested with Arch(true) the return of the architecture this version (and pseudo package) was created for. --- apt-pkg/cacheiterators.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index d8e044f88..e8cf28496 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -178,7 +178,16 @@ class pkgCache::VerIterator : public Iterator { // Accessors inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}; inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}; - inline const char *Arch() const {return S->ParentPkg == 0?0:Owner->StrP + ParentPkg()->Arch;}; + inline const char *Arch() const { + if(S->MultiArch == pkgCache::Version::All) + return "all"; + return S->ParentPkg == 0?0:Owner->StrP + ParentPkg()->Arch; + }; + inline const char *Arch(bool const pseudo) const { + if(pseudo == false) + return Arch(); + return S->ParentPkg == 0?0:Owner->StrP + ParentPkg()->Arch; + }; inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}; inline DescIterator DescriptionList() const; -- cgit v1.2.3 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 +++++++++++++---- 10 files changed, 124 insertions(+), 17 deletions(-) (limited to 'apt-pkg') 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 -- cgit v1.2.3 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 ++- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'apt-pkg') 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()); -- cgit v1.2.3 From 4cc6f8dc52144f773b96ee99070d1be0821b984e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Feb 2010 01:59:22 +0100 Subject: * apt-pkg/deb/dpkgpm.cc: - stdin redirected to /dev/null takes all CPU (Closes: #569488) Thanks to Aurelien Jarno for providing (again) a patch! --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 565f01b84..3dca2b209 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1005,7 +1005,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) // wait for input or output here FD_ZERO(&rfds); - if (!stdin_is_dev_null) + if (master >= 0 && !stdin_is_dev_null) FD_SET(0, &rfds); FD_SET(_dpkgin, &rfds); if(master >= 0) -- cgit v1.2.3 From ee60a63480f7d1a963d7ef2a8e399d0f9b651d71 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 14 Feb 2010 22:24:55 +0100 Subject: Pseudo() doesn't work in the Cache generation step as the check if only one package is in the group will generate false positives - as the others will (maybe) added a little time later in the process. --- apt-pkg/deb/deblistparser.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index bfc0e762e..84eab44a7 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -155,9 +155,10 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) 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. */ + bool const static multiArch = APT::Configuration::getArchitectures().size() > 1; if (strcmp(Ver.Arch(true),"all") == 0) return true; - else if (Ver.Pseudo() == true) + else if (multiArch == true) { // our pseudo packages have no size to not confuse the fetcher Ver->Size = 0; -- cgit v1.2.3 From 83742b3cf4b541fd61533dfecdc97e0e4502a7a4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 14 Feb 2010 23:34:56 +0100 Subject: Add support for the LANGUAGE environment variable --- apt-pkg/aptconfiguration.cc | 91 +++++++++++++++++++++++++++++---------------- apt-pkg/aptconfiguration.h | 2 +- apt-pkg/contrib/strutl.cc | 2 +- 3 files changed, 61 insertions(+), 34 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 0fe84db74..f1989599b 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -8,10 +8,11 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#include #include #include +#include #include +#include #include #include @@ -97,7 +98,7 @@ const Configuration::getCompressionTypes(bool const &Cached) { will result in "de_DE, de, en". The special word "none" is the stopcode for the not-All code vector */ std::vector const Configuration::getLanguages(bool const &All, - bool const &Cached, char const * const Locale) { + bool const &Cached, char const ** const Locale) { using std::string; // The detection is boring and has a lot of cornercases, @@ -118,27 +119,29 @@ std::vector const Configuration::getLanguages(bool const &All, } } - // get the environment language code + // get the environment language codes: LC_MESSAGES (and later LANGUAGE) // we extract both, a long and a short code and then we will // check if we actually need both (rare) or if the short is enough - string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : Locale); + string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale); size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2; - size_t const lenLong = (envMsg.find('.') != string::npos) ? envMsg.find('.') : (lenShort + 3); + size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3); string envLong = envMsg.substr(0,lenLong); string const envShort = envLong.substr(0,lenShort); - bool envLongIncluded = true, envShortIncluded = false; + bool envLongIncluded = true; // first cornercase: LANG=C, so we use only "en" Translation if (envLong == "C") { codes.push_back("en"); + allCodes = codes; return codes; } + // to save the servers from unneeded queries, we only try also long codes + // for languages it is realistic to have a long code translation file… + // TODO: Improve translation acquire system to drop them dynamic + char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL }; if (envLong != envShort) { - // to save the servers from unneeded queries, we only try also long codes - // for languages it is realistic to have a long code translation file... - char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL }; for (char const **l = needLong; *l != NULL; l++) if (envShort.compare(*l) == 0) { envLongIncluded = false; @@ -156,33 +159,64 @@ std::vector const Configuration::getLanguages(bool const &All, if (oldAcquire.empty() == false && oldAcquire != "environment") { if (oldAcquire != "none") codes.push_back(oldAcquire); + allCodes = codes; return codes; } + // It is very likely we will need to environment codes later, + // so let us generate them now from LC_MESSAGES and LANGUAGE + std::vector environment; + // take care of LC_MESSAGES + if (envLongIncluded == false) + environment.push_back(envLong); + environment.push_back(envShort); + // take care of LANGUAGE + string envLang = Locale == 0 ? getenv("LANGUAGE") : *(Locale+1); + if (envLang.empty() == false) { + std::vector env = ExplodeString(envLang,':'); + short addedLangs = 0; // add a maximum of 3 fallbacks from the environment + for (std::vector::const_iterator e = env.begin(); + e != env.end() && addedLangs < 3; ++e) { + if (unlikely(e->empty() == true) || *e == "en") + continue; + if (*e == envLong || *e == envShort) + continue; + if (std::find(environment.begin(), environment.end(), *e) != environment.end()) + continue; + if (e->find('_') != string::npos) { + // Drop LongCodes here - ShortCodes are also included + string const shorty = e->substr(0, e->find('_')); + char const **n = needLong; + for (; *n != NULL; ++n) + if (shorty == *n) + break; + if (*n == NULL) + continue; + } + ++addedLangs; + environment.push_back(*e); + } + } + // Support settings like Acquire::Translation=none on the command line to // override the configuration settings vector of languages. string const forceLang = _config->Find("Acquire::Languages",""); if (forceLang.empty() == false) { if (forceLang == "environment") { - if (envLongIncluded == false) - codes.push_back(envLong); - if (envShortIncluded == false) - codes.push_back(envShort); - return codes; + codes = environment; } else if (forceLang != "none") codes.push_back(forceLang); + allCodes = codes; return codes; } std::vector const lang = _config->FindVector("Acquire::Languages"); // the default setting -> "environment, en" if (lang.empty() == true) { - if (envLongIncluded == false) - codes.push_back(envLong); - if (envShortIncluded == false) - codes.push_back(envShort); + codes = environment; if (envShort != "en") codes.push_back("en"); + allCodes = codes; return codes; } @@ -192,26 +226,19 @@ std::vector const Configuration::getLanguages(bool const &All, for (std::vector::const_iterator l = lang.begin(); l != lang.end(); l++) { if (*l == "environment") { - if (envLongIncluded == true && envShortIncluded == true) - continue; - if (envLongIncluded == false) { - envLongIncluded = true; - if (noneSeen == false) - codes.push_back(envLong); - allCodes.push_back(envLong); - } - if (envShortIncluded == false) { - envShortIncluded = true; + for (std::vector::const_iterator e = environment.begin(); + e != environment.end(); ++e) { + if (std::find(allCodes.begin(), allCodes.end(), *e) != allCodes.end()) + continue; if (noneSeen == false) - codes.push_back(envShort); - allCodes.push_back(envShort); + codes.push_back(*e); + allCodes.push_back(*e); } continue; } else if (*l == "none") { noneSeen = true; continue; - } else if ((envLongIncluded == true && *l == envLong) || - (envShortIncluded == true && *l == envShort)) + } else if (std::find(allCodes.begin(), allCodes.end(), *l) != allCodes.end()) continue; if (noneSeen == false) diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index b6650e20c..dd339d841 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -64,7 +64,7 @@ public: /*{{{*/ * \return a vector of (all) Language Codes in the prefered usage order */ std::vector static const getLanguages(bool const &All = false, - bool const &Cached = true, char const * const Locale = 0); + bool const &Cached = true, char const ** const Locale = 0); /** \brief Returns a vector of Architectures we support * diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index b285a9f2e..d3d6e2739 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1012,7 +1012,7 @@ vector ExplodeString(string const &haystack, char const &split) { do { for (; end != haystack.end() && *end != split; ++end); exploded.push_back(string(start, end)); - start = end; + start = end + 1; } while (end != haystack.end() && (++end) != haystack.end()); return exploded; } -- cgit v1.2.3 From 1a31359bfe4fdbf9ac1a25ab0b9f013d37099ac4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Feb 2010 13:05:53 +0100 Subject: * aptconfiguration.cc: - include all existing Translation files in the Cache (Closes: 564137) Previously if APT was executed with a different LC_* all these invocations needed to rebuild the Cache as too many files were included or missing: Now the lists-directory is checked for Translation-files and all these included in getLanguages() regardless of the environment setting (after a "none" so APT will not use them for displaying information). --- apt-pkg/aptconfiguration.cc | 78 +++++++++++++++++++++++++++++++++++++++++---- apt-pkg/deb/debmetaindex.cc | 5 ++- 2 files changed, 76 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index f1989599b..429219cbd 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -14,9 +14,12 @@ #include #include -#include -#include +#include +#include + #include +#include +#include /*}}}*/ namespace APT { // getCompressionTypes - Return Vector of usbale compressiontypes /*{{{*/ @@ -119,6 +122,37 @@ std::vector const Configuration::getLanguages(bool const &All, } } + // Include all Language codes we have a Translation file for in /var/lib/apt/lists + // so they will be all included in the Cache. + std::vector builtin; + DIR *D = opendir(_config->FindDir("Dir::State::lists").c_str()); + if (D != 0) { + builtin.push_back("none"); + for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D)) { + string const name = Ent->d_name; + size_t const foundDash = name.rfind("-"); + size_t const foundUnderscore = name.rfind("_"); + if (foundDash == string::npos || foundUnderscore == string::npos || + foundDash <= foundUnderscore || + name.substr(foundUnderscore+1, foundDash-(foundUnderscore+1)) != "Translation") + continue; + string const c = name.substr(foundDash+1); + if (unlikely(c.empty() == true) || c == "en") + continue; + // Skip unusual files, like backups or that alike + string::const_iterator s = c.begin(); + for (;s != c.end(); ++s) { + if (isalpha(*s) == 0) + break; + } + if (s != c.end()) + continue; + if (std::find(builtin.begin(), builtin.end(), c) != builtin.end()) + continue; + builtin.push_back(c); + } + } + // get the environment language codes: LC_MESSAGES (and later LANGUAGE) // we extract both, a long and a short code and then we will // check if we actually need both (rare) or if the short is enough @@ -134,7 +168,11 @@ std::vector const Configuration::getLanguages(bool const &All, if (envLong == "C") { codes.push_back("en"); allCodes = codes; - return codes; + allCodes.insert(allCodes.end(), builtin.begin(), builtin.end()); + if (All == true) + return allCodes; + else + return codes; } // to save the servers from unneeded queries, we only try also long codes @@ -159,8 +197,16 @@ std::vector const Configuration::getLanguages(bool const &All, if (oldAcquire.empty() == false && oldAcquire != "environment") { if (oldAcquire != "none") codes.push_back(oldAcquire); + codes.push_back("en"); allCodes = codes; - return codes; + for (std::vector::const_iterator b = builtin.begin(); + b != builtin.end(); ++b) + if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end()) + allCodes.push_back(*b); + if (All == true) + return allCodes; + else + return codes; } // It is very likely we will need to environment codes later, @@ -207,7 +253,14 @@ std::vector const Configuration::getLanguages(bool const &All, } else if (forceLang != "none") codes.push_back(forceLang); allCodes = codes; - return codes; + for (std::vector::const_iterator b = builtin.begin(); + b != builtin.end(); ++b) + if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end()) + allCodes.push_back(*b); + if (All == true) + return allCodes; + else + return codes; } std::vector const lang = _config->FindVector("Acquire::Languages"); @@ -217,7 +270,14 @@ std::vector const Configuration::getLanguages(bool const &All, if (envShort != "en") codes.push_back("en"); allCodes = codes; - return codes; + for (std::vector::const_iterator b = builtin.begin(); + b != builtin.end(); ++b) + if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end()) + allCodes.push_back(*b); + if (All == true) + return allCodes; + else + return codes; } // the configs define the order, so add the environment @@ -245,6 +305,12 @@ std::vector const Configuration::getLanguages(bool const &All, codes.push_back(*l); allCodes.push_back(*l); } + + for (std::vector::const_iterator b = builtin.begin(); + b != builtin.end(); ++b) + if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end()) + allCodes.push_back(*b); + if (All == true) return allCodes; else diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index eb01a0156..0e4e6df9e 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -214,6 +214,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const s != sections.end(); ++s) for (set::const_iterator l = s->second.begin(); l != s->second.end(); l++) { + if (*l == "none") continue; debTranslationsIndex i = debTranslationsIndex(URI,Dist,s->first,(*l).c_str()); i.GetIndexes(Owner); } @@ -268,8 +269,10 @@ vector *debReleaseIndex::GetIndexFiles() { for (map >::const_iterator s = sections.begin(); s != sections.end(); ++s) for (set::const_iterator l = s->second.begin(); - l != s->second.end(); l++) + l != s->second.end(); l++) { + if (*l == "none") continue; Indexes->push_back(new debTranslationsIndex(URI,Dist,s->first,(*l).c_str())); + } return Indexes; } -- cgit v1.2.3 From b7044b4b7483259f6dbca4fce56320dbde6da02a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 18 Feb 2010 00:55:35 +0100 Subject: doesn't use a default separator in ExplodeString (halfway losted in merge) --- apt-pkg/deb/debmetaindex.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 0e4e6df9e..947a7f04b 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -313,7 +313,7 @@ class debSLTypeDebian : public pkgSourceList::Type { map::const_iterator const arch = Options.find("arch"); vector const Archs = - (arch != Options.end()) ? ExplodeString(arch->second) : + (arch != Options.end()) ? ExplodeString(arch->second, ',') : APT::Configuration::getArchitectures(); for (vector::const_iterator I = List.begin(); -- cgit v1.2.3 From 75ce206243e409b170d06723430eb85a4a747882 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 26 Feb 2010 20:47:19 +0100 Subject: move ShowPkg() from apt-get to the PkgIterator and rename it to FullName() responseable for displaying a package name and the architecture in a uniform way. Pretty option can be used to not append the architecture if it is the native architecture or all - and use it all over the place in the commandline tools. --- apt-pkg/cacheiterators.h | 1 + apt-pkg/pkgcache.cc | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 43cbe1377..a64326a44 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -151,6 +151,7 @@ class pkgCache::PkgIterator: public Iterator { //Nice printable representation friend std::ostream& operator <<(std::ostream& out, PkgIterator i); + std::string FullName(bool const &Pretty = false) const; // Constructors inline PkgIterator(pkgCache &Owner,Package *Trg) : Iterator(Owner, Trg), HashIndex(0) { diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 29c27b58e..24d9e0329 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -445,6 +445,18 @@ operator<<(ostream& out, pkgCache::PkgIterator Pkg) return out; } /*}}}*/ +// PkgIterator::FullName - Returns Name and (maybe) Architecture /*{{{*/ +// --------------------------------------------------------------------- +/* Returns a name:arch string */ +std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const +{ + string fullname = Name(); + if (Pretty == false || + (strcmp(Arch(), "all") != 0 && _config->Find("APT::Architecture") != Arch())) + return fullname.append(":").append(Arch()); + return fullname; +} + /*}}}*/ // DepIterator::IsCritical - Returns true if the dep is important /*{{{*/ // --------------------------------------------------------------------- /* Currently critical deps are defined as depends, predepends and -- cgit v1.2.3 From e0b94b97b179812e5a0b3b72ea9fcae106d545c5 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 27 Feb 2010 17:01:12 +0100 Subject: Enable the AutoRemover to talk "Multi-Arch" by marking all pseudo packages in a group if one is marked. The auto-installed flag is from now on Architecture bound: A section without an architecture tag will be treated as applying to all architectures - the next write operation will take care of this by creating separate sections for the architectures. --- apt-pkg/depcache.cc | 170 +++++++++++++++++++++++++++++++++------------------- apt-pkg/depcache.h | 4 +- 2 files changed, 109 insertions(+), 65 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index eeb74a434..45c614c6f 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -165,34 +165,46 @@ bool pkgDepCache::Init(OpProgress *Prog) bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ { FileFd state_file; - string state = _config->FindDir("Dir::State") + "extended_states"; + string const state = _config->FindDir("Dir::State") + "extended_states"; if(FileExists(state)) { state_file.Open(state, FileFd::ReadOnly); - int file_size = state_file.Size(); + int const file_size = state_file.Size(); if(Prog != NULL) Prog->OverallProgress(0, file_size, 1, _("Reading state information")); pkgTagFile tagfile(&state_file); pkgTagSection section; - int amt=0; - bool debug_autoremove=_config->FindB("Debug::pkgAutoRemove",false); + int amt = 0; + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); while(tagfile.Step(section)) { - string pkgname = section.FindS("Package"); - pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname); - // Silently ignore unknown packages and packages with no actual - // version. - if(!pkg.end() && !pkg.VersionList().end()) { - short reason = section.FindI("Auto-Installed", 0); - if(reason > 0) - PkgState[pkg->ID].Flags |= Flag::Auto; - if(debug_autoremove) - std::cout << "Auto-Installed : " << pkgname << std::endl; - amt+=section.size(); - if(Prog != NULL) - Prog->OverallProgress(amt, file_size, 1, - _("Reading state information")); + string const pkgname = section.FindS("Package"); + string pkgarch = section.FindS("Architecture"); + if (pkgarch.empty() == true) + pkgarch = "any"; + pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch); + // Silently ignore unknown packages and packages with no actual version. + if(pkg.end() == true || pkg->VersionList == 0) + continue; + + short const reason = section.FindI("Auto-Installed", 0); + if(reason > 0) + { + PkgState[pkg->ID].Flags |= Flag::Auto; + if (unlikely(debug_autoremove)) + std::cout << "Auto-Installed : " << pkg.FullName() << std::endl; + if (pkgarch == "any") + { + pkgCache::GrpIterator G = pkg.Group(); + for (pkg = G.NextPkg(pkg); pkg.end() != true; pkg = G.NextPkg(pkg)) + if (pkg->VersionList != 0) + PkgState[pkg->ID].Flags |= Flag::Auto; + } } + amt += section.size(); + if(Prog != NULL) + Prog->OverallProgress(amt, file_size, 1, + _("Reading state information")); } if(Prog != NULL) Prog->OverallProgress(file_size, file_size, 1, @@ -204,13 +216,13 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ /*}}}*/ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ { - bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); if(debug_autoremove) std::clog << "pkgDepCache::writeStateFile()" << std::endl; FileFd StateFile; - string state = _config->FindDir("Dir::State") + "extended_states"; + string const state = _config->FindDir("Dir::State") + "extended_states"; // if it does not exist, create a empty one if(!FileExists(state)) @@ -225,7 +237,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ state.c_str()); FILE *OutFile; - string outfile = state + ".tmp"; + string const outfile = state + ".tmp"; if((OutFile = fopen(outfile.c_str(),"w")) == NULL) return _error->Error(_("Failed to write temporary StateFile %s"), outfile.c_str()); @@ -236,46 +248,54 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ std::set pkgs_seen; const char *nullreorderlist[] = {0}; while(tagfile.Step(section)) { - string pkgname = section.FindS("Package"); + string const pkgname = section.FindS("Package"); + string pkgarch = section.FindS("Architecture"); + if (pkgarch.empty() == true) + pkgarch = "native"; // Silently ignore unknown packages and packages with no actual // version. - pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname); + pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch); if(pkg.end() || pkg.VersionList().end()) continue; - bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto); + bool const newAuto = (PkgState[pkg->ID].Flags & Flag::Auto); if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "Update existing AutoInstall info: " - << pkg.Name() << std::endl; - TFRewriteData rewrite[2]; - rewrite[0].Tag = "Auto-Installed"; - rewrite[0].Rewrite = newAuto ? "1" : "0"; + << pkg.FullName() << std::endl; + TFRewriteData rewrite[3]; + rewrite[0].Tag = "Architecture"; + rewrite[0].Rewrite = pkg.Arch(); rewrite[0].NewTag = 0; - rewrite[1].Tag = 0; + rewrite[1].Tag = "Auto-Installed"; + rewrite[1].Rewrite = newAuto ? "1" : "0"; + rewrite[1].NewTag = 0; + rewrite[2].Tag = 0; TFRewrite(OutFile, section, nullreorderlist, rewrite); fprintf(OutFile,"\n"); - pkgs_seen.insert(pkgname); + pkgs_seen.insert(pkg.FullName()); } // then write the ones we have not seen yet std::ostringstream ostr; for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) { if(PkgState[pkg->ID].Flags & Flag::Auto) { - if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) { + if (pkgs_seen.find(pkg.FullName()) != pkgs_seen.end()) { if(debug_autoremove) - std::clog << "Skipping already written " << pkg.Name() << std::endl; + std::clog << "Skipping already written " << pkg.FullName() << std::endl; continue; } - // skip not installed ones if requested - if(InstalledOnly && pkg->CurrentVer == 0) - continue; + // skip not installed ones if requested + if(InstalledOnly && pkg->CurrentVer == 0) + continue; + const char* const pkgarch = pkg.Arch(); + if (strcmp(pkgarch, "all") == 0) + continue; if(debug_autoremove) - std::clog << "Writing new AutoInstall: " - << pkg.Name() << std::endl; + std::clog << "Writing new AutoInstall: " << pkg.FullName() << std::endl; ostr.str(string("")); - ostr << "Package: " << pkg.Name() + ostr << "Package: " << pkg.Name() + << "\nArchitecture: " << pkgarch << "\nAuto-Installed: 1\n\n"; fprintf(OutFile,"%s",ostr.str().c_str()); - fprintf(OutFile,"\n"); } } fclose(OutFile); @@ -1426,7 +1446,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) // debug output if(debug_autoremove && PkgState[p->ID].Flags & Flag::Auto) - std::clog << "AutoDep: " << p.Name() << std::endl; + std::clog << "AutoDep: " << p.FullName() << std::endl; } // init vars @@ -1460,13 +1480,18 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) // MarkPackage - mark a single package in Mark-and-Sweep /*{{{*/ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, const pkgCache::VerIterator &ver, - bool follow_recommends, - bool follow_suggests) + bool const &follow_recommends, + bool const &follow_suggests) { pkgDepCache::StateCache &state = PkgState[pkg->ID]; - VerIterator currver = pkg.CurrentVer(); - VerIterator candver = state.CandidateVerIter(*this); - VerIterator instver = state.InstVerIter(*this); + + // if we are marked already we are done + if(state.Marked) + return; + + VerIterator const currver = pkg.CurrentVer(); + VerIterator const candver = state.CandidateVerIter(*this); + VerIterator const instver = state.InstVerIter(*this); #if 0 // If a package was garbage-collected but is now being marked, we @@ -1492,15 +1517,11 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, !(ver == currver && instver.end() && !ver.end())) return; - // if we are marked already we are done - if(state.Marked) - return; + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false); - bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false); - if(debug_autoremove) { - std::clog << "Marking: " << pkg.Name(); + std::clog << "Marking: " << pkg.FullName(); if(!ver.end()) std::clog << " " << ver.VerStr(); if(!currver.end()) @@ -1512,8 +1533,34 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, state.Marked=true; - if(!ver.end()) + if(ver.end() == true) + return; + + // If the version belongs to a Multi-Arch all package + // we will mark all others in this Group with this version also + // Beware: We compare versions here the lazy way: string comparision + // this is bad if multiple repositories provide different versions + // of the package with an identical version number - but even in this + // case the dependencies are likely the same. + if (ver->MultiArch == pkgCache::Version::All && + strcmp(ver.Arch(true), "all") == 0) { + GrpIterator G = pkg.Group(); + const char* const VerStr = ver.VerStr(); + for (PkgIterator P = G.FindPkg("any"); + P.end() != true; P = G.NextPkg(P)) + { + for (VerIterator V = P.VersionList(); + V.end() != true; ++V) + { + if (strcmp(VerStr, V.VerStr()) != 0) + continue; + MarkPackage(P, V, follow_recommends, follow_suggests); + break; + } + } + } + for(DepIterator d = ver.DependsList(); !d.end(); ++d) { if(d->Type == Dep::Depends || @@ -1531,10 +1578,9 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, { if(debug_autoremove) { - std::clog << "Following dep: " << d.ParentPkg().Name() + std::clog << "Following dep: " << d.ParentPkg().FullName() << " " << d.ParentVer().VerStr() << " " - << d.DepType() << " " - << d.TargetPkg().Name(); + << d.DepType() << " " << d.TargetPkg().FullName(); if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp) { std::clog << " (" << d.CompType() << " " @@ -1542,7 +1588,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, } std::clog << std::endl; } - MarkPackage(V.ParentPkg(), V, + MarkPackage(V.ParentPkg(), V, follow_recommends, follow_suggests); } } @@ -1555,17 +1601,16 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, { if(debug_autoremove) { - std::clog << "Following dep: " << d.ParentPkg().Name() - << " " << d.ParentVer().VerStr() << " " - << d.DepType() << " " - << d.TargetPkg().Name(); + std::clog << "Following dep: " << d.ParentPkg().FullName() << " " + << d.ParentVer().VerStr() << " " + << d.DepType() << " " << d.TargetPkg().FullName() << " "; if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp) { std::clog << " (" << d.CompType() << " " << d.TargetVer() << ")"; } std::clog << ", provided by " - << prv.OwnerPkg().Name() << " " + << prv.OwnerPkg().FullName() << " " << prv.OwnerVer().VerStr() << std::endl; } @@ -1576,7 +1621,6 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, } } } - } } /*}}}*/ bool pkgDepCache::Sweep() /*{{{*/ @@ -1598,7 +1642,7 @@ bool pkgDepCache::Sweep() /*{{{*/ { state.Garbage=true; if(debug_autoremove) - std::cout << "Garbage: " << p.Name() << std::endl; + std::cout << "Garbage: " << p.FullName() << std::endl; } } diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index ab1021a44..23b29cc13 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -79,8 +79,8 @@ class pkgDepCache : protected pkgCache::Namespace */ void MarkPackage(const pkgCache::PkgIterator &pkg, const pkgCache::VerIterator &ver, - bool follow_recommends, - bool follow_suggests); + bool const &follow_recommends, + bool const &follow_suggests); /** \brief Update the Marked field of all packages. * -- cgit v1.2.3 From a04cd1f9a580867d65be8f1ecb3eac25a86eb953 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 28 Feb 2010 19:45:05 +0100 Subject: Fix the PkgFileIterator Constructor which defaults to the wrong value. (0 instead of the HeaderP) This breaks the Cache Validation functionality as the end() doesn't test for NULL. (The fault was introduced with the rewriting of the CacheIterators) --- apt-pkg/cacheiterators.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index a64326a44..28e062f3c 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -345,7 +345,8 @@ class pkgCache::PkgFileIterator : public Iterator // Constructors inline PkgFileIterator() : Iterator() {}; - inline PkgFileIterator(pkgCache &Owner,PackageFile *Trg = 0) : Iterator(Owner, Trg) {}; + inline PkgFileIterator(pkgCache &Owner) : Iterator(Owner, Owner.PkgFileP) {}; + inline PkgFileIterator(pkgCache &Owner,PackageFile *Trg) : Iterator(Owner, Trg) {}; }; /*}}}*/ // Version File /*{{{*/ -- cgit v1.2.3 From 4a6d21639f807ae82d5a51a92c4bbbd0ca2a4494 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 28 Feb 2010 22:45:34 +0100 Subject: Create Pins for all group members instead of only for native architecture --- apt-pkg/policy.cc | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index f9901bc9a..0b8c1a81b 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -187,35 +187,38 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator Pkg) void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, string Data,signed short Priority) { - Pin *P = 0; - if (Name.empty() == true) - P = &*Defaults.insert(Defaults.end(),PkgPin()); - else { - // Get a spot to put the pin - pkgCache::PkgIterator Pkg = Cache->FindPkg(Name); - if (Pkg.end() == true) + Pin *P = &*Defaults.insert(Defaults.end(),PkgPin()); + P->Type = Type; + P->Priority = Priority; + P->Data = Data; + return; + } + + // Get a spot to put the pin + pkgCache::GrpIterator Grp = Cache->FindGrp(Name); + for (pkgCache::PkgIterator Pkg = Grp.FindPkg("any"); + Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) + { + Pin *P = 0; + if (Pkg.end() == false) + P = Pins + Pkg->ID; + else { // Check the unmatched table - for (vector::iterator I = Unmatched.begin(); + for (vector::iterator I = Unmatched.begin(); I != Unmatched.end() && P == 0; I++) if (I->Pkg == Name) P = &*I; - + if (P == 0) - P = &*Unmatched.insert(Unmatched.end(),PkgPin()); + P = &*Unmatched.insert(Unmatched.end(),PkgPin()); } - else - { - P = Pins + Pkg->ID; - } + P->Type = Type; + P->Priority = Priority; + P->Data = Data; } - - // Set.. - P->Type = Type; - P->Priority = Priority; - P->Data = Data; } /*}}}*/ // Policy::GetMatch - Get the matching version for a package pin /*{{{*/ -- cgit v1.2.3 From 70ae240915df3ef89715d71d5fe7a6910cbf057e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 1 Mar 2010 15:27:55 +0100 Subject: Remove and Unpack operations should not be ignored for pseudo packages - they should trigger the remove/unpack of the "all" package. Otherwise - as this package has no dependencies - it will be triggered to late. The Configuration step doesn't need it as the "all" package is a dependency of the pseudo-package, so it will be configured before the pseudo packages are tried: So at this step the ignorance is okay. Also IsMissing() should report the status of the all package if an pseudo package is checked instead of always reporting no-miss. --- apt-pkg/orderlist.cc | 11 ++++++----- apt-pkg/packagemanager.cc | 13 +++++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc index 2e7618b55..7c950292a 100644 --- a/apt-pkg/orderlist.cc +++ b/apt-pkg/orderlist.cc @@ -127,8 +127,9 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg) if (FileList[Pkg->ID].empty() == false) return false; + // Missing Pseudo packages are missing if the real package is missing if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true) - return false; + return IsMissing(Pkg.Group().FindPkg("all")); return true; } @@ -203,7 +204,7 @@ bool pkgOrderList::OrderCritical() { PkgIterator P(Cache,*I); if (IsNow(P) == true) - clog << " " << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl; + clog << " " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl; } } @@ -276,7 +277,7 @@ bool pkgOrderList::OrderUnpack(string *FileList) { PkgIterator P(Cache,*I); if (IsNow(P) == true) - clog << " " << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl; + clog << " " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl; } } @@ -547,7 +548,7 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg) if (Debug == true) { for (int j = 0; j != Depth; j++) clog << ' '; - clog << "Visit " << Pkg.Name() << endl; + clog << "Visit " << Pkg.FullName() << endl; } Depth++; @@ -606,7 +607,7 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg) if (Debug == true) { for (int j = 0; j != Depth; j++) clog << ' '; - clog << "Leave " << Pkg.Name() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl; + clog << "Leave " << Pkg.FullName() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl; } return true; diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index db882721e..35cc24550 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -470,6 +470,8 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg) if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false) return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge); + else + return SmartRemove(Pkg.Group().FindPkg("all")); return true; } /*}}}*/ @@ -584,11 +586,14 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) for (PrvIterator P = Cache[Pkg].InstVerIter(Cache).ProvidesList(); P.end() == false; P++) CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); - - if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false && - Install(Pkg,FileNames[Pkg->ID]) == false) + + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false) + { + if(Install(Pkg,FileNames[Pkg->ID]) == false) + return false; + } else if (SmartUnPack(Pkg.Group().FindPkg("all")) == false) return false; - + List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); // Perform immedate configuration of the package. -- cgit v1.2.3 From 1ec1653cd4849423e0d5f769ecbfab2d6f16c4ad Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 1 Mar 2010 21:59:03 +0100 Subject: We need to kill also pseudo packages which have no dependency, no installed reverse dependency and which also doesn't provide something. They cause problems if this pseudo packages get new dependencies. As a consequence we also need to recheck the dependencies of a killed pseudo package (and especially the providers of these dependencies) to really kill all non required packages. --- apt-pkg/depcache.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++--------- apt-pkg/depcache.h | 1 + 2 files changed, 66 insertions(+), 12 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 45c614c6f..893164ea1 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -630,11 +630,46 @@ bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::setMultiArch != Version::All) return false; - unsigned char const DepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); - if ((DepState & DepInstMin) == DepInstMin) + // Never ever kill an "all" package - they have no dependency so they can't be broken + if (strcmp(Pkg.Arch(),"all") == 0) return false; - // Dependencies for this arch all are not statisfied +// std::cout << "CHECK " << Pkg << std::endl; + + unsigned char const DepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); + if ((DepState & DepInstMin) == DepInstMin) { + // okay, the package isn't broken, but is the package also required? + // If it has no real dependencies, no installed rdepends and doesn't + // provide something of value, we will kill it as not required. + // These pseudopackages have otherwise interesting effects if they get + // a new dependency in a newer version… + for (pkgCache::DepIterator D = V.DependsList(); + D.end() != true; ++D) + if ((D->Type == pkgCache::Dep::Depends || + D->Type == pkgCache::Dep::PreDepends) && + D.ParentPkg()->Group != Pkg->Group) + return false; + for (DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D) + { + if (D->Type != pkgCache::Dep::Depends && + D->Type != pkgCache::Dep::PreDepends) + continue; + PkgIterator const P = D.ParentPkg(); + if (P->CurrentVer != 0) + return false; + } + 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 && + P->Group != Pkg->Group) + return false; + } + } + + // Dependencies for this arch all package are not statisfied // so we installed it only for our convenience: get right of it now. RemoveSizes(Pkg); RemoveStates(Pkg); @@ -655,15 +690,33 @@ bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::setCurrentVer != 0) - recheck.insert(P.Index()); - } + for (DepIterator d = V.DependsList(); d.end() != true; ++d) + { + PkgIterator const P = d.TargetPkg(); + for (PrvIterator Prv = P.ProvidesList(); Prv.end() != true; ++Prv) + { + PkgIterator const O = Prv.OwnerPkg(); + if (O->CurrentVer != 0) + recheck.insert(O.Index()); + } + + if (P->CurrentVer != 0) + recheck.insert(P.Index()); + } + + 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) + continue; + + recheck.insert(P.Index()); + } + } + return true; } diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 23b29cc13..ea605f199 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -332,6 +332,7 @@ class pkgDepCache : protected pkgCache::Namespace inline operator pkgCache &() {return *Cache;}; inline Header &Head() {return *Cache->HeaderP;}; inline PkgIterator PkgBegin() {return Cache->PkgBegin();}; + inline GrpIterator FindGrp(string const &Name) {return Cache->FindGrp(Name);}; inline PkgIterator FindPkg(string const &Name) {return Cache->FindPkg(Name);}; inline PkgIterator FindPkg(string const &Name, string const &Arch) {return Cache->FindPkg(Name, Arch);}; -- cgit v1.2.3 From 5e5d20643487fd1693af418bd1201be5802c232d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 1 Mar 2010 22:47:17 +0100 Subject: fix compiler error if compiled with -std=c++0x --- apt-pkg/algorithms.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index c905cffa9..f8a9e210c 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -535,11 +535,11 @@ void pkgProblemResolver::MakeScores() // Important Required Standard Optional Extra signed short PrioMap[] = { 0, - _config->FindI("pkgProblemResolver::Scores::Important",3), - _config->FindI("pkgProblemResolver::Scores::Required",2), - _config->FindI("pkgProblemResolver::Scores::Standard",1), - _config->FindI("pkgProblemResolver::Scores::Optional",-1), - _config->FindI("pkgProblemResolver::Scores::Extra",-2) + (signed short) _config->FindI("pkgProblemResolver::Scores::Important",3), + (signed short) _config->FindI("pkgProblemResolver::Scores::Required",2), + (signed short) _config->FindI("pkgProblemResolver::Scores::Standard",1), + (signed short) _config->FindI("pkgProblemResolver::Scores::Optional",-1), + (signed short) _config->FindI("pkgProblemResolver::Scores::Extra",-2) }; signed short PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100); signed short PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1); -- cgit v1.2.3 From 1f530ccb32c17b70b05dd5feee706dc1098a7251 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 14 Mar 2010 14:45:00 +0100 Subject: Ensure that for each all package at least one pseudopackage is installed Removing pseudo packages is cool so far, the problem is that we will remove with the not required removing so many pseudo packages that we will have after the remove a few packages with NO installed pseudo package (e.g. metapackages are good candidates) - so we will walk over all these packages and try to find a pseudopackage for this package we can install without breaking something. --- apt-pkg/depcache.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 9 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 893164ea1..ffa4fe71c 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -634,10 +634,8 @@ bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::setType == pkgCache::Dep::Depends || - D->Type == pkgCache::Dep::PreDepends) && - D.ParentPkg()->Group != Pkg->Group) + if (D.IsCritical() == true && D.ParentPkg()->Group != Pkg->Group) return false; for (DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D) { - if (D->Type != pkgCache::Dep::Depends && - D->Type != pkgCache::Dep::PreDepends) + if (D.IsCritical() == false) continue; PkgIterator const P = D.ParentPkg(); + if (P->Group == Pkg->Group) + continue; if (P->CurrentVer != 0) return false; } @@ -800,6 +797,68 @@ void pkgDepCache::Update(OpProgress *Prog) } recheck.erase(p); } + + /* Okay, we have killed a great amount of pseudopackages - + we have killed so many that we have now arch "all" packages + without an installed pseudo package, but we NEED an installed + pseudo package, so we will search now for a pseudo package + we can install without breaking everything. */ + for (GrpIterator G = Cache->GrpBegin(); G.end() != true; ++G) + { + PkgIterator P = G.FindPkg("all"); + if (P.end() == true) + continue; + if (P->CurrentVer == 0) + continue; + bool installed = false; + for (P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (P->CurrentVer == 0) + continue; + installed = true; + break; + } + if (installed == false) + recheck.insert(G.Index()); + } + std::vector Archs = APT::Configuration::getArchitectures(); + bool checkChanged = false; + do { + for(std::set::const_iterator g = recheck.begin(); + g != recheck.end(); ++g) { + GrpIterator G = GrpIterator(*Cache, Cache->GrpP + *g); + VerIterator allV = G.FindPkg("all").CurrentVer(); + for (std::vector::const_iterator a = Archs.begin(); + a != Archs.end(); ++a) + { + PkgIterator P = G.FindPkg(*a); + if (P.end() == true) continue; + for (VerIterator V = P.VersionList(); V.end() != true; ++V) + { + // FIXME: String comparison isn't a save indicator! + if (strcmp(allV.VerStr(),V.VerStr()) != 0) + continue; + unsigned char const CurDepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); + if ((CurDepState & DepInstMin) != DepInstMin) + break; // we found the correct version, but it is broken. Better try another arch or later again + P->CurrentVer = V.Index(); + AddStates(P); + Update(P); + AddSizes(P); + checkChanged = true; + break; + } + } + recheck.erase(g); + } + } while (checkChanged == true && recheck.empty() == false); + + if (_config->FindB("Debug::MultiArchKiller", false) == true) + for(std::set::const_iterator g = recheck.begin(); + g != recheck.end(); ++g) + std::cout << "No pseudo package for »" << GrpIterator(*Cache, Cache->GrpP + *g).Name() << "« installed" << std::endl; } if (Prog != 0) -- cgit v1.2.3 From 306eacf617b8ea8c87b31258c55a5373be4ad946 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 18 Mar 2010 18:07:51 +0100 Subject: generate "negative" dependencies against all architectures of a package Negative means here Conflicts, Replaces and Breaks - this adds again a whole lot of dependencies. --- apt-pkg/deb/deblistparser.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 84eab44a7..5c9cf6d4b 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -609,7 +609,10 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, const char *Stop; if (Section.Find(Tag,Start,Stop) == false) return true; - + + static std::vector const archs = APT::Configuration::getArchitectures(); + static bool const multiArch = archs.size() <= 1; + string Package; string const pkgArch = Ver.Arch(true); string Version; @@ -620,8 +623,18 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, Start = ParseDepends(Start,Stop,Package,Version,Op); if (Start == 0) return _error->Error("Problem parsing dependency %s",Tag); - - if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) + + if (multiArch == true && + (Type == pkgCache::Dep::Conflicts || + Type == pkgCache::Dep::DpkgBreaks || + Type == pkgCache::Dep::Replaces)) + { + for (std::vector::const_iterator a = archs.begin(); + a != archs.end(); ++a) + if (NewDepends(Ver,Package,*a,Version,Op,Type) == false) + return false; + } + else if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) return false; if (Start == Stop) break; -- cgit v1.2.3 From 8d4c859d0d20687a8ffcf9e1d60466d061c2e24d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 18 Mar 2010 18:51:14 +0100 Subject: Readd the FindPkg() method implementation used in the singleArch days to use it as a fallback if multiarch is not enabled. The effect is barly noticeable but SingleArch is the realworld scenario. --- apt-pkg/pkgcache.cc | 30 +++++++++++++++++++++++++++++- apt-pkg/pkgcache.h | 8 +++++++- 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 24d9e0329..fe8757ded 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -108,6 +108,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const /* */ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) { + MultiArchEnabled = APT::Configuration::getArchitectures().size() > 1; if (DoMap == true) ReMap(); } @@ -178,11 +179,31 @@ unsigned long pkgCache::sHash(const char *Str) const return Hash % _count(HeaderP->PkgHashTable); } + /*}}}*/ +// 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->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); + } + return PkgIterator(*this,0); +} /*}}}*/ // Cache::FindPkg - Locate a package by name /*{{{*/ // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { + if (MultiArchCache() == false) + return SingleArchFindPkg(Name); size_t const found = Name.find(':'); if (found == string::npos) return FindPkg(Name, "native"); @@ -195,7 +216,14 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { // 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) { +pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) { + if (MultiArchCache() == false) { + if (Arch == "native" || Arch == "all" || + Arch == _config->Find("APT::Architecture")) + return SingleArchFindPkg(Name); + else + return PkgIterator(*this,0); + } /* We make a detour via the GrpIterator here as on a multi-arch environment a group is easier to find than a package (less entries in the buckets) */ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 012caac76..577eebad9 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -126,7 +126,7 @@ class pkgCache /*{{{*/ // Accessors GrpIterator FindGrp(const string &Name); PkgIterator FindPkg(const string &Name); - PkgIterator FindPkg(const string &Name, string Arch); + PkgIterator FindPkg(const string &Name, const string &Arch); Header &Head() {return *HeaderP;}; inline GrpIterator GrpBegin(); @@ -136,6 +136,8 @@ class pkgCache /*{{{*/ inline PkgFileIterator FileBegin(); inline PkgFileIterator FileEnd(); + inline bool MultiArchCache() const { return MultiArchEnabled; }; + // Make me a function pkgVersioningSystem *VS; @@ -146,6 +148,10 @@ class pkgCache /*{{{*/ pkgCache(MMap *Map,bool DoMap = true); virtual ~pkgCache() {}; + +private: + bool MultiArchEnabled; + PkgIterator SingleArchFindPkg(const string &Name); }; /*}}}*/ // Header structure /*{{{*/ -- cgit v1.2.3