- backport forgotten Valid-Until patch from the obsolete experimental
authorDavid Kalnischkies <kalnischkies@gmail.com>
Wed, 9 Jun 2010 08:52:45 +0000 (10:52 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Wed, 9 Jun 2010 08:52:45 +0000 (10:52 +0200)
    branch to prevent replay attacks better, thanks to Thomas Viehmann
    for the initial patch! (Closes: #499897)
* doc/apt.conf.5.xml:
  - document the new Valid-Until related options
* apt-pkg/contrib/strutl.cc:
  - split StrToTime() into HTTP1.1 and FTP date parser methods and
    use strptime() instead of some self-made scanf mangling
  - use the portable timegm shown in his manpage instead of a strange
    looking code copycat from wget
* ftparchive/writer.cc:
  - add ValidTime option to generate a Valid-Until header in Release file

41 files changed:
apt-inst/deb/dpkgdb.cc
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
apt-pkg/acquire.cc
apt-pkg/acquire.h
apt-pkg/aptconfiguration.cc
apt-pkg/cachefile.cc
apt-pkg/cachefile.h
apt-pkg/cacheiterators.h
apt-pkg/cacheset.cc [new file with mode: 0644]
apt-pkg/cacheset.h [new file with mode: 0644]
apt-pkg/contrib/cmndline.cc
apt-pkg/deb/debindexfile.cc
apt-pkg/deb/debindexfile.h
apt-pkg/deb/deblistparser.cc
apt-pkg/deb/debsystem.cc
apt-pkg/deb/dpkgpm.cc
apt-pkg/deb/dpkgpm.h
apt-pkg/depcache.cc
apt-pkg/depcache.h
apt-pkg/indexfile.h
apt-pkg/indexrecords.cc
apt-pkg/indexrecords.h
apt-pkg/makefile
apt-pkg/pkgcache.cc
apt-pkg/pkgcache.h
apt-pkg/pkgcachegen.cc
apt-pkg/pkgcachegen.h
apt-pkg/tagfile.cc
apt-pkg/tagfile.h
cmdline/apt-cache.cc
cmdline/apt-extracttemplates.cc
cmdline/apt-get.cc
debian/changelog
doc/apt-mark.8.xml
doc/apt.ent
doc/examples/configure-index
ftparchive/writer.h
test/libapt/getarchitectures_test.cc [new file with mode: 0644]
test/libapt/makefile
test/libapt/run-tests.sh

index e51e4f8..a75cf59 100644 (file)
@@ -142,7 +142,7 @@ bool debDpkgDB::ReadyPkgCache(OpProgress &Progress)
       CacheMap = 0;
    }
    
-   if (pkgMakeOnlyStatusCache(Progress,&CacheMap) == false)
+   if (pkgCacheGenerator::MakeOnlyStatusCache(&Progress,&CacheMap) == false)
       return false;
    Cache->DropProgress();
    
index ac84c2e..629d572 100644 (file)
@@ -1106,13 +1106,16 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)                         /*{{{*/
             return;
          }
       }
-      
-      // Queue Packages file (either diff or full packages files, depending
-      // on the users option)
-      if(_config->FindB("Acquire::PDiffs",true) == true) 
+
+      /* Queue Packages file (either diff or full packages files, depending
+         on the users option) - we also check if the PDiff Index file is listed
+         in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this
+         instead, but passing the required info to it is to much hassle */
+      if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false ||
+         MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true))
         new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
                             (*Target)->ShortDesc, ExpectedIndexHash);
-      else 
+      else
         new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
                            (*Target)->ShortDesc, ExpectedIndexHash);
    }
index b338b2a..36fc53b 100644 (file)
@@ -112,10 +112,10 @@ class pkgAcquire::Item : public WeakPointable
    string ErrorText;
 
    /** \brief The size of the object to fetch. */
-   unsigned long FileSize;
+   unsigned long long FileSize;
 
    /** \brief How much of the object was already fetched. */
-   unsigned long PartialSize;
+   unsigned long long PartialSize;
 
    /** \brief If not \b NULL, contains the name of a subprocess that
     *  is operating on this object (for instance, "gzip" or "gpgv").
index 832eaa0..63825da 100644 (file)
@@ -506,9 +506,9 @@ bool pkgAcquire::Clean(string Dir)
 // Acquire::TotalNeeded - Number of bytes to fetch                     /*{{{*/
 // ---------------------------------------------------------------------
 /* This is the total number of bytes needed */
-double pkgAcquire::TotalNeeded()
+unsigned long long pkgAcquire::TotalNeeded()
 {
-   double Total = 0;
+   unsigned long long Total = 0;
    for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); I++)
       Total += (*I)->FileSize;
    return Total;
@@ -517,9 +517,9 @@ double pkgAcquire::TotalNeeded()
 // Acquire::FetchNeeded - Number of bytes needed to get                        /*{{{*/
 // ---------------------------------------------------------------------
 /* This is the number of bytes that is not local */
-double pkgAcquire::FetchNeeded()
+unsigned long long pkgAcquire::FetchNeeded()
 {
-   double Total = 0;
+   unsigned long long Total = 0;
    for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); I++)
       if ((*I)->Local == false)
         Total += (*I)->FileSize;
@@ -529,9 +529,9 @@ double pkgAcquire::FetchNeeded()
 // Acquire::PartialPresent - Number of partial bytes we already have   /*{{{*/
 // ---------------------------------------------------------------------
 /* This is the number of bytes that is not local */
-double pkgAcquire::PartialPresent()
+unsigned long long pkgAcquire::PartialPresent()
 {
-  double Total = 0;
+  unsigned long long Total = 0;
    for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); I++)
       if ((*I)->Local == false)
         Total += (*I)->PartialSize;
index 8e2c211..82be8b8 100644 (file)
@@ -323,17 +323,17 @@ class pkgAcquire
    /** \return the total size in bytes of all the items included in
     *  this download.
     */
-   double TotalNeeded();
+   unsigned long long TotalNeeded();
 
    /** \return the size in bytes of all non-local items included in
     *  this download.
     */
-   double FetchNeeded();
+   unsigned long long FetchNeeded();
 
    /** \return the amount of data to be fetched that is already
     *  present on the filesystem.
     */
-   double PartialPresent();
+   unsigned long long PartialPresent();
 
    /** \brief Delayed constructor
     *
index 2acf8dd..0c050d9 100644 (file)
@@ -327,11 +327,24 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
        if (likely(Cached == true) && archs.empty() == false)
                return archs;
 
-       string const arch = _config->Find("APT::Architecture");
        archs = _config->FindVector("APT::Architectures");
+       string const arch = _config->Find("APT::Architecture");
+       if (unlikely(arch.empty() == true))
+               return archs;
+
        if (archs.empty() == true ||
            std::find(archs.begin(), archs.end(), arch) == archs.end())
                archs.push_back(arch);
+
+       // erase duplicates and empty strings
+       for (std::vector<string>::reverse_iterator a = archs.rbegin();
+            a != archs.rend(); ++a) {
+               if (a->empty() == true || std::find(a + 1, archs.rend(), *a) != archs.rend())
+                       archs.erase(a.base()-1);
+               if (a == archs.rend())
+                       break;
+       }
+
        return archs;
 }
                                                                        /*}}}*/
index 790312d..0159838 100644 (file)
@@ -27,7 +27,8 @@
 // CacheFile::CacheFile - Constructor                                  /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgCacheFile::pkgCacheFile() : Map(0), Cache(0), DCache(0), Policy(0)
+pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL),
+                               Policy(NULL), SrcList(NULL)
 {
 }
                                                                        /*}}}*/
@@ -38,16 +39,30 @@ pkgCacheFile::~pkgCacheFile()
 {
    delete DCache;
    delete Policy;
+   delete SrcList;
    delete Cache;
    delete Map;
    _system->UnLock(true);
-}   
+}
                                                                        /*}}}*/
 // CacheFile::BuildCaches - Open and build the cache files             /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
+bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock)
 {
+   if (Cache != NULL)
+      return true;
+
+   if (_config->FindB("pkgCacheFile::Generate", true) == false)
+   {
+      Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
+                    FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
+      Cache = new pkgCache(Map);
+      if (_error->PendingError() == true)
+         return false;
+      return true;
+   }
+
    const bool ErrorWasEmpty = _error->empty();
    if (WithLock == true)
       if (_system->Lock() == false)
@@ -58,15 +73,13 @@ bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
       
    if (_error->PendingError() == true)
       return false;
-   
-   // Read the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return _error->Error(_("The list of sources could not be read."));
+
+   BuildSourceList(Progress);
 
    // Read the caches
-   bool Res = pkgMakeStatusCache(List,Progress,&Map,!WithLock);
-   Progress.Done();
+   bool Res = pkgCacheGenerator::MakeStatusCache(*SrcList,Progress,&Map,!WithLock);
+   if (Progress != NULL)
+      Progress->Done();
    if (Res == false)
       return _error->Error(_("The package lists or status file could not be parsed or opened."));
 
@@ -80,29 +93,70 @@ bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
    return true;
 }
                                                                        /*}}}*/
-// CacheFile::Open - Open the cache files, creating if necessary       /*{{{*/
+// CacheFile::BuildSourceList - Open and build all relevant sources.list/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgCacheFile::Open(OpProgress &Progress,bool WithLock)
+bool pkgCacheFile::BuildSourceList(OpProgress *Progress)
 {
-   if (BuildCaches(Progress,WithLock) == false)
-      return false;
-   
-   // The policy engine
+   if (SrcList != NULL)
+      return true;
+
+   SrcList = new pkgSourceList();
+   if (SrcList->ReadMainList() == false)
+      return _error->Error(_("The list of sources could not be read."));
+   return true;
+}
+                                                                       /*}}}*/
+// CacheFile::BuildPolicy - Open and build all relevant preferences    /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheFile::BuildPolicy(OpProgress *Progress)
+{
+   if (Policy != NULL)
+      return true;
+
    Policy = new pkgPolicy(Cache);
    if (_error->PendingError() == true)
       return false;
 
    if (ReadPinFile(*Policy) == false || ReadPinDir(*Policy) == false)
       return false;
-   
-   // Create the dependency cache
+
+   return true;
+}
+                                                                       /*}}}*/
+// CacheFile::BuildDepCache - Open and build the dependency cache      /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheFile::BuildDepCache(OpProgress *Progress)
+{
+   if (DCache != NULL)
+      return true;
+
    DCache = new pkgDepCache(Cache,Policy);
    if (_error->PendingError() == true)
       return false;
-   
-   DCache->Init(&Progress);
-   Progress.Done();
+
+   DCache->Init(Progress);
+   return true;
+}
+                                                                       /*}}}*/
+// CacheFile::Open - Open the cache files, creating if necessary       /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheFile::Open(OpProgress *Progress, bool WithLock)
+{
+   if (BuildCaches(Progress,WithLock) == false)
+      return false;
+
+   if (BuildPolicy(Progress) == false)
+      return false;
+
+   if (BuildDepCache(Progress) == false)
+      return false;
+
+   if (Progress != NULL)
+      Progress->Done();
    if (_error->PendingError() == true)
       return false;
    
@@ -117,12 +171,14 @@ void pkgCacheFile::Close()
    delete DCache;
    delete Policy;
    delete Cache;
+   delete SrcList;
    delete Map;
    _system->UnLock(true);
 
-   Map = 0;
-   DCache = 0;
-   Policy = 0;
-   Cache = 0;
+   Map = NULL;
+   DCache = NULL;
+   Policy = NULL;
+   Cache = NULL;
+   SrcList = NULL;
 }
                                                                        /*}}}*/
index 3b05795..1647aff 100644 (file)
@@ -23,6 +23,7 @@
 #include <apt-pkg/sourcelist.h>
 
 class pkgPolicy;
+class pkgSourceList;
 class pkgCacheFile
 {
    protected:
@@ -30,27 +31,42 @@ class pkgCacheFile
    MMap *Map;
    pkgCache *Cache;
    pkgDepCache *DCache;
-   
+   pkgPolicy *Policy;
+   pkgSourceList *SrcList;
+
    public:
 
-   pkgPolicy *Policy;
-      
    // We look pretty much exactly like a pointer to a dep cache
    inline operator pkgCache &() {return *Cache;};
    inline operator pkgCache *() {return Cache;};
    inline operator pkgDepCache &() {return *DCache;};
    inline operator pkgDepCache *() {return DCache;};
+   inline operator pkgPolicy &() {return *Policy;};
+   inline operator pkgPolicy *() {return Policy;};
+   inline operator pkgSourceList &() {return *SrcList;};
+   inline operator pkgSourceList *() {return SrcList;};
    inline pkgDepCache *operator ->() {return DCache;};
    inline pkgDepCache &operator *() {return *DCache;};
    inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*DCache)[I];};
    inline unsigned char &operator [](pkgCache::DepIterator const &I) {return (*DCache)[I];};
 
-   bool BuildCaches(OpProgress &Progress,bool WithLock = true);
-   bool Open(OpProgress &Progress,bool WithLock = true);
+   bool BuildCaches(OpProgress *Progress = NULL,bool WithLock = true);
+   __deprecated bool BuildCaches(OpProgress &Progress,bool const &WithLock = true) { return BuildCaches(&Progress, WithLock); };
+   bool BuildSourceList(OpProgress *Progress = NULL);
+   bool BuildPolicy(OpProgress *Progress = NULL);
+   bool BuildDepCache(OpProgress *Progress = NULL);
+   bool Open(OpProgress *Progress = NULL, bool WithLock = true);
+   inline bool ReadOnlyOpen(OpProgress *Progress = NULL) { return Open(Progress, false); };
+   __deprecated bool Open(OpProgress &Progress,bool const &WithLock = true) { return Open(&Progress, WithLock); };
    void Close();
-   
+
+   inline pkgCache* GetPkgCache() { BuildCaches(NULL, false); return Cache; };
+   inline pkgDepCache* GetDepCache() { BuildDepCache(); return DCache; };
+   inline pkgPolicy* GetPolicy() { BuildPolicy(); return Policy; };
+   inline pkgSourceList* GetSourceList() { BuildSourceList(); return SrcList; };
+
    pkgCacheFile();
-   ~pkgCacheFile();
+   virtual ~pkgCacheFile();
 };
 
 #endif
index e2ca746..f0b40db 100644 (file)
                                                                        /*}}}*/
 #ifndef PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
+#include<iterator>
 // abstract Iterator template                                          /*{{{*/
 /* This template provides the very basic iterator methods we
    need to have for doing some walk-over-the-cache magic */
-template<typename Str, typename Itr> class pkgCache::Iterator {
+template<typename Str, typename Itr> class pkgCache::Iterator :
+                       public std::iterator<std::forward_iterator_tag, Str> {
        protected:
        Str *S;
        pkgCache *Owner;
@@ -64,7 +66,7 @@ template<typename Str, typename Itr> class pkgCache::Iterator {
        inline operator Str const *() const {return S == OwnerPointer() ? 0 : S;};
        inline Str &operator *() {return *S;};
        inline Str const &operator *() const {return *S;};
-       inline pkgCache *Cache() {return Owner;};
+       inline pkgCache *Cache() const {return Owner;};
 
        // Mixed stuff
        inline void operator =(const Itr &B) {S = B.S; Owner = B.Owner;};
@@ -102,6 +104,11 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
        inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
        inline PkgIterator PackageList() const;
        PkgIterator FindPkg(string Arch = "any");
+       /** \brief find the package with the "best" architecture
+
+           The best architecture is either the "native" or the first
+           in the list of Architectures which is not an end-Pointer */
+       PkgIterator FindPreferredPkg();
        PkgIterator NextPkg(PkgIterator const &Pkg);
 
        // Constructors
@@ -198,8 +205,8 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
        inline PrvIterator ProvidesList() const;
        inline VerFileIterator FileList() const;
        bool Downloadable() const;
-       inline const char *PriorityType() {return Owner->Priority(S->Priority);};
-       string RelStr();
+       inline const char *PriorityType() const {return Owner->Priority(S->Priority);};
+       string RelStr() const;
 
        bool Automatic() const;
        bool Pseudo() const;
diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc
new file mode 100644 (file)
index 0000000..43ade4b
--- /dev/null
@@ -0,0 +1,280 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+/* ######################################################################
+
+   Simple wrapper around a std::set to provide a similar interface to
+   a set of cache structures as to the complete set of all structures
+   in the pkgCache. Currently only Package is supported.
+
+   ##################################################################### */
+                                                                       /*}}}*/
+// Include Files                                                       /*{{{*/
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/cacheset.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/versionmatch.h>
+
+#include <apti18n.h>
+
+#include <vector>
+
+#include <regex.h>
+                                                                       /*}}}*/
+namespace APT {
+// FromRegEx - Return all packages in the cache matching a pattern     /*{{{*/
+PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out) {
+       PackageSet pkgset;
+       std::string arch = "native";
+       static const char * const isregex = ".?+*|[^$";
+
+       if (pattern.find_first_of(isregex) == std::string::npos)
+               return pkgset;
+
+       size_t archfound = pattern.find_last_of(':');
+       if (archfound != std::string::npos) {
+               arch = pattern.substr(archfound+1);
+               if (arch.find_first_of(isregex) == std::string::npos)
+                       pattern.erase(archfound);
+               else
+                       arch = "native";
+       }
+
+       regex_t Pattern;
+       int Res;
+       if ((Res = regcomp(&Pattern, pattern.c_str() , REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) {
+               char Error[300];
+               regerror(Res, &Pattern, Error, sizeof(Error));
+               _error->Error(_("Regex compilation error - %s"), Error);
+               return pkgset;
+       }
+
+       for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp)
+       {
+               if (regexec(&Pattern, Grp.Name(), 0, 0, 0) != 0)
+                       continue;
+               pkgCache::PkgIterator Pkg = Grp.FindPkg(arch);
+               if (Pkg.end() == true) {
+                       if (archfound == std::string::npos) {
+                               std::vector<std::string> archs = APT::Configuration::getArchitectures();
+                               for (std::vector<std::string>::const_iterator a = archs.begin();
+                                    a != archs.end() && Pkg.end() != true; ++a)
+                                       Pkg = Grp.FindPkg(*a);
+                       }
+                       if (Pkg.end() == true)
+                               continue;
+               }
+
+               ioprintf(out, _("Note, selecting %s for regex '%s'\n"),
+                        Pkg.FullName(true).c_str(), pattern.c_str());
+
+               pkgset.insert(Pkg);
+       }
+
+       regfree(&Pattern);
+
+       return pkgset;
+}
+                                                                       /*}}}*/
+// GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
+std::map<unsigned short, PackageSet> PackageSet::GroupedFromCommandLine(
+               pkgCacheFile &Cache, const char **cmdline,
+               std::list<PackageSet::Modifier> const &mods,
+               unsigned short const &fallback, std::ostream &out) {
+       std::map<unsigned short, PackageSet> pkgsets;
+       for (const char **I = cmdline; *I != 0; ++I) {
+               unsigned short modID = fallback;
+               std::string str = *I;
+               for (std::list<PackageSet::Modifier>::const_iterator mod = mods.begin();
+                    mod != mods.end(); ++mod) {
+                       size_t const alength = strlen(mod->Alias);
+                       switch(mod->Pos) {
+                       case PackageSet::Modifier::POSTFIX:
+                               if (str.compare(str.length() - alength, alength,
+                                   mod->Alias, 0, alength) != 0)
+                                       continue;
+                               str.erase(str.length() - alength);
+                               modID = mod->ID;
+                               break;
+                       case PackageSet::Modifier::PREFIX:
+                               continue;
+                       case PackageSet::Modifier::NONE:
+                               continue;
+                       }
+                       break;
+               }
+               PackageSet pset = PackageSet::FromString(Cache, str, out);
+               pkgsets[modID].insert(pset.begin(), pset.end());
+       }
+       return pkgsets;
+}
+                                                                       /*}}}*/
+// FromCommandLine - Return all packages specified on commandline      /*{{{*/
+PackageSet PackageSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out) {
+       PackageSet pkgset;
+       for (const char **I = cmdline; *I != 0; ++I) {
+               PackageSet pset = FromString(Cache, *I, out);
+               pkgset.insert(pset.begin(), pset.end());
+       }
+       return pkgset;
+}
+                                                                       /*}}}*/
+// FromString - Return all packages matching a specific string         /*{{{*/
+PackageSet PackageSet::FromString(pkgCacheFile &Cache, std::string const &str, std::ostream &out) {
+       std::string pkg = str;
+       size_t archfound = pkg.find_last_of(':');
+       std::string arch;
+       if (archfound != std::string::npos) {
+               arch = pkg.substr(archfound+1);
+               pkg.erase(archfound);
+       }
+
+       pkgCache::PkgIterator Pkg;
+       if (arch.empty() == true) {
+               pkgCache::GrpIterator Grp = Cache.GetPkgCache()->FindGrp(pkg);
+               if (Grp.end() == false)
+                       Pkg = Grp.FindPreferredPkg();
+       } else
+               Pkg = Cache.GetPkgCache()->FindPkg(pkg, arch);
+
+       if (Pkg.end() == false) {
+               PackageSet pkgset;
+               pkgset.insert(Pkg);
+               return pkgset;
+       }
+       PackageSet regex = FromRegEx(Cache, str, out);
+       if (regex.empty() == true)
+               _error->Warning(_("Unable to locate package %s"), str.c_str());
+       return regex;
+}
+                                                                       /*}}}*/
+// FromCommandLine - Return all versions specified on commandline      /*{{{*/
+APT::VersionSet VersionSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+               APT::VersionSet::Version const &fallback, std::ostream &out) {
+       VersionSet verset;
+       for (const char **I = cmdline; *I != 0; ++I) {
+               std::string pkg = *I;
+               std::string ver;
+               bool verIsRel = false;
+               size_t const vertag = pkg.find_last_of("/=");
+               if (vertag != string::npos) {
+                       ver = pkg.substr(vertag+1);
+                       verIsRel = (pkg[vertag] == '/');
+                       pkg.erase(vertag);
+               }
+               PackageSet pkgset = PackageSet::FromString(Cache, pkg.c_str(), out);
+               for (PackageSet::const_iterator P = pkgset.begin();
+                    P != pkgset.end(); ++P) {
+                       if (vertag == string::npos) {
+                               AddSelectedVersion(Cache, verset, P, fallback);
+                               continue;
+                       }
+                       pkgCache::VerIterator V;
+                       if (ver == "installed")
+                               V = getInstalledVer(Cache, P);
+                       else if (ver == "candidate")
+                               V = getCandidateVer(Cache, P);
+                       else {
+                               pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release :
+                                               pkgVersionMatch::Version));
+                               V = Match.Find(P);
+                               if (V.end() == true) {
+                                       if (verIsRel == true)
+                                               _error->Error(_("Release '%s' for '%s' was not found"),
+                                                               ver.c_str(), P.FullName(true).c_str());
+                                       else
+                                               _error->Error(_("Version '%s' for '%s' was not found"),
+                                                               ver.c_str(), P.FullName(true).c_str());
+                                       continue;
+                               }
+                       }
+                       if (V.end() == true)
+                               continue;
+                       if (ver == V.VerStr())
+                               ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+                                        V.VerStr(), V.RelStr().c_str(), P.FullName(true).c_str());
+                       verset.insert(V);
+               }
+       }
+       return verset;
+}
+                                                                       /*}}}*/
+// AddSelectedVersion - add version from package based on fallback     /*{{{*/
+bool VersionSet::AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset,
+               pkgCache::PkgIterator const &P, VersionSet::Version const &fallback,
+               bool const &AllowError) {
+       pkgCache::VerIterator V;
+       switch(fallback) {
+       case VersionSet::ALL:
+               if (P->VersionList != 0)
+                       for (V = P.VersionList(); V.end() != true; ++V)
+                               verset.insert(V);
+               else if (AllowError == false)
+                       return _error->Error(_("Can't select versions from package '%s' as it purely virtual"), P.FullName(true).c_str());
+               else
+                       return false;
+               break;
+       case VersionSet::CANDANDINST:
+               verset.insert(getInstalledVer(Cache, P, AllowError));
+               verset.insert(getCandidateVer(Cache, P, AllowError));
+               break;
+       case VersionSet::CANDIDATE:
+               verset.insert(getCandidateVer(Cache, P, AllowError));
+               break;
+       case VersionSet::INSTALLED:
+               verset.insert(getInstalledVer(Cache, P, AllowError));
+               break;
+       case VersionSet::CANDINST:
+               V = getCandidateVer(Cache, P, true);
+               if (V.end() == true)
+                       V = getInstalledVer(Cache, P, true);
+               if (V.end() == false)
+                       verset.insert(V);
+               else if (AllowError == false)
+                       return _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P.FullName(true).c_str());
+               else
+                       return false;
+               break;
+       case VersionSet::INSTCAND:
+               V = getInstalledVer(Cache, P, true);
+               if (V.end() == true)
+                       V = getCandidateVer(Cache, P, true);
+               if (V.end() == false)
+                       verset.insert(V);
+               else if (AllowError == false)
+                       return _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P.FullName(true).c_str());
+               else
+                       return false;
+               break;
+       case VersionSet::NEWEST:
+               if (P->VersionList != 0)
+                       verset.insert(P.VersionList());
+               else if (AllowError == false)
+                       return _error->Error(_("Can't select newest version from package '%s' as it is purely virtual"), P.FullName(true).c_str());
+               else
+                       return false;
+               break;
+       }
+       return true;
+}
+                                                                       /*}}}*/
+// getCandidateVer - Returns the candidate version of the given package        /*{{{*/
+pkgCache::VerIterator VersionSet::getCandidateVer(pkgCacheFile &Cache,
+               pkgCache::PkgIterator const &Pkg, bool const &AllowError) {
+       if (unlikely(Cache.BuildDepCache() == false))
+               return pkgCache::VerIterator(*Cache);
+       pkgCache::VerIterator Cand = Cache[Pkg].CandidateVerIter(Cache);
+       if (AllowError == false && Cand.end() == true)
+               _error->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg.FullName(true).c_str());
+       return Cand;
+}
+                                                                       /*}}}*/
+// getInstalledVer - Returns the installed version of the given package        /*{{{*/
+pkgCache::VerIterator VersionSet::getInstalledVer(pkgCacheFile &Cache,
+               pkgCache::PkgIterator const &Pkg, bool const &AllowError) {
+       if (AllowError == false && Pkg->CurrentVer == 0)
+               _error->Error(_("Can't select installed version from package %s as it is not installed"), Pkg.FullName(true).c_str());
+       return Pkg.CurrentVer();
+}
+                                                                       /*}}}*/
+}
diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h
new file mode 100644 (file)
index 0000000..c9d1210
--- /dev/null
@@ -0,0 +1,239 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+/** \file cacheset.h
+   Wrappers around std::set to have set::iterators which behave
+   similar to the Iterators of the cache structures.
+
+   Provides also a few helper methods which work with these sets */
+                                                                       /*}}}*/
+#ifndef APT_CACHESET_H
+#define APT_CACHESET_H
+// Include Files                                                       /*{{{*/
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/pkgcache.h>
+                                                                       /*}}}*/
+namespace APT {
+class PackageSet : public std::set<pkgCache::PkgIterator> {            /*{{{*/
+/** \class APT::PackageSet
+
+    Simple wrapper around a std::set to provide a similar interface to
+    a set of packages as to the complete set of all packages in the
+    pkgCache. */
+public:                                                                        /*{{{*/
+       /** \brief smell like a pkgCache::PkgIterator */
+       class const_iterator : public std::set<pkgCache::PkgIterator>::const_iterator {
+       public:
+               const_iterator(std::set<pkgCache::PkgIterator>::const_iterator x) :
+                        std::set<pkgCache::PkgIterator>::const_iterator(x) {}
+
+               operator pkgCache::PkgIterator(void) { return **this; }
+
+               inline const char *Name() const {return (**this).Name(); }
+               inline std::string FullName(bool const &Pretty) const { return (**this).FullName(Pretty); }
+               inline std::string FullName() const { return (**this).FullName(); }
+               inline const char *Section() const {return (**this).Section(); }
+               inline bool Purge() const {return (**this).Purge(); }
+               inline const char *Arch() const {return (**this).Arch(); }
+               inline pkgCache::GrpIterator Group() const { return (**this).Group(); }
+               inline pkgCache::VerIterator VersionList() const { return (**this).VersionList(); }
+               inline pkgCache::VerIterator CurrentVer() const { return (**this).CurrentVer(); }
+               inline pkgCache::DepIterator RevDependsList() const { return (**this).RevDependsList(); }
+               inline pkgCache::PrvIterator ProvidesList() const { return (**this).ProvidesList(); }
+               inline pkgCache::PkgIterator::OkState State() const { return (**this).State(); }
+               inline const char *CandVersion() const { return (**this).CandVersion(); }
+               inline const char *CurVersion() const { return (**this).CurVersion(); }
+               inline pkgCache *Cache() const { return (**this).Cache(); };
+               inline unsigned long Index() const {return (**this).Index();};
+               // we have only valid iterators here
+               inline bool end() const { return false; };
+
+               friend std::ostream& operator<<(std::ostream& out, const_iterator i) { return operator<<(out, (*i)); }
+
+               inline pkgCache::Package const * operator->() const {
+                       return &***this;
+               };
+       };
+       // 103. set::iterator is required to be modifiable, but this allows modification of keys
+       typedef typename APT::PackageSet::const_iterator iterator;
+
+       using std::set<pkgCache::PkgIterator>::insert;
+       inline void insert(pkgCache::PkgIterator const &P) { if (P.end() == false) std::set<pkgCache::PkgIterator>::insert(P); };
+
+       /** \brief returns all packages in the cache whose name matchs a given pattern
+
+           A simple helper responsible for executing a regular expression on all
+           package names in the cache. Optional it prints a a notice about the
+           packages chosen cause of the given package.
+           \param Cache the packages are in
+           \param pattern regular expression for package names
+           \param out stream to print the notice to */
+       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out);
+       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string const &pattern) {
+               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               return APT::PackageSet::FromRegEx(Cache, pattern, out);
+       }
+
+       /** \brief returns all packages specified by a string
+
+           \param Cache the packages are in
+           \param string String the package name(s) should be extracted from
+           \param out stream to print various notices to */
+       static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, std::ostream &out);
+       static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string) {
+               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               return APT::PackageSet::FromString(Cache, string, out);
+       }
+
+       /** \brief returns all packages specified on the commandline
+
+           Get all package names from the commandline and executes regex's if needed.
+           No special package command is supported, just plain names.
+           \param Cache the packages are in
+           \param cmdline Command line the package names should be extracted from
+           \param out stream to print various notices to */
+       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out);
+       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
+               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               return APT::PackageSet::FromCommandLine(Cache, cmdline, out);
+       }
+
+       struct Modifier {
+               enum Position { NONE, PREFIX, POSTFIX };
+               unsigned short ID;
+               const char * const Alias;
+               Position Pos;
+               Modifier (unsigned short const &id, const char * const alias, Position const &pos) : ID(id), Alias(alias), Pos(pos) {};
+       };
+
+       static std::map<unsigned short, PackageSet> GroupedFromCommandLine(
+               pkgCacheFile &Cache, const char **cmdline,
+               std::list<PackageSet::Modifier> const &mods,
+               unsigned short const &fallback, std::ostream &out);
+       static std::map<unsigned short, PackageSet> GroupedFromCommandLine(
+               pkgCacheFile &Cache, const char **cmdline,
+               std::list<PackageSet::Modifier> const &mods,
+               unsigned short const &fallback) {
+               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               return APT::PackageSet::GroupedFromCommandLine(Cache, cmdline,
+                               mods, fallback, out);
+       }
+                                                                       /*}}}*/
+};                                                                     /*}}}*/
+class VersionSet : public std::set<pkgCache::VerIterator> {            /*{{{*/
+/** \class APT::VersionSet
+
+    Simple wrapper around a std::set to provide a similar interface to
+    a set of versions as to the complete set of all versions in the
+    pkgCache. */
+public:                                                                        /*{{{*/
+       /** \brief smell like a pkgCache::VerIterator */
+       class const_iterator : public std::set<pkgCache::VerIterator>::const_iterator {
+       public:
+               const_iterator(std::set<pkgCache::VerIterator>::const_iterator x) :
+                        std::set<pkgCache::VerIterator>::const_iterator(x) {}
+
+               operator pkgCache::VerIterator(void) { return **this; }
+
+               inline pkgCache *Cache() const { return (**this).Cache(); };
+               inline unsigned long Index() const {return (**this).Index();};
+               // we have only valid iterators here
+               inline bool end() const { return false; };
+
+               inline pkgCache::Version const * operator->() const {
+                       return &***this;
+               };
+
+               inline int CompareVer(const pkgCache::VerIterator &B) const { return (**this).CompareVer(B); };
+               inline const char *VerStr() const { return (**this).VerStr(); };
+               inline const char *Section() const { return (**this).Section(); };
+               inline const char *Arch() const { return (**this).Arch(); };
+               inline const char *Arch(bool const pseudo) const { return (**this).Arch(pseudo); };
+               inline pkgCache::PkgIterator ParentPkg() const { return (**this).ParentPkg(); };
+               inline pkgCache::DescIterator DescriptionList() const { return (**this).DescriptionList(); };
+               inline pkgCache::DescIterator TranslatedDescription() const { return (**this).TranslatedDescription(); };
+               inline pkgCache::DepIterator DependsList() const { return (**this).DependsList(); };
+               inline pkgCache::PrvIterator ProvidesList() const { return (**this).ProvidesList(); };
+               inline pkgCache::VerFileIterator FileList() const { return (**this).FileList(); };
+               inline bool Downloadable() const { return (**this).Downloadable(); };
+               inline const char *PriorityType() const { return (**this).PriorityType(); };
+               inline string RelStr() const { return (**this).RelStr(); };
+               inline bool Automatic() const { return (**this).Automatic(); };
+               inline bool Pseudo() const { return (**this).Pseudo(); };
+               inline pkgCache::VerFileIterator NewestFile() const { return (**this).NewestFile(); };
+       };
+       // 103. set::iterator is required to be modifiable, but this allows modification of keys
+       typedef typename APT::VersionSet::const_iterator iterator;
+
+       using std::set<pkgCache::VerIterator>::insert;
+       inline void insert(pkgCache::VerIterator const &V) { if (V.end() == false) std::set<pkgCache::VerIterator>::insert(V); };
+
+       /** \brief specifies which version(s) will be returned if non is given */
+       enum Version {
+               /** All versions */
+               ALL,
+               /** Candidate and installed version */
+               CANDANDINST,
+               /** Candidate version */
+               CANDIDATE,
+               /** Installed version */
+               INSTALLED,
+               /** Candidate or if non installed version */
+               CANDINST,
+               /** Installed or if non candidate version */
+               INSTCAND,
+               /** Newest version */
+               NEWEST
+       };
+
+       /** \brief returns all versions specified on the commandline
+
+           Get all versions from the commandline, uses given default version if
+           non specifically requested  and executes regex's if needed on names.
+           \param Cache the packages and versions are in
+           \param cmdline Command line the versions should be extracted from
+           \param out stream to print various notices to */
+       static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+                       APT::VersionSet::Version const &fallback, std::ostream &out);
+       static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+                       APT::VersionSet::Version const &fallback) {
+               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               return APT::VersionSet::FromCommandLine(Cache, cmdline, fallback, out);
+       }
+       static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
+               return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST);
+       }
+                                                                       /*}}}*/
+protected:                                                             /*{{{*/
+
+       /** \brief returns the candidate version of the package
+
+           \param Cache to be used to query for information
+           \param Pkg we want the candidate version from this package
+           \param AllowError add an error to the stack if not */
+       static pkgCache::VerIterator getCandidateVer(pkgCacheFile &Cache,
+               pkgCache::PkgIterator const &Pkg, bool const &AllowError = false);
+
+       /** \brief returns the installed version of the package
+
+           \param Cache to be used to query for information
+           \param Pkg we want the installed version from this package
+           \param AllowError add an error to the stack if not */
+       static pkgCache::VerIterator getInstalledVer(pkgCacheFile &Cache,
+               pkgCache::PkgIterator const &Pkg, bool const &AllowError = false);
+
+
+       static bool AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset,
+               pkgCache::PkgIterator const &P, VersionSet::Version const &fallback,
+               bool const &AllowError = false);
+
+                                                                       /*}}}*/
+};                                                                     /*}}}*/
+}
+#endif
index 0b16bf5..5a99440 100644 (file)
@@ -360,11 +360,11 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch)
    than nothing after all. */
 void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv)
 {
-   char cmdline[300];
+   char cmdline[100 + argc * 50];
    unsigned int length = 0;
    bool lastWasOption = false;
    bool closeQuote = false;
-   for (unsigned int i = 0; i < argc; ++i, ++length)
+   for (unsigned int i = 0; i < argc && length < sizeof(cmdline); ++i, ++length)
    {
       for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length)
       {
index b89429d..6d9e994 100644 (file)
@@ -262,15 +262,15 @@ unsigned long debPackagesIndex::Size() const
 // PackagesIndex::Merge - Load the index file into a cache             /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
    string PackageFile = IndexFile("Packages");
    FileFd Pkg(PackageFile,FileFd::ReadOnly);
    debListParser Parser(&Pkg, Architecture);
    if (_error->PendingError() == true)
       return _error->Error("Problem opening %s",PackageFile.c_str());
-   
-   Prog.SubProgress(0,Info("Packages"));
+   if (Prog != NULL)
+      Prog->SubProgress(0,Info("Packages"));
    ::URI Tmp(URI);
    if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
       return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
@@ -445,7 +445,7 @@ unsigned long debTranslationsIndex::Size() const
 // TranslationsIndex::Merge - Load the index file into a cache         /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
    // Check the translation file, if in use
    string TranslationFile = IndexFile(Language);
@@ -456,7 +456,8 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
      if (_error->PendingError() == true)
        return false;
      
-     Prog.SubProgress(0, Info(TranslationFile.c_str()));
+     if (Prog != NULL)
+       Prog->SubProgress(0, Info(TranslationFile.c_str()));
      if (Gen.SelectFile(TranslationFile,string(),*this) == false)
        return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
 
@@ -529,7 +530,7 @@ unsigned long debStatusIndex::Size() const
 // StatusIndex::Merge - Load the index file into a cache               /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
    FileFd Pkg(File,FileFd::ReadOnly);
    if (_error->PendingError() == true)
@@ -537,8 +538,9 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
    debListParser Parser(&Pkg);
    if (_error->PendingError() == true)
       return false;
-   
-   Prog.SubProgress(0,File);
+
+   if (Prog != NULL)
+      Prog->SubProgress(0,File);
    if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
       return _error->Error("Problem with SelectFile %s",File.c_str());
 
index 766e8b2..b508599 100644 (file)
@@ -35,7 +35,7 @@ class debStatusIndex : public pkgIndexFile
    virtual bool Exists() const;
    virtual bool HasPackages() const {return true;};
    virtual unsigned long Size() const;
-   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
    debStatusIndex(string File);
@@ -67,7 +67,7 @@ class debPackagesIndex : public pkgIndexFile
    virtual bool Exists() const;
    virtual bool HasPackages() const {return true;};
    virtual unsigned long Size() const;
-   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
    debPackagesIndex(string const &URI, string const &Dist, string const &Section,
@@ -99,7 +99,7 @@ class debTranslationsIndex : public pkgIndexFile
    virtual bool Exists() const;
    virtual bool HasPackages() const;
    virtual unsigned long Size() const;
-   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
    debTranslationsIndex(string URI,string Dist,string Section, char const * const Language);
index 0551a5f..83c5b8d 100644 (file)
@@ -133,10 +133,9 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
    }
 
    // Archive Size
-   Ver->Size = (unsigned)Section.FindI("Size");
-   
+   Ver->Size = Section.FindULL("Size");
    // Unpacked Size (in K)
-   Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
+   Ver->InstalledSize = Section.FindULL("Installed-Size");
    Ver->InstalledSize *= 1024;
 
    // Priority
index 59f826d..31c26ab 100644 (file)
@@ -158,7 +158,7 @@ bool debSystem::Initialize(Configuration &Cnf)
    /* These really should be jammed into a generic 'Local Database' engine
       which is yet to be determined. The functions in pkgcachegen should
       be the only users of these */
-   Cnf.CndSet("Dir::State::userstatus","status.user"); // Defunct
+   Cnf.CndSet("Dir::State::extended_states", Cnf.FindDir("Dir::State").append("extended_states"));
    Cnf.CndSet("Dir::State::status","/var/lib/dpkg/status");
    Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg");
 
index 8318fe3..0ac6ac1 100644 (file)
@@ -470,7 +470,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
         std::clog << "send: '" << status.str() << "'" << endl;
 
       if (strncmp(action, "disappear", strlen("disappear")) == 0)
-        disappearedPkgs.insert(string(pkg_or_trigger));
+        handleDisappearAction(pkg_or_trigger);
       return;
    }
 
@@ -530,6 +530,51 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
                << " action: " << action << endl;
 }
                                                                        /*}}}*/
+// DPkgPM::handleDisappearAction                                       /*{{{*/
+void pkgDPkgPM::handleDisappearAction(string const &pkgname)
+{
+   // record the package name for display and stuff later
+   disappearedPkgs.insert(pkgname);
+
+   pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname);
+   if (unlikely(Pkg.end() == true))
+      return;
+   // the disappeared package was auto-installed - nothing to do
+   if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+      return;
+   pkgCache::VerIterator PkgVer = Pkg.CurrentVer();
+   if (unlikely(PkgVer.end() == true))
+      return;
+   /* search in the list of dependencies for (Pre)Depends,
+      check if this dependency has a Replaces on our package
+      and if so transfer the manual installed flag to it */
+   for (pkgCache::DepIterator Dep = PkgVer.DependsList(); Dep.end() != true; ++Dep)
+   {
+      if (Dep->Type != pkgCache::Dep::Depends &&
+         Dep->Type != pkgCache::Dep::PreDepends)
+        continue;
+      pkgCache::PkgIterator Tar = Dep.TargetPkg();
+      if (unlikely(Tar.end() == true))
+        continue;
+      // the package is already marked as manual
+      if ((Cache[Tar].Flags & pkgCache::Flag::Auto) != pkgCache::Flag::Auto)
+        continue;
+      pkgCache::VerIterator TarVer = Tar.CurrentVer();
+      for (pkgCache::DepIterator Rep = TarVer.DependsList(); Rep.end() != true; ++Rep)
+      {
+        if (Rep->Type != pkgCache::Dep::Replaces)
+           continue;
+        if (Pkg != Rep.TargetPkg())
+           continue;
+        // okay, they are strongly connected - transfer manual-bit
+        if (Debug == true)
+           std::clog << "transfer manual-bit from disappeared Â»" << pkgname << "« to Â»" << Tar.FullName() << "«" << std::endl;
+        Cache[Tar].Flags &= ~Flag::Auto;
+        break;
+      }
+   }
+}
+                                                                       /*}}}*/
 // DPkgPM::DoDpkgStatusFd                                              /*{{{*/
 // ---------------------------------------------------------------------
 /*
@@ -568,15 +613,15 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
 }
                                                                        /*}}}*/
 // DPkgPM::WriteHistoryTag                                             /*{{{*/
-void pkgDPkgPM::WriteHistoryTag(string tag, string value)
+void pkgDPkgPM::WriteHistoryTag(string const &tag, string value)
 {
-   if (value.size() > 0)
-   {
-      // poor mans rstrip(", ")
-      if (value[value.size()-2] == ',' && value[value.size()-1] == ' ')
-        value.erase(value.size() - 2, 2);
-      fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
-   }
+   size_t const length = value.length();
+   if (length == 0)
+      return;
+   // poor mans rstrip(", ")
+   if (value[length-2] == ',' && value[length-1] == ' ')
+      value.erase(length - 2, 2);
+   fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
 }                                                                      /*}}}*/
 // DPkgPM::OpenLog                                                     /*{{{*/
 bool pkgDPkgPM::OpenLog()
@@ -663,7 +708,22 @@ bool pkgDPkgPM::CloseLog()
 
    if(history_out)
    {
-      if (dpkg_error.size() > 0)
+      if (disappearedPkgs.empty() == false)
+      {
+        string disappear;
+        for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
+             d != disappearedPkgs.end(); ++d)
+        {
+           pkgCache::PkgIterator P = Cache.FindPkg(*d);
+           disappear.append(*d);
+           if (P.end() == true)
+              disappear.append(", ");
+           else
+              disappear.append(" (").append(Cache[P].CurVersion).append("), ");
+        }
+        WriteHistoryTag("Disappeared", disappear);
+      }
+      if (dpkg_error.empty() == false)
         fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
       fprintf(history_out, "End-Date: %s\n", timestr);
       fclose(history_out);
index 330c788..9a4478f 100644 (file)
@@ -32,6 +32,21 @@ class pkgDPkgPM : public pkgPackageManager
    FILE *history_out;
    string dpkg_error;
 
+   /** \brief record the disappear action and handle accordingly
+
+      dpkg let packages disappear then they have no files any longer and
+      nothing depends on them. We need to collect this as dpkg as well as
+      APT doesn't know beforehand that the package will disappear, so the
+      only possible option is to tell the user afterwards about it.
+      To enhance the experience we also try to forward the auto-install
+      flag so the disappear-causer(s) are not autoremoved next time -
+      for the transfer to happen the disappeared version needs to depend
+      on the package the flag should be forwarded to and this package
+      needs to declare a Replaces on the disappeared package.
+      \param pkgname Name of the package that disappeared
+   */
+   void handleDisappearAction(string const &pkgname);
+
    protected:
 
    // progress reporting
@@ -68,7 +83,7 @@ class pkgDPkgPM : public pkgPackageManager
    // Helpers
    bool RunScriptsWithPkgs(const char *Cnf);
    bool SendV2Pkgs(FILE *F);
-   void WriteHistoryTag(string tag, string value);
+   void WriteHistoryTag(string const &tag, string value);
 
    // dpkg log
    bool OpenLog();
index 411ae5f..3ae5f59 100644 (file)
@@ -165,7 +165,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
 bool pkgDepCache::readStateFile(OpProgress *Prog)                      /*{{{*/
 {
    FileFd state_file;
-   string const state = _config->FindDir("Dir::State") + "extended_states";
+   string const state = _config->FindFile("Dir::State::extended_states");
    if(FileExists(state)) {
       state_file.Open(state, FileFd::ReadOnly);
       int const file_size = state_file.Size();
@@ -222,7 +222,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)      /*{{{*/
       std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 
    FileFd StateFile;
-   string const state = _config->FindDir("Dir::State") + "extended_states";
+   string const state = _config->FindFile("Dir::State::extended_states");
 
    // if it does not exist, create a empty one
    if(!FileExists(state)) 
@@ -407,8 +407,11 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
                                                                        /*}}}*/
 // DepCache::AddSizes - Add the packages sizes to the counters         /*{{{*/
 // ---------------------------------------------------------------------
-/* Call with Mult = -1 to preform the inverse opration */
-void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
+/* Call with Mult = -1 to preform the inverse opration
+   The Mult increases the complexity of the calulations here and is unused -
+   or do we really have a usecase for removing the size of a package two
+   times? So let us replace it with a simple bool and be done with it… */
+__deprecated void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
 {
    StateCache &P = PkgState[Pkg->ID];
    
@@ -422,8 +425,8 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
    // Compute the size data
    if (P.NewInstall() == true)
    {
-      iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
-      iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
+      iUsrSize += (signed long long)(Mult*P.InstVerIter(*this)->InstalledSize);
+      iDownloadSize += (signed long long)(Mult*P.InstVerIter(*this)->Size);
       return;
    }
    
@@ -432,9 +435,9 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
        (P.InstallVer != (Version *)Pkg.CurrentVer() || 
        (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
    {
-      iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize - 
-                       (signed)Pkg.CurrentVer()->InstalledSize));
-      iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
+      iUsrSize += (signed long long)(Mult*((signed long long)P.InstVerIter(*this)->InstalledSize - 
+                       (signed long long)Pkg.CurrentVer()->InstalledSize));
+      iDownloadSize += (signed long long)(Mult*P.InstVerIter(*this)->Size);
       return;
    }
    
@@ -442,14 +445,80 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
    if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
        P.Delete() == false)
    {
-      iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
+      iDownloadSize += (signed long long)(Mult*P.InstVerIter(*this)->Size);
       return;
    }
    
    // Removing
    if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
    {
-      iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
+      iUsrSize -= (signed long long)(Mult*Pkg.CurrentVer()->InstalledSize);
+      return;
+   }   
+}
+                                                                       /*}}}*/
+// DepCache::AddSizes - Add the packages sizes to the counters         /*{{{*/
+// ---------------------------------------------------------------------
+/* Call with Inverse = true to preform the inverse opration */
+void pkgDepCache::AddSizes(const PkgIterator &Pkg, bool const &Inverse)
+{
+   StateCache &P = PkgState[Pkg->ID];
+   
+   if (Pkg->VersionList == 0)
+      return;
+   
+   if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && 
+       P.Keep() == true)
+      return;
+   
+   // Compute the size data
+   if (P.NewInstall() == true)
+   {
+      if (Inverse == false) {
+        iUsrSize += P.InstVerIter(*this)->InstalledSize;
+        iDownloadSize += P.InstVerIter(*this)->Size;
+      } else {
+        iUsrSize -= P.InstVerIter(*this)->InstalledSize;
+        iDownloadSize -= P.InstVerIter(*this)->Size;
+      }
+      return;
+   }
+   
+   // Upgrading
+   if (Pkg->CurrentVer != 0 && 
+       (P.InstallVer != (Version *)Pkg.CurrentVer() || 
+       (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
+   {
+      if (Inverse == false) {
+        iUsrSize -= Pkg.CurrentVer()->InstalledSize;
+        iUsrSize += P.InstVerIter(*this)->InstalledSize;
+        iDownloadSize += P.InstVerIter(*this)->Size;
+      } else {
+        iUsrSize -= P.InstVerIter(*this)->InstalledSize;
+        iUsrSize += Pkg.CurrentVer()->InstalledSize;
+        iDownloadSize -= P.InstVerIter(*this)->Size;
+      }
+      return;
+   }
+   
+   // Reinstall
+   if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
+       P.Delete() == false)
+   {
+      if (Inverse == false)
+        iDownloadSize += P.InstVerIter(*this)->Size;
+      else
+        iDownloadSize -= P.InstVerIter(*this)->Size;
+      return;
+   }
+   
+   // Removing
+   if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
+   {
+      if (Inverse == false)
+        iUsrSize -= Pkg.CurrentVer()->InstalledSize;
+      else
+        iUsrSize += Pkg.CurrentVer()->InstalledSize;
       return;
    }   
 }
@@ -806,7 +875,7 @@ void pkgDepCache::Update(OpProgress *Prog)
                a bit we increase with a kill, but we should do something more clever… */
       while(recheck.empty() == false)
         for (std::set<unsigned long>::const_iterator p = recheck.begin();
-            p != recheck.end(); ++p) {
+            p != recheck.end();) {
            if (Prog != 0 && Done%20 == 0)
               Prog->Progress(Done);
            PkgIterator P = PkgIterator(*Cache, Cache->PkgP + *p);
@@ -814,7 +883,7 @@ void pkgDepCache::Update(OpProgress *Prog)
               ++killed;
               ++Done;
            }
-           recheck.erase(p);
+           recheck.erase(p++);
         }
 
       /* Okay, we have killed a great amount of pseudopackages -
@@ -849,7 +918,7 @@ void pkgDepCache::Update(OpProgress *Prog)
         unsigned long const G = *g;
         recheck.erase(g);
         if (unlikely(ReInstallPseudoForGroup(G, recheck) == false))
-           _error->Warning(_("Internal error, group '%s' has no installable pseudo package"), GrpIterator(*Cache, Cache->GrpP + *g).Name());
+           _error->Warning(_("Internal error, group '%s' has no installable pseudo package"), GrpIterator(*Cache, Cache->GrpP + G).Name());
       }
    }
 
@@ -1638,8 +1707,11 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
    {
       if(!(PkgState[p->ID].Flags & Flag::Auto) ||
          (p->Flags & Flag::Essential) ||
-         userFunc.InRootSet(p))
-          
+         userFunc.InRootSet(p) ||
+         // be nice even then a required package violates the policy (#583517)
+         // and do the full mark process also for required packages
+         (p.CurrentVer().end() != true &&
+          p.CurrentVer()->Priority == pkgCache::State::Required))
       {
         // the package is installed (and set to keep)
         if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
@@ -1716,10 +1788,6 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 
    // 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)
    {
@@ -1731,7 +1799,8 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
         for (VerIterator V = P.VersionList();
              V.end() != true; ++V)
         {
-           if (strcmp(VerStr, V.VerStr()) != 0)
+           if (ver->Hash != V->Hash ||
+               strcmp(VerStr, V.VerStr()) != 0)
               continue;
            MarkPackage(P, V, follow_recommends, follow_suggests);
            break;
index 3decc7a..c6f245a 100644 (file)
@@ -286,9 +286,11 @@ class pkgDepCache : protected pkgCache::Namespace
    pkgCache *Cache;
    StateCache *PkgState;
    unsigned char *DepState;
-   
-   double iUsrSize;
-   double iDownloadSize;
+
+   /** Stores the space changes after installation */
+   signed long long iUsrSize;
+   /** Stores how much we need to download to get the packages */
+   unsigned long long iDownloadSize;
    unsigned long iInstCount;
    unsigned long iDelCount;
    unsigned long iKeepCount;
@@ -321,8 +323,9 @@ class pkgDepCache : protected pkgCache::Namespace
    void Update(PkgIterator const &P);
    
    // Count manipulators
-   void AddSizes(const PkgIterator &Pkg,signed long Mult = 1);
-   inline void RemoveSizes(const PkgIterator &Pkg) {AddSizes(Pkg,-1);};
+   void AddSizes(const PkgIterator &Pkg, bool const &Invert = false);
+   inline void RemoveSizes(const PkgIterator &Pkg) {AddSizes(Pkg, true);};
+   void AddSizes(const PkgIterator &Pkg,signed long Mult) __deprecated;
    void AddStates(const PkgIterator &Pkg,int Add = 1);
    inline void RemoveStates(const PkgIterator &Pkg) {AddStates(Pkg,-1);};
    
@@ -451,8 +454,8 @@ class pkgDepCache : protected pkgCache::Namespace
    bool writeStateFile(OpProgress *prog, bool InstalledOnly=true);
    
    // Size queries
-   inline double UsrSize() {return iUsrSize;};
-   inline double DebSize() {return iDownloadSize;};
+   inline signed long long UsrSize() {return iUsrSize;};
+   inline unsigned long long DebSize() {return iDownloadSize;};
    inline unsigned long DelCount() {return iDelCount;};
    inline unsigned long KeepCount() {return iKeepCount;};
    inline unsigned long InstCount() {return iInstCount;};
index 3cc5016..2b5ae63 100644 (file)
@@ -74,8 +74,12 @@ class pkgIndexFile
    virtual bool Exists() const = 0;
    virtual bool HasPackages() const = 0;
    virtual unsigned long Size() const = 0;
-   virtual bool Merge(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return false;};
-   virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return true;};
+   virtual bool Merge(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const { return false; };
+   __deprecated virtual bool Merge(pkgCacheGenerator &Gen, OpProgress &Prog) const
+      { return Merge(Gen, &Prog); };
+   virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const {return true;};
+   __deprecated virtual bool MergeFileProvides(pkgCacheGenerator &Gen, OpProgress &Prog) const
+      {return MergeFileProvides(Gen, &Prog);};
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
    static bool TranslationsAvailable();
index 3bde743..eb9a368 100644 (file)
@@ -39,6 +39,11 @@ const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
    return Entries[MetaKey];
 }
 
+bool indexRecords::Exists(string const &MetaKey) const
+{
+   return Entries.count(MetaKey) == 1;
+}
+
 bool indexRecords::Load(const string Filename)                         /*{{{*/
 {
    FileFd Fd(Filename, FileFd::ReadOnly);
index 500cf23..5b532c1 100644 (file)
@@ -37,6 +37,8 @@ class indexRecords
 
    // Lookup function
    virtual const checkSum *Lookup(const string MetaKey);
+   /** \brief tests if a checksum for this file is available */
+   bool Exists(string const &MetaKey) const;
    std::vector<std::string> MetaKeys();
 
    virtual bool Load(string Filename);
index 148ad58..1a70786 100644 (file)
@@ -35,14 +35,15 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
         srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
         pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
         indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
-        aptconfiguration.cc
+        aptconfiguration.cc cacheset.cc
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
          orderlist.h sourcelist.h packagemanager.h tagfile.h \
          init.h pkgcache.h version.h progress.h pkgrecords.h \
          acquire.h acquire-worker.h acquire-item.h acquire-method.h \
          clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
          pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
-          vendorlist.h cdrom.h indexcopy.h aptconfiguration.h
+          vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \
+         cacheset.h
 
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..
index a59a06d..30bb414 100644 (file)
@@ -340,6 +340,25 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
                        break;
        }
 
+       return PkgIterator(*Owner, 0);
+}
+                                                                       /*}}}*/
+// GrpIterator::FindPreferredPkg - Locate the "best" package           /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns an End-Pointer on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() {
+       pkgCache::PkgIterator Pkg = FindPkg("native");
+       if (Pkg.end() == false)
+               return Pkg;
+
+       std::vector<std::string> const archs = APT::Configuration::getArchitectures();
+       for (std::vector<std::string>::const_iterator a = archs.begin();
+            a != archs.end(); ++a) {
+               Pkg = FindPkg(*a);
+               if (Pkg.end() == false)
+                       return Pkg;
+       }
+
        return PkgIterator(*Owner, 0);
 }
                                                                        /*}}}*/
@@ -723,7 +742,7 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
 // ---------------------------------------------------------------------
 /* This describes the version from a release-centric manner. The output is a 
    list of Label:Version/Archive */
-string pkgCache::VerIterator::RelStr()
+string pkgCache::VerIterator::RelStr() const
 {
    bool First = true;
    string Res;
index 643f240..426bb9f 100644 (file)
@@ -532,9 +532,9 @@ struct pkgCache::Version
    /** \brief archive size for this version
 
        For Debian this is the size of the .deb file. */
-   map_ptrloc Size;              // These are the .deb size
+   unsigned long long Size;      // These are the .deb size
    /** \brief uncompressed size for this version */
-   map_ptrloc InstalledSize;
+   unsigned long long InstalledSize;
    /** \brief characteristic value representing this version
 
        No two packages in existence should have the same VerStr
index d96d337..5649cd6 100644 (file)
@@ -526,7 +526,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
 // CacheGenerator::FinishCache - do various finish operations          /*{{{*/
 // ---------------------------------------------------------------------
 /* This prepares the Cache for delivery */
-bool pkgCacheGenerator::FinishCache(OpProgress &Progress)
+bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
 {
    // FIXME: add progress reporting for this operation
    // Do we have different architectures in your groups ?
@@ -923,7 +923,7 @@ static unsigned long ComputeSize(FileIterator Start,FileIterator End)
 // ---------------------------------------------------------------------
 /* */
 static bool BuildCache(pkgCacheGenerator &Gen,
-                      OpProgress &Progress,
+                      OpProgress *Progress,
                       unsigned long &CurrentSize,unsigned long TotalSize,
                       FileIterator Start, FileIterator End)
 {
@@ -944,7 +944,8 @@ static bool BuildCache(pkgCacheGenerator &Gen,
       }
       
       unsigned long Size = (*I)->Size();
-      Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
+      if (Progress != NULL)
+        Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
       CurrentSize += Size;
       
       if ((*I)->Merge(Gen,Progress) == false)
@@ -953,13 +954,15 @@ static bool BuildCache(pkgCacheGenerator &Gen,
 
    if (Gen.HasFileDeps() == true)
    {
-      Progress.Done();
+      if (Progress != NULL)
+        Progress->Done();
       TotalSize = ComputeSize(Start, End);
       CurrentSize = 0;
       for (I = Start; I != End; I++)
       {
         unsigned long Size = (*I)->Size();
-        Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
+        if (Progress != NULL)
+           Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
         CurrentSize += Size;
         if ((*I)->MergeFileProvides(Gen,Progress) == false)
            return false;
@@ -969,7 +972,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
    return true;
 }
                                                                        /*}}}*/
-// MakeStatusCache - Construct the status cache                                /*{{{*/
+// CacheGenerator::MakeStatusCache - Construct the status cache                /*{{{*/
 // ---------------------------------------------------------------------
 /* This makes sure that the status cache (the cache that has all 
    index files from the sources list and all local ones) is ready
@@ -977,7 +980,10 @@ static bool BuildCache(pkgCacheGenerator &Gen,
    the cache will be stored there. This is pretty much mandetory if you
    are using AllowMem. AllowMem lets the function be run as non-root
    where it builds the cache 'fast' into a memory buffer. */
-bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
+__deprecated bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
+                       MMap **OutMap, bool AllowMem)
+   { return pkgCacheGenerator::MakeStatusCache(List, &Progress, OutMap, AllowMem); }
+bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
                        MMap **OutMap,bool AllowMem)
 {
    bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
@@ -1028,13 +1034,15 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
 
    if (Writeable == false && AllowMem == false && CacheFile.empty() == false)
       return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str());
-   
-   Progress.OverallProgress(0,1,1,_("Reading package lists"));
-   
+
+   if (Progress != NULL)
+      Progress->OverallProgress(0,1,1,_("Reading package lists"));
+
    // Cache is OK, Fin.
    if (CheckValidity(CacheFile,Files.begin(),Files.end(),OutMap) == true)
    {
-      Progress.OverallProgress(1,1,1,_("Reading package lists"));
+      if (Progress != NULL)
+        Progress->OverallProgress(1,1,1,_("Reading package lists"));
       if (Debug == true)
         std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
       return true;
@@ -1084,7 +1092,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
       TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
 
       // Build the status cache
-      pkgCacheGenerator Gen(Map.Get(),&Progress);
+      pkgCacheGenerator Gen(Map.Get(),Progress);
       if (_error->PendingError() == true)
         return false;
       if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
@@ -1101,7 +1109,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
       TotalSize = ComputeSize(Files.begin(),Files.end());
       
       // Build the source cache
-      pkgCacheGenerator Gen(Map.Get(),&Progress);
+      pkgCacheGenerator Gen(Map.Get(),Progress);
       if (_error->PendingError() == true)
         return false;
       if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
@@ -1160,10 +1168,12 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
    return true;
 }
                                                                        /*}}}*/
-// MakeOnlyStatusCache - Build a cache with just the status files      /*{{{*/
+// CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
+__deprecated bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
+   { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress, OutMap); }
+bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
 {
    unsigned long MapSize = _config->FindI("APT::Cache-Limit",20*1024*1024);
    vector<pkgIndexFile *> Files;
@@ -1178,8 +1188,9 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
    TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
    
    // Build the status cache
-   Progress.OverallProgress(0,1,1,_("Reading package lists"));
-   pkgCacheGenerator Gen(Map.Get(),&Progress);
+   if (Progress != NULL)
+      Progress->OverallProgress(0,1,1,_("Reading package lists"));
+   pkgCacheGenerator Gen(Map.Get(),Progress);
    if (_error->PendingError() == true)
       return false;
    if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
index 46d0cd8..ff0941e 100644 (file)
@@ -76,7 +76,11 @@ class pkgCacheGenerator                                                      /*{{{*/
 
    bool HasFileDeps() {return FoundFileDeps;};
    bool MergeFileProvides(ListParser &List);
-   bool FinishCache(OpProgress &Progress);
+   bool FinishCache(OpProgress *Progress);
+
+   static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
+                       MMap **OutMap = 0,bool AllowMem = false);
+   static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap);
 
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
    ~pkgCacheGenerator();
@@ -134,10 +138,12 @@ class pkgCacheGenerator::ListParser
    virtual ~ListParser() {};
 };
                                                                        /*}}}*/
+
 bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
                        MMap **OutMap = 0,bool AllowMem = false);
 bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);
 
+
 #ifdef APT_COMPATIBILITY
 #if APT_COMPATIBILITY != 986
 #warning "Using APT_COMPATIBILITY"
@@ -145,7 +151,7 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);
 MMap *pkgMakeStatusCacheMem(pkgSourceList &List,OpProgress &Progress)
 {
    MMap *Map = 0;
-   if (pkgMakeStatusCache(List,Progress,&Map,true) == false)
+   if (pkgCacheGenerator::MakeStatusCache(List,&Progress,&Map,true) == false)
       return 0;
    return Map;
 }
index 0d4999e..1394d7e 100644 (file)
@@ -365,6 +365,30 @@ signed int pkgTagSection::FindI(const char *Tag,signed long Default) const
    return Result;
 }
                                                                        /*}}}*/
+// TagSection::FindULL - Find an unsigned long long integer            /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long const &Default) const
+{
+   const char *Start;
+   const char *Stop;
+   if (Find(Tag,Start,Stop) == false)
+      return Default;
+
+   // Copy it into a temp buffer so we can use strtoull
+   char S[100];
+   if ((unsigned)(Stop - Start) >= sizeof(S))
+      return Default;
+   strncpy(S,Start,Stop-Start);
+   S[Stop - Start] = 0;
+   
+   char *End;
+   unsigned long long Result = strtoull(S,&End,10);
+   if (S == End)
+      return Default;
+   return Result;
+}
+                                                                       /*}}}*/
 // TagSection::FindFlag - Locate a yes/no type flag                    /*{{{*/
 // ---------------------------------------------------------------------
 /* The bits marked in Flag are masked on/off in Flags */
index f63a51d..6891c1d 100644 (file)
@@ -57,6 +57,7 @@ class pkgTagSection
    bool Find(const char *Tag,unsigned &Pos) const;
    string FindS(const char *Tag) const;
    signed int FindI(const char *Tag,signed long Default = 0) const ;
+   unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    bool FindFlag(const char *Tag,unsigned long &Flags,
                 unsigned long Flag) const;
    bool Scan(const char *Start,unsigned long MaxLength);
index 10dbf44..7cb95b3 100644 (file)
@@ -29,6 +29,7 @@
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/sptr.h>
+#include <apt-pkg/cacheset.h>
 
 #include <config.h>
 #include <apti18n.h>
@@ -45,9 +46,6 @@
 
 using namespace std;
 
-pkgCache *GCache = 0;
-pkgSourceList *SrcList = 0;
-
 // LocalitySort - Sort a version list by package file locality         /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -83,15 +81,8 @@ void LocalitySort(pkgCache::DescFile **begin,
 // UnMet - Show unmet dependencies                                     /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool UnMet(CommandLine &CmdL)
+bool ShowUnMet(pkgCache::VerIterator const &V, bool const &Important)
 {
-   pkgCache &Cache = *GCache;
-   bool Important = _config->FindB("APT::Cache::Important",false);
-   
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
-   {
-      for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
-      {
         bool Header = false;
         for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
         {
@@ -99,20 +90,19 @@ bool UnMet(CommandLine &CmdL)
            pkgCache::DepIterator Start;
            pkgCache::DepIterator End;
            D.GlobOr(Start,End);
-           
-           // Skip conflicts and replaces
-           if (End->Type != pkgCache::Dep::PreDepends &&
-               End->Type != pkgCache::Dep::Depends && 
-               End->Type != pkgCache::Dep::Suggests &&
-               End->Type != pkgCache::Dep::Recommends)
-              continue;
 
            // Important deps only
            if (Important == true)
               if (End->Type != pkgCache::Dep::PreDepends &&
                   End->Type != pkgCache::Dep::Depends)
                  continue;
-           
+
+           // Skip conflicts and replaces
+           if (End->Type == pkgCache::Dep::DpkgBreaks ||
+               End->Type == pkgCache::Dep::Replaces ||
+               End->Type == pkgCache::Dep::Conflicts)
+              continue;
+
            // Verify the or group
            bool OK = false;
            pkgCache::DepIterator RealStart = Start;
@@ -141,7 +131,7 @@ bool UnMet(CommandLine &CmdL)
            // Oops, it failed..
            if (Header == false)
               ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
-                       P.FullName(true).c_str(),V.VerStr());
+                       V.ParentPkg().FullName(true).c_str(),V.VerStr());
            Header = true;
            
            // Print out the dep type
@@ -163,9 +153,31 @@ bool UnMet(CommandLine &CmdL)
            while (1);
            
            cout << endl;
-        }       
-      }
-   }   
+        }
+   return true;
+}
+bool UnMet(CommandLine &CmdL)
+{
+   bool const Important = _config->FindB("APT::Cache::Important",false);
+
+   pkgCacheFile CacheFile;
+   if (unlikely(CacheFile.GetPkgCache() == NULL))
+      return false;
+
+   if (CmdL.FileSize() <= 1)
+   {
+      for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; P++)
+        for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
+           if (ShowUnMet(V, Important) == false)
+              return false;
+   }
+   else
+   {
+      APT::VersionSet verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
+      for (APT::VersionSet::iterator V = verset.begin(); V != verset.end(); ++V)
+        if (ShowUnMet(V, Important) == false)
+           return false;
+   }
    return true;
 }
                                                                        /*}}}*/
@@ -173,17 +185,12 @@ bool UnMet(CommandLine &CmdL)
 // ---------------------------------------------------------------------
 /* */
 bool DumpPackage(CommandLine &CmdL)
-{   
-   pkgCache &Cache = *GCache;
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
+{
+   pkgCacheFile CacheFile;
+   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
 
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   {
       cout << "Package: " << Pkg.FullName(true) << endl;
       cout << "Versions: " << endl;
       for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
@@ -243,18 +250,22 @@ bool DumpPackage(CommandLine &CmdL)
 /* */
 bool Stats(CommandLine &Cmd)
 {
-   pkgCache &Cache = *GCache;
-   cout << _("Total package names: ") << Cache.Head().GroupCount << " (" <<
-      SizeToStr(Cache.Head().GroupCount*Cache.Head().GroupSz) << ')' << endl
-        << _("Total package structures: ") << Cache.Head().PackageCount << " (" <<
-      SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
+   cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
+      SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
+        << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
+      SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
 
    int Normal = 0;
    int Virtual = 0;
    int NVirt = 0;
    int DVirt = 0;
    int Missing = 0;
-   pkgCache::PkgIterator I = Cache.PkgBegin();
+   pkgCache::PkgIterator I = Cache->PkgBegin();
    for (;I.end() != true; I++)
    {
       if (I->VersionList != 0 && I->ProvidesList == 0)
@@ -292,33 +303,33 @@ bool Stats(CommandLine &Cmd)
    cout << _("  Mixed virtual packages: ") << NVirt << endl;
    cout << _("  Missing: ") << Missing << endl;
    
-   cout << _("Total distinct versions: ") << Cache.Head().VersionCount << " (" <<
-      SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
-   cout << _("Total distinct descriptions: ") << Cache.Head().DescriptionCount << " (" <<
-      SizeToStr(Cache.Head().DescriptionCount*Cache.Head().DescriptionSz) << ')' << endl;
-   cout << _("Total dependencies: ") << Cache.Head().DependsCount << " (" << 
-      SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
+   cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
+      SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
+   cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
+      SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
+   cout << _("Total dependencies: ") << Cache->Head().DependsCount << " (" << 
+      SizeToStr(Cache->Head().DependsCount*Cache->Head().DependencySz) << ')' << endl;
    
-   cout << _("Total ver/file relations: ") << Cache.Head().VerFileCount << " (" <<
-      SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
-   cout << _("Total Desc/File relations: ") << Cache.Head().DescFileCount << " (" <<
-      SizeToStr(Cache.Head().DescFileCount*Cache.Head().DescFileSz) << ')' << endl;
-   cout << _("Total Provides mappings: ") << Cache.Head().ProvidesCount << " (" <<
-      SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
+   cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
+      SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
+   cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
+      SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
+   cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
+      SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
    
    // String list stats
    unsigned long Size = 0;
    unsigned long Count = 0;
-   for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
-        I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
+   for (pkgCache::StringItem *I = Cache->StringItemP + Cache->Head().StringList;
+        I!= Cache->StringItemP; I = Cache->StringItemP + I->NextItem)
    {
       Count++;
-      Size += strlen(Cache.StrP + I->String) + 1;
+      Size += strlen(Cache->StrP + I->String) + 1;
    }
    cout << _("Total globbed strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
 
    unsigned long DepVerSize = 0;
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
    {
       for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
       {
@@ -333,15 +344,15 @@ bool Stats(CommandLine &Cmd)
    
    unsigned long Slack = 0;
    for (int I = 0; I != 7; I++)
-      Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
+      Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
    cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
    
    unsigned long Total = 0;
-   Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz + 
-           Cache.Head().VersionCount*Cache.Head().VersionSz +
-           Cache.Head().PackageCount*Cache.Head().PackageSz + 
-           Cache.Head().VerFileCount*Cache.Head().VerFileSz +
-           Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
+   Total = Slack + Size + Cache->Head().DependsCount*Cache->Head().DependencySz + 
+           Cache->Head().VersionCount*Cache->Head().VersionSz +
+           Cache->Head().PackageCount*Cache->Head().PackageSz + 
+           Cache->Head().VerFileCount*Cache->Head().VerFileSz +
+           Cache->Head().ProvidesCount*Cache->Head().ProvidesSz;
    cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
    
    return true;
@@ -352,10 +363,14 @@ bool Stats(CommandLine &Cmd)
 /* This is worthless except fer debugging things */
 bool Dump(CommandLine &Cmd)
 {
-   pkgCache &Cache = *GCache;
-   cout << "Using Versioning System: " << Cache.VS->Label << endl;
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
+   cout << "Using Versioning System: " << Cache->VS->Label << endl;
    
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
    {
       cout << "Package: " << P.FullName(true) << endl;
       for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
@@ -374,7 +389,7 @@ bool Dump(CommandLine &Cmd)
       }      
    }
 
-   for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
+   for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; F++)
    {
       cout << "File: " << F.FileName() << endl;
       cout << " Type: " << F.IndexType() << endl;
@@ -400,18 +415,17 @@ bool Dump(CommandLine &Cmd)
    make this run really fast, perhaps I went a little overboard.. */
 bool DumpAvail(CommandLine &Cmd)
 {
-   pkgCache &Cache = *GCache;
-
-   pkgPolicy Plcy(&Cache);
-   if (ReadPinFile(Plcy) == false || ReadPinDir(Plcy) == false)
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
       return false;
-   
-   unsigned long Count = Cache.HeaderP->PackageCount+1;
+
+   unsigned long Count = Cache->HeaderP->PackageCount+1;
    pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
    memset(VFList,0,sizeof(*VFList)*Count);
    
    // Map versions that we want to write out onto the VerList array.
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
    {    
       if (P->VersionList == 0)
         continue;
@@ -419,7 +433,7 @@ bool DumpAvail(CommandLine &Cmd)
       /* Find the proper version to use. If the policy says there are no
          possible selections we return the installed version, if available..
                 This prevents dselect from making it obsolete. */
-      pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
+      pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
       if (V.end() == true)
       {
         if (P->CurrentVer == 0)
@@ -464,10 +478,10 @@ bool DumpAvail(CommandLine &Cmd)
    LocalitySort(VFList,Count,sizeof(*VFList));
 
    // Iterate over all the package files and write them out.
-   char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
+   char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
    for (pkgCache::VerFile **J = VFList; *J != 0;)
    {
-      pkgCache::PkgFileIterator File(Cache,(*J)->File + Cache.PkgFileP);
+      pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
       if (File.IsOk() == false)
       {
         _error->Error(_("Package file %s is out of sync."),File.FileName());
@@ -486,7 +500,7 @@ bool DumpAvail(CommandLine &Cmd)
       unsigned long Pos = 0;
       for (; *J != 0; J++)
       {
-        if ((*J)->File + Cache.PkgFileP != File)
+        if ((*J)->File + Cache->PkgFileP != File)
            break;
         
         const pkgCache::VerFile &VF = **J;
@@ -542,21 +556,18 @@ bool DumpAvail(CommandLine &Cmd)
 /* */
 bool Depends(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
-   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
-   
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
+   SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
+   memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
+
+   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
       Colours[Pkg->ID] = 1;
-   }
-   
+
    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
    bool Installed = _config->FindB("APT::Cache::Installed",false);
    bool Important = _config->FindB("APT::Cache::Important",false);
@@ -564,7 +575,7 @@ bool Depends(CommandLine &CmdL)
    do
    {
       DidSomething = false;
-      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
       {
         if (Colours[Pkg->ID] != 1)
            continue;
@@ -611,11 +622,11 @@ bool Depends(CommandLine &CmdL)
            
            // Display all solutions
            SPtrArray<pkgCache::Version *> List = D.AllTargets();
-           pkgPrioSortList(Cache,List);
+           pkgPrioSortList(*Cache,List);
            for (pkgCache::Version **I = List; *I != 0; I++)
            {
-              pkgCache::VerIterator V(Cache,*I);
-              if (V != Cache.VerP + V.ParentPkg()->VersionList ||
+              pkgCache::VerIterator V(*Cache,*I);
+              if (V != Cache->VerP + V.ParentPkg()->VersionList ||
                   V->ParentPkg == D->Package)
                  continue;
               cout << "    " << V.ParentPkg().FullName(true) << endl;
@@ -636,28 +647,25 @@ bool Depends(CommandLine &CmdL)
 /* */
 bool RDepends(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
-   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
-   
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
+   SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
+   memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
+
+   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
       Colours[Pkg->ID] = 1;
-   }
-   
+
    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
    bool Installed = _config->FindB("APT::Cache::Installed",false);
    bool DidSomething;
    do
    {
       DidSomething = false;
-      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
       {
         if (Colours[Pkg->ID] != 1)
            continue;
@@ -699,11 +707,11 @@ bool RDepends(CommandLine &CmdL)
            
            // Display all solutions
            SPtrArray<pkgCache::Version *> List = D.AllTargets();
-           pkgPrioSortList(Cache,List);
+           pkgPrioSortList(*Cache,List);
            for (pkgCache::Version **I = List; *I != 0; I++)
            {
-              pkgCache::VerIterator V(Cache,*I);
-              if (V != Cache.VerP + V.ParentPkg()->VersionList ||
+              pkgCache::VerIterator V(*Cache,*I);
+              if (V != Cache->VerP + V.ParentPkg()->VersionList ||
                   V->ParentPkg == D->Package)
                  continue;
               cout << "    " << V.ParentPkg().FullName(true) << endl;
@@ -725,7 +733,11 @@ bool RDepends(CommandLine &CmdL)
 
 bool XVcg(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
    bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
    
    /* Normal packages are boxes
@@ -742,21 +754,21 @@ bool XVcg(CommandLine &CmdL)
       0 = None */
    enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
    enum TheFlags {ForceNR=(1<<0)};
-   unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
-   unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
-   unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
+   unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
+   unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
+   unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
    
    // Show everything if no arguments given
    if (CmdL.FileList[1] == 0)
-      for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
+      for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
         Show[I] = ToShow;
    else
-      for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
+      for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
         Show[I] = None;
-   memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
+   memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
    
    // Map the shapes
-   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
    {   
       if (Pkg->VersionList == 0)
       {
@@ -775,38 +787,24 @@ bool XVcg(CommandLine &CmdL)
            ShapeMap[Pkg->ID] = 3;
       }
    }
-   
+
    // Load the list of packages from the command line into the show list
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   std::list<APT::PackageSet::Modifier> mods;
+   mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
+   mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
+   std::map<unsigned short, APT::PackageSet> pkgsets =
+               APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0);
+
+   for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
+       Pkg != pkgsets[0].end(); ++Pkg)
+      Show[Pkg->ID] = ToShow;
+   for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
+       Pkg != pkgsets[1].end(); ++Pkg)
    {
-      // Process per-package flags
-      string P = *I;
-      bool Force = false;
-      if (P.length() > 3)
-      {
-        if (P.end()[-1] == '^')
-        {
-           Force = true;
-           P.erase(P.end()-1);
-        }
-        
-        if (P.end()[-1] == ',')
-           P.erase(P.end()-1);
-      }
-      
-      // Locate the package
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
       Show[Pkg->ID] = ToShow;
-      
-      if (Force == true)
-        Flags[Pkg->ID] |= ForceNR;
+      Flags[Pkg->ID] |= ForceNR;
    }
-   
+
    // Little header
    cout << "graph: { title: \"packages\"" << endl <<
      "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
@@ -816,7 +814,7 @@ bool XVcg(CommandLine &CmdL)
    while (Act == true)
    {
       Act = false;
-      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
       {
         // See we need to show this package
         if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
@@ -851,7 +849,7 @@ bool XVcg(CommandLine &CmdL)
            for (pkgCache::VerIterator I = DPkg.VersionList();
                      I.end() == false && Hit == false; I++)
            {
-              if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
+              if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
                  Hit = true;
            }
            
@@ -859,7 +857,7 @@ bool XVcg(CommandLine &CmdL)
            for (pkgCache::PrvIterator I = DPkg.ProvidesList(); 
                      I.end() == false && Hit == false; I++)
            {
-              if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
+              if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
                  Hit = true;
            }
            
@@ -920,7 +918,7 @@ bool XVcg(CommandLine &CmdL)
    
    /* Draw the box colours after the fact since we can not tell what colour
       they should be until everything is finished drawing */
-   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
    {
       if (Show[Pkg->ID] < DoneNR)
         continue;
@@ -949,7 +947,11 @@ bool XVcg(CommandLine &CmdL)
    http://www.research.att.com/sw/tools/graphviz/ */
 bool Dotty(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
    bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
    
    /* Normal packages are boxes
@@ -966,21 +968,21 @@ bool Dotty(CommandLine &CmdL)
       0 = None */
    enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
    enum TheFlags {ForceNR=(1<<0)};
-   unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
-   unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
-   unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
+   unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
+   unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
+   unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
    
    // Show everything if no arguments given
    if (CmdL.FileList[1] == 0)
-      for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
+      for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
         Show[I] = ToShow;
    else
-      for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
+      for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
         Show[I] = None;
-   memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
+   memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
    
    // Map the shapes
-   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
    {   
       if (Pkg->VersionList == 0)
       {
@@ -999,38 +1001,24 @@ bool Dotty(CommandLine &CmdL)
            ShapeMap[Pkg->ID] = 3;
       }
    }
-   
+
    // Load the list of packages from the command line into the show list
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   std::list<APT::PackageSet::Modifier> mods;
+   mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
+   mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
+   std::map<unsigned short, APT::PackageSet> pkgsets =
+               APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0);
+
+   for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
+       Pkg != pkgsets[0].end(); ++Pkg)
+      Show[Pkg->ID] = ToShow;
+   for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
+       Pkg != pkgsets[1].end(); ++Pkg)
    {
-      // Process per-package flags
-      string P = *I;
-      bool Force = false;
-      if (P.length() > 3)
-      {
-        if (P.end()[-1] == '^')
-        {
-           Force = true;
-           P.erase(P.end()-1);
-        }
-        
-        if (P.end()[-1] == ',')
-           P.erase(P.end()-1);
-      }
-      
-      // Locate the package
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
       Show[Pkg->ID] = ToShow;
-      
-      if (Force == true)
-        Flags[Pkg->ID] |= ForceNR;
+      Flags[Pkg->ID] |= ForceNR;
    }
-   
+
    // Little header
    printf("digraph packages {\n");
    printf("concentrate=true;\n");
@@ -1040,7 +1028,7 @@ bool Dotty(CommandLine &CmdL)
    while (Act == true)
    {
       Act = false;
-      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
       {
         // See we need to show this package
         if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
@@ -1073,7 +1061,7 @@ bool Dotty(CommandLine &CmdL)
            for (pkgCache::VerIterator I = DPkg.VersionList();
                      I.end() == false && Hit == false; I++)
            {
-              if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
+              if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
                  Hit = true;
            }
            
@@ -1081,7 +1069,7 @@ bool Dotty(CommandLine &CmdL)
            for (pkgCache::PrvIterator I = DPkg.ProvidesList(); 
                      I.end() == false && Hit == false; I++)
            {
-              if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
+              if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
                  Hit = true;
            }
            
@@ -1135,7 +1123,7 @@ bool Dotty(CommandLine &CmdL)
    
    /* Draw the box colours after the fact since we can not tell what colour
       they should be until everything is finished drawing */
-   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
    {
       if (Show[Pkg->ID] < DoneNR)
         continue;
@@ -1209,8 +1197,12 @@ bool DoAdd(CommandLine &CmdL)
 // ---------------------------------------------------------------------
 /* This displays the package record from the proper package index file. 
    It is not used by DumpAvail for performance reasons. */
-bool DisplayRecord(pkgCache::VerIterator V)
+bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
 {
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
    // Find an appropriate file
    pkgCache::VerFileIterator Vf = V.FileList();
    for (; Vf.end() == false; Vf++)
@@ -1223,13 +1215,13 @@ bool DisplayRecord(pkgCache::VerIterator V)
    pkgCache::PkgFileIterator I = Vf.File();
    if (I.IsOk() == false)
       return _error->Error(_("Package file %s is out of sync."),I.FileName());
-   
-   FileFd PkgF(I.FileName(),FileFd::ReadOnly);
-   if (_error->PendingError() == true)
+
+   FileFd PkgF;
+   if (PkgF.Open(I.FileName(), FileFd::ReadOnly) == false)
       return false;
-   
+
    // Read the record
-   unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
+   unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+1];
    Buffer[V.FileList()->Size] = '\n';
    if (PkgF.Seek(V.FileList()->Offset) == false ||
        PkgF.Read(Buffer,V.FileList()->Size) == false)
@@ -1249,7 +1241,7 @@ bool DisplayRecord(pkgCache::VerIterator V)
    }
 
    // Show the right description
-   pkgRecords Recs(*GCache);
+   pkgRecords Recs(*Cache);
    pkgCache::DescIterator Desc = V.TranslatedDescription();
    pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
    cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
@@ -1289,16 +1281,19 @@ struct ExDescFile
 /* This searches the package names and package descriptions for a pattern */
 bool Search(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
-   bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
-   unsigned NumPatterns = CmdL.FileSize() -1;
-   
-   pkgDepCache::Policy Plcy;
-   
+   bool const ShowFull = _config->FindB("APT::Cache::ShowFull",false);
+   bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
+   unsigned int const NumPatterns = CmdL.FileSize() -1;
+   
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
+   if (unlikely(Cache == NULL || Plcy == NULL))
+      return false;
+
    // Make sure there is at least one argument
    if (NumPatterns < 1)
-      return _error->Error(_("You must give exactly one pattern"));
+      return _error->Error(_("You must give at least one search pattern"));
    
    // Compile the regex pattern
    regex_t *Patterns = new regex_t[NumPatterns];
@@ -1314,8 +1309,6 @@ bool Search(CommandLine &CmdL)
       }      
    }
    
-   // Create the text record parser
-   pkgRecords Recs(Cache);
    if (_error->PendingError() == true)
    {
       for (unsigned I = 0; I != NumPatterns; I++)
@@ -1323,70 +1316,75 @@ bool Search(CommandLine &CmdL)
       return false;
    }
    
-   ExDescFile *DFList = new ExDescFile[Cache.HeaderP->PackageCount+1];
-   memset(DFList,0,sizeof(*DFList)*Cache.HeaderP->PackageCount+1);
+   ExDescFile *DFList = new ExDescFile[Cache->HeaderP->GroupCount+1];
+   memset(DFList,0,sizeof(*DFList)*Cache->HeaderP->GroupCount+1);
 
    // Map versions that we want to write out onto the VerList array.
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
    {
-      DFList[P->ID].NameMatch = NumPatterns != 0;
+      if (DFList[G->ID].NameMatch == true)
+        continue;
+
+      DFList[G->ID].NameMatch = true;
       for (unsigned I = 0; I != NumPatterns; I++)
       {
-        if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
-           DFList[P->ID].NameMatch &= true;
-        else
-           DFList[P->ID].NameMatch = false;
+        if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
+           continue;
+        DFList[G->ID].NameMatch = false;
+        break;
       }
         
       // Doing names only, drop any that dont match..
-      if (NamesOnly == true && DFList[P->ID].NameMatch == false)
+      if (NamesOnly == true && DFList[G->ID].NameMatch == false)
         continue;
         
-      // Find the proper version to use. 
-      pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
+      // Find the proper version to use
+      pkgCache::PkgIterator P = G.FindPreferredPkg();
+      if (P.end() == true)
+        continue;
+      pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
       if (V.end() == false)
-        DFList[P->ID].Df = V.DescriptionList().FileList();
-   }
-      
-   // Include all the packages that provide matching names too
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
-   {
-      if (DFList[P->ID].NameMatch == false)
+        DFList[G->ID].Df = V.DescriptionList().FileList();
+
+      if (DFList[G->ID].NameMatch == false)
         continue;
 
+      // Include all the packages that provide matching names too
       for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
       {
-        pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
-        if (V.end() == false)
-        {
-           DFList[Prv.OwnerPkg()->ID].Df = V.DescriptionList().FileList();
-           DFList[Prv.OwnerPkg()->ID].NameMatch = true;
-        }
+        pkgCache::VerIterator V = Plcy->GetCandidateVer(Prv.OwnerPkg());
+        if (V.end() == true)
+           continue;
+
+        unsigned long id = Prv.OwnerPkg().Group()->ID;
+        DFList[id].Df = V.DescriptionList().FileList();
+        DFList[id].NameMatch = true;
       }
    }
    
-   LocalitySort(&DFList->Df,Cache.HeaderP->PackageCount,sizeof(*DFList));
+   LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
 
+   // Create the text record parser
+   pkgRecords Recs(*Cache);
    // Iterate over all the version records and check them
    for (ExDescFile *J = DFList; J->Df != 0; J++)
    {
-      pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(Cache,J->Df));
+      pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
 
-      bool Match = true;
-      if (J->NameMatch == false)
+      if (J->NameMatch == false && NamesOnly == false)
       {
-        string LongDesc = P.LongDesc();
-        Match = NumPatterns != 0;
+        string const LongDesc = P.LongDesc();
+        J->NameMatch = true;
         for (unsigned I = 0; I != NumPatterns; I++)
         {
            if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
-              Match &= true;
-           else
-              Match = false;
+              continue;
+           J->NameMatch = false;
+           break;
         }
       }
       
-      if (Match == true)
+      if (J->NameMatch == true)
       {
         if (ShowFull == true)
         {
@@ -1413,15 +1411,17 @@ bool Search(CommandLine &CmdL)
 /* show automatically installed packages (sorted) */
 bool ShowAuto(CommandLine &CmdL)
 {
-   OpProgress op;
-   pkgDepCache DepCache(GCache);
-   DepCache.Init(&op);
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   pkgDepCache *DepCache = CacheFile.GetDepCache();
+   if (unlikely(Cache == NULL || DepCache == NULL))
+      return false;
 
    std::vector<string> packages;
-   packages.reserve(GCache->HeaderP->PackageCount / 3);
+   packages.reserve(Cache->HeaderP->PackageCount / 3);
    
-   for (pkgCache::PkgIterator P = GCache->PkgBegin(); P.end() == false; P++)
-      if (DepCache[P].Flags & pkgCache::Flag::Auto)
+   for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
+      if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
          packages.push_back(P.Name());
 
     std::sort(packages.begin(), packages.end());
@@ -1436,48 +1436,16 @@ bool ShowAuto(CommandLine &CmdL)
 // ---------------------------------------------------------------------
 /* */
 bool ShowPackage(CommandLine &CmdL)
-{   
-   pkgCache &Cache = *GCache;
-   pkgDepCache::Policy Plcy;
-
-   unsigned found = 0;
-   
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      // FIXME: Handle the case in which pkgname name:arch is not found
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        Pkg = Cache.FindPkg(*I, "any");
-        if (Pkg.end() == true) {
-               _error->Warning(_("Unable to locate package %s"),*I);
-               continue;
-        }
-      }
-
-      ++found;
-
-      // Find the proper version to use.
-      if (_config->FindB("APT::Cache::AllVersions","true") == true)
-      {
-        pkgCache::VerIterator V;
-        for (V = Pkg.VersionList(); V.end() == false; V++)
-        {
-           if (DisplayRecord(V) == false)
-              return false;
-        }
-      }
-      else
-      {
-        pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
-        if (V.end() == true || V.FileList().end() == true)
-           continue;
-        if (DisplayRecord(V) == false)
-           return false;
-      }      
-   }
-
-   if (found > 0)
+{
+   pkgCacheFile CacheFile;
+   APT::VersionSet::Version const select = _config->FindB("APT::Cache::AllVersions", true) ?
+                       APT::VersionSet::ALL : APT::VersionSet::CANDIDATE;
+   APT::VersionSet const verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, select);
+   for (APT::VersionSet::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
+      if (DisplayRecord(CacheFile, Ver) == false)
+        return false;
+
+   if (verset.empty() == false)
         return true;
    return _error->Error(_("No packages found"));
 }
@@ -1487,8 +1455,10 @@ bool ShowPackage(CommandLine &CmdL)
 /* This does a prefix match on the first argument */
 bool ShowPkgNames(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   pkgCache::GrpIterator I = Cache.GrpBegin();
+   pkgCacheFile CacheFile;
+   if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
+      return false;
+   pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
    bool const All = _config->FindB("APT::Cache::AllNames","false");
 
    if (CmdL.FileList[1] != 0)
@@ -1524,11 +1494,13 @@ bool ShowPkgNames(CommandLine &CmdL)
 /* */
 bool ShowSrcPackage(CommandLine &CmdL)
 {
-   pkgSourceList List;
-   List.ReadMainList();
-   
+   pkgCacheFile CacheFile;
+   pkgSourceList *List = CacheFile.GetSourceList();
+   if (unlikely(List == NULL))
+      return false;
+
    // Create the text record parsers
-   pkgSrcRecords SrcRecs(List);
+   pkgSrcRecords SrcRecs(*List);
    if (_error->PendingError() == true)
       return false;
 
@@ -1559,19 +1531,24 @@ bool ShowSrcPackage(CommandLine &CmdL)
 /* */
 bool Policy(CommandLine &CmdL)
 {
-   if (SrcList == 0)
-      return _error->Error("Generate must be enabled for this function");
-   
-   pkgCache &Cache = *GCache;
-   pkgPolicy Plcy(&Cache);
-   if (ReadPinFile(Plcy) == false || ReadPinDir(Plcy) == false)
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   pkgPolicy *Plcy = CacheFile.GetPolicy();
+   pkgSourceList *SrcList = CacheFile.GetSourceList();
+   if (unlikely(Cache == NULL || Plcy == NULL || SrcList == NULL))
       return false;
-   
+
+   /* Should the MultiArchKiller be run to see which pseudo packages for an
+      arch all package are currently installed? Activating it gives a speed
+      penality for no real gain beside enhanced debugging, so in general no. */
+   if (_config->FindB("APT::Cache::Policy::DepCache", false) == true)
+      CacheFile.GetDepCache();
+
    // Print out all of the package files
    if (CmdL.FileList[1] == 0)
    {
       cout << _("Package files:") << endl;   
-      for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
+      for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; F++)
       {
         // Locate the associated index files so we can derive a description
         pkgIndexFile *Indx;
@@ -1580,7 +1557,7 @@ bool Policy(CommandLine &CmdL)
            return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
         
         printf("%4i %s\n",
-               Plcy.GetPriority(F),Indx->Describe(true).c_str());
+               Plcy->GetPriority(F),Indx->Describe(true).c_str());
         
         // Print the reference information for the package
         string Str = F.RelStr();
@@ -1592,16 +1569,16 @@ bool Policy(CommandLine &CmdL)
       
       // Show any packages have explicit pins
       cout << _("Pinned packages:") << endl;
-      pkgCache::PkgIterator I = Cache.PkgBegin();
+      pkgCache::PkgIterator I = Cache->PkgBegin();
       for (;I.end() != true; I++)
       {
-        if (Plcy.GetPriority(I) == 0)
+        if (Plcy->GetPriority(I) == 0)
            continue;
 
         // Print the package name and the version we are forcing to
         cout << "     " << I.FullName(true) << " -> ";
         
-        pkgCache::VerIterator V = Plcy.GetMatch(I);
+        pkgCache::VerIterator V = Plcy->GetMatch(I);
         if (V.end() == true)
            cout << _("(not found)") << endl;
         else
@@ -1622,17 +1599,12 @@ bool Policy(CommandLine &CmdL)
                (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
 
    // Print out detailed information for each package
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
+   for (APT::PackageSet::const_iterator I = pkgset.begin(); I != pkgset.end(); ++I)
    {
-      pkgCache::GrpIterator Grp = Cache.FindGrp(*I);
-      pkgCache::PkgIterator Pkg = Grp.FindPkg("any");
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
+      pkgCache::PkgIterator Pkg = I.Group().FindPkg("any");
 
-      for (; Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) {
+      for (; Pkg.end() != true; Pkg = I.Group().NextPkg(Pkg)) {
       if (strcmp(Pkg.Arch(),"all") == 0)
         continue;
 
@@ -1647,17 +1619,17 @@ bool Policy(CommandLine &CmdL)
       
       // Candidate Version 
       cout << msgCandidate << OutputInDepth(deepCandidate, " ");
-      pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
+      pkgCache::VerIterator V = Plcy->GetCandidateVer(Pkg);
       if (V.end() == true)
         cout << _("(none)") << endl;
       else
         cout << V.VerStr() << endl;
 
       // Pinned version
-      if (Plcy.GetPriority(Pkg) != 0)
+      if (Plcy->GetPriority(Pkg) != 0)
       {
         cout << _("  Package pin: ");
-        V = Plcy.GetMatch(Pkg);
+        V = Plcy->GetMatch(Pkg);
         if (V.end() == true)
            cout << _("(not found)") << endl;
         else
@@ -1672,7 +1644,7 @@ bool Policy(CommandLine &CmdL)
            cout << " *** " << V.VerStr();
         else
            cout << "     " << V.VerStr();
-        cout << " " << Plcy.GetPriority(Pkg) << endl;
+        cout << " " << Plcy->GetPriority(Pkg) << endl;
         for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
         {
            // Locate the associated index files so we can derive a description
@@ -1680,7 +1652,7 @@ bool Policy(CommandLine &CmdL)
            if (SrcList->FindIndex(VF.File(),Indx) == false &&
                _system->FindIndex(VF.File(),Indx) == false)
               return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
-           printf("       %4i %s\n",Plcy.GetPriority(VF.File()),
+           printf("       %4i %s\n",Plcy->GetPriority(VF.File()),
                   Indx->Describe(true).c_str());
         }
       }
@@ -1695,12 +1667,11 @@ bool Policy(CommandLine &CmdL)
 /* */
 bool Madison(CommandLine &CmdL)
 {
-   if (SrcList == 0)
-      return _error->Error("Generate must be enabled for this function");
-
-   SrcList->ReadMainList();
+   pkgCacheFile CacheFile;
+   pkgSourceList *SrcList = CacheFile.GetSourceList();
 
-   pkgCache &Cache = *GCache;
+   if (SrcList == 0)
+      return false;
 
    // Create the src text record parsers and ignore errors about missing
    // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
@@ -1708,10 +1679,9 @@ bool Madison(CommandLine &CmdL)
    if (_error->PendingError() == true)
       _error->Discard();
 
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
    {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-
       if (Pkg.end() == false)
       {
          for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; V++)
@@ -1746,7 +1716,7 @@ bool Madison(CommandLine &CmdL)
       
       SrcRecs.Restart();
       pkgSrcRecords::Parser *SrcParser;
-      while ((SrcParser = SrcRecs.Find(*I,false)) != 0)
+      while ((SrcParser = SrcRecs.Find(Pkg.Name(),false)) != 0)
       {
          // Maybe support Release info here too eventually
          cout << setw(10) << SrcParser->Package() << " | "
@@ -1764,11 +1734,9 @@ bool Madison(CommandLine &CmdL)
 bool GenCaches(CommandLine &Cmd)
 {
    OpTextProgress Progress(*_config);
-   
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return false;   
-   return pkgMakeStatusCache(List,Progress);
+
+   pkgCacheFile CacheFile;
+   return CacheFile.BuildCaches(&Progress, true);
 }
                                                                        /*}}}*/
 // ShowHelp - Show a help screen                                       /*{{{*/
@@ -1846,6 +1814,8 @@ int main(int argc,const char *argv[])                                     /*{{{*/
       {'n',"names-only","APT::Cache::NamesOnly",0},
       {0,"all-names","APT::Cache::AllNames",0},
       {0,"recurse","APT::Cache::RecurseDepends",0},
+      {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
+      {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {0,"installed","APT::Cache::Installed",0},
@@ -1900,35 +1870,10 @@ int main(int argc,const char *argv[])                                   /*{{{*/
    if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
       _config->Set("quiet","1");
 
+//       if (_config->FindB("APT::Cache::Generate",true) == false)
    if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
-   { 
-      MMap *Map = 0;
-      if (_config->FindB("APT::Cache::Generate",true) == false)
-      {
-        Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
-                                   FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
-      }
-      else
-      {
-        // Open the cache file
-        SrcList = new pkgSourceList;
-        SrcList->ReadMainList();
+      CmdL.DispatchArg(CmdsB);
 
-        // Generate it and map it
-        OpProgress Prog;
-        pkgMakeStatusCache(*SrcList,Prog,&Map,true);
-      }
-      
-      if (_error->PendingError() == false)
-      {
-        pkgCache Cache(Map);   
-        GCache = &Cache;
-        if (_error->PendingError() == false)
-           CmdL.DispatchArg(CmdsB);
-      }
-      delete Map;
-   }
-   
    // Print any errors or warnings found during parsing
    if (_error->empty() == false)
    {
index 21ef1a0..07bc0c2 100644 (file)
@@ -296,8 +296,7 @@ bool Go(CommandLine &CmdL)
        MMap *Map = 0;
        pkgSourceList List;
        List.ReadMainList();
-       OpProgress Prog;
-       pkgMakeStatusCache(List,Prog,&Map,true);
+       pkgCacheGenerator::MakeStatusCache(List,NULL,&Map,true);
        if (Map == 0)
           return false;
        DebFile::Cache = new pkgCache(Map);
index 44235e3..2340a7e 100644 (file)
@@ -40,7 +40,8 @@
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
-    
+#include <apt-pkg/cacheset.h>
+
 #include <config.h>
 #include <apti18n.h>
 
@@ -90,14 +91,14 @@ class CacheFile : public pkgCacheFile
    bool BuildCaches(bool WithLock = true)
    {
       OpTextProgress Prog(*_config);
-      if (pkgCacheFile::BuildCaches(Prog,WithLock) == false)
+      if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false)
         return false;
       return true;
    }
    bool Open(bool WithLock = true) 
    {
       OpTextProgress Prog(*_config);
-      if (pkgCacheFile::Open(Prog,WithLock) == false)
+      if (pkgCacheFile::Open(&Prog,WithLock) == false)
         return false;
       Sort();
       
@@ -837,9 +838,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       return false;
 
    // Display statistics
-   double FetchBytes = Fetcher.FetchNeeded();
-   double FetchPBytes = Fetcher.PartialPresent();
-   double DebBytes = Fetcher.TotalNeeded();
+   unsigned long long FetchBytes = Fetcher.FetchNeeded();
+   unsigned long long FetchPBytes = Fetcher.PartialPresent();
+   unsigned long long DebBytes = Fetcher.TotalNeeded();
    if (DebBytes != Cache->DebSize())
    {
       c0out << DebBytes << ',' << Cache->DebSize() << endl;
@@ -1780,51 +1781,24 @@ bool DoInstall(CommandLine &CmdL)
         Packages++;
         if (Pkg.end() == true)
         {
-           // Check if the name is a regex
-           const char *I;
-           for (I = S; *I != 0; I++)
-              if (*I == '?' || *I == '*' || *I == '|' ||
-                  *I == '[' || *I == '^' || *I == '$')
-                 break;
-           if (*I == 0)
+           APT::PackageSet pkgset = APT::PackageSet::FromRegEx(Cache, S, c1out);
+           if (pkgset.empty() == true)
               return _error->Error(_("Couldn't find package %s"),S);
 
            // Regexs must always be confirmed
            ExpectedInst += 1000;
-        
-           // Compile the regex pattern
-           regex_t Pattern;
-           int Res;
-           if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
-                              REG_NOSUB)) != 0)
-           {
-              char Error[300];     
-              regerror(Res,&Pattern,Error,sizeof(Error));
-              return _error->Error(_("Regex compilation error - %s"),Error);
-           }
-        
-           // Run over the matches
+
            bool Hit = false;
-           for (pkgCache::GrpIterator Grp = Cache->GrpBegin(); Grp.end() == false; ++Grp)
+           for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
            {
-              if (regexec(&Pattern,Grp.Name(),0,0,0) != 0)
-                 continue;
-              Pkg = Grp.FindPkg("native");
-              if (unlikely(Pkg.end() == true))
-                 continue;
-
-              ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
-                       Pkg.Name(),S);
-           
               if (VerTag != 0)
                  if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
                     return false;
-           
+
               Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
                                   ExpectedInst,false);
            }
-           regfree(&Pattern);
-        
+
            if (Hit == false)
               return _error->Error(_("Couldn't find package %s"),S);
         }
@@ -2362,9 +2336,9 @@ bool DoSource(CommandLine &CmdL)
    }
    
    // Display statistics
-   double FetchBytes = Fetcher.FetchNeeded();
-   double FetchPBytes = Fetcher.PartialPresent();
-   double DebBytes = Fetcher.TotalNeeded();
+   unsigned long long FetchBytes = Fetcher.FetchNeeded();
+   unsigned long long FetchPBytes = Fetcher.PartialPresent();
+   unsigned long long DebBytes = Fetcher.TotalNeeded();
 
    // Check for enough free space
    struct statvfs Buf;
index c3f7a3e..56a17eb 100644 (file)
@@ -1,12 +1,58 @@
 apt (0.7.26~exp6) UNRELEASED; urgency=low
 
   [ David Kalnischkies ]
-  * doc/apt.conf.5.xml:
-    - document the new Valid-Until related options
-  * apt-pkg/indexrecords.cc:
+  * apt-pkg/deb/dpkgpm.cc:
+    - write Disappeared also to the history.log
+    - forward manual-installed bit on package disappearance
+  * apt-pkg/deb/debsystem.cc:
+    - add better config item for extended_states file
+  * apt-pkg/pkgcache.h:
+    - switch {,Install-}Size to unsigned long long
+  * apt-pkg/depcache.cc:
+    - do the autoremove mark process also for required packages to handle
+      these illegally depending on lower priority packages (Closes: #583517)
+    - try harder to find the other pseudo versions for autoremove multiarch
+    - correct "Dangerous iterator usage" pointed out by cppcheck
+    - deal with long long, not with int to remove 2GB Limit (LP: #250909)
+    - deprecate AddSize with Multiplier as it is unused and switch to
+      boolean instead to handle the sizes more gracefully.
+    - switch i{Download,Usr}Size from double to (un)signed long long
+  * apt-pkg/aptconfiguration.cc:
+    - remove duplicate architectures in getArchitectures()
+  * apt-pkg/indexrecords.{cc,h}:
     - backport forgotten Valid-Until patch from the obsolete experimental
       branch to prevent replay attacks better, thanks to Thomas Viehmann
       for the initial patch! (Closes: #499897)
+    - add a constant Exists check for MetaKeys
+  * apt-pkg/acquire-item.cc:
+    - do not try PDiff if it is not listed in the Meta file
+  * apt-pkg/cacheiterator.h:
+    - let pkgCache::Iterator inherent std::iterator
+  * ftparchive/writer.h:
+    - add a virtual destructor to FTWScanner class (for cppcheck)
+  * apt-pkg/cacheset.{cc,h}:
+    - add simple wrapper around std::set for cache structures
+    - move regex magic from apt-get to new FromRegEx method
+    - move cmdline parsing from apt-cache to new FromCommandLine method
+    - support special release-modifier 'installed' and 'candidate'
+  * apt-pkg/contrib/cmdline.cc:
+    - fix segfault in SaveInConfig caused by writing over char[] sizes
+  * apt-pkg/pkgcache.cc:
+    - get the best matching arch package from a group with FindPreferredPkg
+  * cmdline/apt-cache.cc:
+    - make the search multiarch compatible by using GrpIterator instead
+    - use pkgCacheFile and the new CacheSets all over the place
+    - add --target-release option (Closes: #115520)
+    - accept pkg/release and pkg=version in show and co. (Closes: #236270)
+    - accept package versions in the unmet command
+  * cmdline/apt-get.cc:
+    - use unsigned long long instead of double to store values it gets
+  * apt-pkg/cachefile.{cc,h}:
+    - split Open() into submethods to be able to build only parts
+    - make the OpProgress optional in the Cache buildprocess
+    - store also the SourceList we use internally for export
+  * doc/apt.conf.5.xml:
+    - document the new Valid-Until related options
   * apt-pkg/contrib/strutl.cc:
     - split StrToTime() into HTTP1.1 and FTP date parser methods and
       use strptime() instead of some self-made scanf mangling
@@ -15,7 +61,7 @@ apt (0.7.26~exp6) UNRELEASED; urgency=low
   * ftparchive/writer.cc:
     - add ValidTime option to generate a Valid-Until header in Release file
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Wed, 09 Jun 2010 10:43:58 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Wed, 09 Jun 2010 10:52:31 +0200
 
 apt (0.7.26~exp5) experimental; urgency=low
 
index 3f6cc78..8e07cd7 100644 (file)
 
  <refsect1><title>Files</title>
    <variablelist>
-      <varlistentry><term><filename>/var/lib/apt/extended_states</filename></term>
-      <listitem><para>Status list of auto-installed packages.
-                     Configuration Item: <literal>Dir::State</literal>
-                     sets the path to the <filename>extended_states</filename> file.
-      </para></listitem>
-      </varlistentry>
+       &file-extended_states;
    </variablelist>
  </refsect1>
 
index 494c6b0..0d037c8 100644 (file)
      </varlistentry>
 ">
 
+<!ENTITY file-extended_states "
+      <varlistentry><term><filename>/var/lib/apt/extended_states</filename></term>
+      <listitem><para>Status list of auto-installed packages.
+      Configuration Item: <literal>Dir::State::extended_states</literal>.
+      </para></listitem>
+      </varlistentry>
+">
+
 <!-- TRANSLATOR: This is the section header for the following paragraphs - comparable
      to the other headers like NAME and DESCRIPTION and should therefore be uppercase. -->
 <!ENTITY translation-title "TRANSLATION">
index 127feb9..fdec32c 100644 (file)
@@ -298,9 +298,8 @@ Dir "/"
   State "var/lib/apt/" 
   {
      Lists "lists/";
-     xstatus "xstatus";
-     userstatus "status.user";
      status "/var/lib/dpkg/status";
+     extended_states "extended_states";
      cdroms "cdroms.list";
   };
   
index 3123a7f..49d430c 100644 (file)
@@ -72,6 +72,7 @@ class FTWScanner
    bool SetExts(string const &Vals);
       
    FTWScanner(string const &Arch = string());
+   virtual ~FTWScanner() {};
 };
 
 class TranslationWriter
diff --git a/test/libapt/getarchitectures_test.cc b/test/libapt/getarchitectures_test.cc
new file mode 100644 (file)
index 0000000..1500cae
--- /dev/null
@@ -0,0 +1,61 @@
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/configuration.h>
+
+#include "assert.h"
+#include <string>
+#include <vector>
+
+#include <iostream>
+
+// simple helper to quickly output a vector of strings
+void dumpVector(std::vector<std::string> vec) {
+       for (std::vector<std::string>::const_iterator v = vec.begin();
+            v != vec.end(); v++)
+               std::cout << *v << std::endl;
+}
+
+int main(int argc,char *argv[])
+{
+       std::vector<std::string> vec;
+
+       _config->Set("APT::Architectures::1", "i386");
+       _config->Set("APT::Architectures::2", "amd64");
+       vec = APT::Configuration::getArchitectures(false);
+       equals(vec.size(), 2);
+       equals(vec[0], "i386");
+       equals(vec[1], "amd64");
+
+       _config->Set("APT::Architecture", "i386");
+       vec = APT::Configuration::getArchitectures(false);
+       equals(vec.size(), 2);
+       equals(vec[0], "i386");
+       equals(vec[1], "amd64");
+
+       _config->Set("APT::Architectures::2", "");
+       vec = APT::Configuration::getArchitectures(false);
+       equals(vec.size(), 1);
+       equals(vec[0], "i386");
+
+       _config->Set("APT::Architecture", "armel");
+       vec = APT::Configuration::getArchitectures(false);
+       equals(vec.size(), 2);
+       equals(vec[0], "i386");
+       equals(vec[1], "armel");
+
+       _config->Set("APT::Architectures::2", "amd64");
+       _config->Set("APT::Architectures::3", "i386");
+       _config->Set("APT::Architectures::4", "armel");
+       _config->Set("APT::Architectures::5", "i386");
+       _config->Set("APT::Architectures::6", "amd64");
+       _config->Set("APT::Architectures::7", "armel");
+       _config->Set("APT::Architectures::8", "armel");
+       _config->Set("APT::Architectures::9", "amd64");
+       _config->Set("APT::Architectures::10", "amd64");
+       vec = APT::Configuration::getArchitectures(false);
+       equals(vec.size(), 3);
+       equals(vec[0], "i386");
+       equals(vec[1], "amd64");
+       equals(vec[2], "armel");
+
+       return 0;
+}
index 98bdb33..ee3401b 100644 (file)
@@ -12,6 +12,11 @@ SLIBS = -lapt-pkg
 SOURCE = getlanguages_test.cc
 include $(PROGRAM_H)
 
+PROGRAM = getArchitectures${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = getarchitectures_test.cc
+include $(PROGRAM_H)
+
 # Program for testing ParseDepends
 PROGRAM = ParseDepends${BASENAME}
 SLIBS = -lapt-pkg
index f9df1af..cb7769e 100755 (executable)
@@ -2,6 +2,7 @@
 set -e
 
 echo "Compiling the tests ..."
+test -d '../../build/obj/test/libapt/' || mkdir -p '../../build/obj/test/libapt/'
 make
 echo "Running all testcases ..."
 LDPATH=$(pwd)/../../build/bin