Просмотр исходного кода

merged from lp:~donkult/apt/sid

Michael Vogt лет назад: 16
Родитель
Сommit
189bb640d2
52 измененных файлов с 1611 добавлено и 586 удалено
  1. 1 1
      apt-inst/deb/dpkgdb.cc
  2. 21 6
      apt-pkg/acquire-item.cc
  3. 2 2
      apt-pkg/acquire-item.h
  4. 1 1
      apt-pkg/acquire-method.cc
  5. 6 6
      apt-pkg/acquire.cc
  6. 3 3
      apt-pkg/acquire.h
  7. 14 1
      apt-pkg/aptconfiguration.cc
  8. 81 25
      apt-pkg/cachefile.cc
  9. 23 7
      apt-pkg/cachefile.h
  10. 11 4
      apt-pkg/cacheiterators.h
  11. 280 0
      apt-pkg/cacheset.cc
  12. 239 0
      apt-pkg/cacheset.h
  13. 2 2
      apt-pkg/contrib/cmndline.cc
  14. 52 20
      apt-pkg/contrib/strutl.cc
  15. 3 1
      apt-pkg/contrib/strutl.h
  16. 10 8
      apt-pkg/deb/debindexfile.cc
  17. 3 3
      apt-pkg/deb/debindexfile.h
  18. 2 3
      apt-pkg/deb/deblistparser.cc
  19. 1 1
      apt-pkg/deb/debsystem.cc
  20. 70 10
      apt-pkg/deb/dpkgpm.cc
  21. 16 1
      apt-pkg/deb/dpkgpm.h
  22. 90 21
      apt-pkg/depcache.cc
  23. 10 7
      apt-pkg/depcache.h
  24. 6 2
      apt-pkg/indexfile.h
  25. 47 3
      apt-pkg/indexrecords.cc
  26. 6 0
      apt-pkg/indexrecords.h
  27. 3 2
      apt-pkg/makefile
  28. 20 1
      apt-pkg/pkgcache.cc
  29. 2 2
      apt-pkg/pkgcache.h
  30. 28 17
      apt-pkg/pkgcachegen.cc
  31. 8 2
      apt-pkg/pkgcachegen.h
  32. 24 0
      apt-pkg/tagfile.cc
  33. 1 0
      apt-pkg/tagfile.h
  34. 309 364
      cmdline/apt-cache.cc
  35. 1 2
      cmdline/apt-extracttemplates.cc
  36. 16 42
      cmdline/apt-get.cc
  37. 63 2
      debian/changelog
  38. 2 1
      doc/apt-ftparchive.1.xml
  39. 1 6
      doc/apt-mark.8.xml
  40. 24 0
      doc/apt.conf.5.xml
  41. 8 0
      doc/apt.ent
  42. 5 2
      doc/examples/configure-index
  43. 10 0
      ftparchive/writer.cc
  44. 1 0
      ftparchive/writer.h
  45. 1 2
      methods/ftp.cc
  46. 1 1
      methods/http.cc
  47. 1 2
      methods/rsh.cc
  48. 61 0
      test/libapt/getarchitectures_test.cc
  49. 5 0
      test/libapt/makefile
  50. 1 0
      test/libapt/run-tests.sh
  51. 14 0
      test/pre-upload-check.py
  52. 1 0
      test/testsources.list/sources.list.all-validuntil-broken

+ 1 - 1
apt-inst/deb/dpkgdb.cc

@@ -142,7 +142,7 @@ bool debDpkgDB::ReadyPkgCache(OpProgress &Progress)
       CacheMap = 0;
       CacheMap = 0;
    }
    }
    
    
-   if (pkgMakeOnlyStatusCache(Progress,&CacheMap) == false)
+   if (pkgCacheGenerator::MakeOnlyStatusCache(&Progress,&CacheMap) == false)
       return false;
       return false;
    Cache->DropProgress();
    Cache->DropProgress();
    
    

+ 21 - 6
apt-pkg/acquire-item.cc

@@ -33,6 +33,7 @@
 #include <string>
 #include <string>
 #include <sstream>
 #include <sstream>
 #include <stdio.h>
 #include <stdio.h>
+#include <ctime>
 									/*}}}*/
 									/*}}}*/
 
 
 using namespace std;
 using namespace std;
@@ -1164,13 +1165,16 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
             return;
             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,
 	 new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
 			     (*Target)->ShortDesc, ExpectedIndexHash);
 			     (*Target)->ShortDesc, ExpectedIndexHash);
-      else 
+      else
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 			    (*Target)->ShortDesc, ExpectedIndexHash);
 			    (*Target)->ShortDesc, ExpectedIndexHash);
    }
    }
@@ -1236,6 +1240,17 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message)			/*{{{*/
       Transformed = "";
       Transformed = "";
    }
    }
 
 
+   if (_config->FindB("Acquire::Check-Valid-Until", true) == true &&
+       MetaIndexParser->GetValidUntil() > 0) {
+      time_t const invalid_since = time(NULL) - MetaIndexParser->GetValidUntil();
+      if (invalid_since > 0)
+	 // TRANSLATOR: The first %s is the URL of the bad Release file, the second is
+	 // the time since then the file is invalid - formated in the same way as in
+	 // the download progress display (e.g. 7d 3h 42min 1s)
+	 return _error->Error(_("Release file expired, ignoring %s (invalid since %s)"),
+	                      RealURI.c_str(), TimeToStr(invalid_since).c_str());
+   }
+
    if (_config->FindB("Debug::pkgAcquire::Auth", false)) 
    if (_config->FindB("Debug::pkgAcquire::Auth", false)) 
    {
    {
       std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl;
       std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl;
@@ -1253,7 +1268,7 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message)			/*{{{*/
 //       return false;
 //       return false;
       if (!Transformed.empty())
       if (!Transformed.empty())
       {
       {
-         _error->Warning("Conflicting distribution: %s (expected %s but got %s)",
+         _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
                          Desc.Description.c_str(),
                          Desc.Description.c_str(),
                          Transformed.c_str(),
                          Transformed.c_str(),
                          MetaIndexParser->GetDist().c_str());
                          MetaIndexParser->GetDist().c_str());

+ 2 - 2
apt-pkg/acquire-item.h

@@ -112,10 +112,10 @@ class pkgAcquire::Item : public WeakPointable
    string ErrorText;
    string ErrorText;
 
 
    /** \brief The size of the object to fetch. */
    /** \brief The size of the object to fetch. */
-   unsigned long FileSize;
+   unsigned long long FileSize;
 
 
    /** \brief How much of the object was already fetched. */
    /** \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
    /** \brief If not \b NULL, contains the name of a subprocess that
     *  is operating on this object (for instance, "gzip" or "gpgv").
     *  is operating on this object (for instance, "gzip" or "gpgv").

+ 1 - 1
apt-pkg/acquire-method.cc

@@ -378,7 +378,7 @@ int pkgAcqMethod::Run(bool Single)
 	    
 	    
 	    Tmp->Uri = LookupTag(Message,"URI");
 	    Tmp->Uri = LookupTag(Message,"URI");
 	    Tmp->DestFile = LookupTag(Message,"FileName");
 	    Tmp->DestFile = LookupTag(Message,"FileName");
-	    if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false)
+	    if (RFC1123StrToTime(LookupTag(Message,"Last-Modified").c_str(),Tmp->LastModified) == false)
 	       Tmp->LastModified = 0;
 	       Tmp->LastModified = 0;
 	    Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
 	    Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
 	    Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false);
 	    Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false);

+ 6 - 6
apt-pkg/acquire.cc

@@ -506,9 +506,9 @@ bool pkgAcquire::Clean(string Dir)
 // Acquire::TotalNeeded - Number of bytes to fetch			/*{{{*/
 // Acquire::TotalNeeded - Number of bytes to fetch			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is the total number of bytes needed */
 /* 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++)
    for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); I++)
       Total += (*I)->FileSize;
       Total += (*I)->FileSize;
    return Total;
    return Total;
@@ -517,9 +517,9 @@ double pkgAcquire::TotalNeeded()
 // Acquire::FetchNeeded - Number of bytes needed to get			/*{{{*/
 // Acquire::FetchNeeded - Number of bytes needed to get			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is the number of bytes that is not local */
 /* 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++)
    for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); I++)
       if ((*I)->Local == false)
       if ((*I)->Local == false)
 	 Total += (*I)->FileSize;
 	 Total += (*I)->FileSize;
@@ -529,9 +529,9 @@ double pkgAcquire::FetchNeeded()
 // Acquire::PartialPresent - Number of partial bytes we already have	/*{{{*/
 // Acquire::PartialPresent - Number of partial bytes we already have	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is the number of bytes that is not local */
 /* 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++)
    for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); I++)
       if ((*I)->Local == false)
       if ((*I)->Local == false)
 	 Total += (*I)->PartialSize;
 	 Total += (*I)->PartialSize;

+ 3 - 3
apt-pkg/acquire.h

@@ -323,17 +323,17 @@ class pkgAcquire
    /** \return the total size in bytes of all the items included in
    /** \return the total size in bytes of all the items included in
     *  this download.
     *  this download.
     */
     */
-   double TotalNeeded();
+   unsigned long long TotalNeeded();
 
 
    /** \return the size in bytes of all non-local items included in
    /** \return the size in bytes of all non-local items included in
     *  this download.
     *  this download.
     */
     */
-   double FetchNeeded();
+   unsigned long long FetchNeeded();
 
 
    /** \return the amount of data to be fetched that is already
    /** \return the amount of data to be fetched that is already
     *  present on the filesystem.
     *  present on the filesystem.
     */
     */
-   double PartialPresent();
+   unsigned long long PartialPresent();
 
 
    /** \brief Delayed constructor
    /** \brief Delayed constructor
     *
     *

+ 14 - 1
apt-pkg/aptconfiguration.cc

@@ -327,11 +327,24 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 	if (likely(Cached == true) && archs.empty() == false)
 	if (likely(Cached == true) && archs.empty() == false)
 		return archs;
 		return archs;
 
 
-	string const arch = _config->Find("APT::Architecture");
 	archs = _config->FindVector("APT::Architectures");
 	archs = _config->FindVector("APT::Architectures");
+	string const arch = _config->Find("APT::Architecture");
+	if (unlikely(arch.empty() == true))
+		return archs;
+
 	if (archs.empty() == true ||
 	if (archs.empty() == true ||
 	    std::find(archs.begin(), archs.end(), arch) == archs.end())
 	    std::find(archs.begin(), archs.end(), arch) == archs.end())
 		archs.push_back(arch);
 		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;
 	return archs;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 81 - 25
apt-pkg/cachefile.cc

@@ -27,7 +27,8 @@
 // CacheFile::CacheFile - Constructor					/*{{{*/
 // 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 DCache;
    delete Policy;
    delete Policy;
+   delete SrcList;
    delete Cache;
    delete Cache;
    delete Map;
    delete Map;
    _system->UnLock(true);
    _system->UnLock(true);
-}   
+}
 									/*}}}*/
 									/*}}}*/
 // CacheFile::BuildCaches - Open and build the cache files		/*{{{*/
 // 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();
    const bool ErrorWasEmpty = _error->empty();
    if (WithLock == true)
    if (WithLock == true)
       if (_system->Lock() == false)
       if (_system->Lock() == false)
@@ -58,15 +73,13 @@ bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
       
       
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       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
    // 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)
    if (Res == false)
       return _error->Error(_("The package lists or status file could not be parsed or opened."));
       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;
    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);
    Policy = new pkgPolicy(Cache);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       return false;
 
 
    if (ReadPinFile(*Policy) == false || ReadPinDir(*Policy) == false)
    if (ReadPinFile(*Policy) == false || ReadPinDir(*Policy) == false)
       return 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);
    DCache = new pkgDepCache(Cache,Policy);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       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)
    if (_error->PendingError() == true)
       return false;
       return false;
    
    
@@ -117,12 +171,14 @@ void pkgCacheFile::Close()
    delete DCache;
    delete DCache;
    delete Policy;
    delete Policy;
    delete Cache;
    delete Cache;
+   delete SrcList;
    delete Map;
    delete Map;
    _system->UnLock(true);
    _system->UnLock(true);
 
 
-   Map = 0;
-   DCache = 0;
-   Policy = 0;
-   Cache = 0;
+   Map = NULL;
+   DCache = NULL;
+   Policy = NULL;
+   Cache = NULL;
+   SrcList = NULL;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 23 - 7
apt-pkg/cachefile.h

@@ -23,6 +23,7 @@
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sourcelist.h>
 
 
 class pkgPolicy;
 class pkgPolicy;
+class pkgSourceList;
 class pkgCacheFile
 class pkgCacheFile
 {
 {
    protected:
    protected:
@@ -30,27 +31,42 @@ class pkgCacheFile
    MMap *Map;
    MMap *Map;
    pkgCache *Cache;
    pkgCache *Cache;
    pkgDepCache *DCache;
    pkgDepCache *DCache;
-   
+   pkgPolicy *Policy;
+   pkgSourceList *SrcList;
+
    public:
    public:
 
 
-   pkgPolicy *Policy;
-      
    // We look pretty much exactly like a pointer to a dep cache
    // We look pretty much exactly like a pointer to a dep cache
    inline operator pkgCache &() {return *Cache;};
    inline operator pkgCache &() {return *Cache;};
    inline operator pkgCache *() {return Cache;};
    inline operator pkgCache *() {return Cache;};
    inline operator pkgDepCache &() {return *DCache;};
    inline operator pkgDepCache &() {return *DCache;};
    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 &operator *() {return *DCache;};
    inline pkgDepCache &operator *() {return *DCache;};
    inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*DCache)[I];};
    inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*DCache)[I];};
    inline unsigned char &operator [](pkgCache::DepIterator 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();
    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();
-   ~pkgCacheFile();
+   virtual ~pkgCacheFile();
 };
 };
 
 
 #endif
 #endif

+ 11 - 4
apt-pkg/cacheiterators.h

@@ -29,10 +29,12 @@
 									/*}}}*/
 									/*}}}*/
 #ifndef PKGLIB_CACHEITERATORS_H
 #ifndef PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
+#include<iterator>
 // abstract Iterator template						/*{{{*/
 // abstract Iterator template						/*{{{*/
 /* This template provides the very basic iterator methods we
 /* This template provides the very basic iterator methods we
    need to have for doing some walk-over-the-cache magic */
    need to have for doing some walk-over-the-cache magic */
-template<typename Str, typename Itr> class pkgCache::Iterator {
+template<typename Str, typename Itr> class pkgCache::Iterator :
+			public std::iterator<std::forward_iterator_tag, Str> {
 	protected:
 	protected:
 	Str *S;
 	Str *S;
 	pkgCache *Owner;
 	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 operator Str const *() const {return S == OwnerPointer() ? 0 : S;};
 	inline Str &operator *() {return *S;};
 	inline Str &operator *() {return *S;};
 	inline Str const &operator *() const {return *S;};
 	inline Str const &operator *() const {return *S;};
-	inline pkgCache *Cache() {return Owner;};
+	inline pkgCache *Cache() const {return Owner;};
 
 
 	// Mixed stuff
 	// Mixed stuff
 	inline void operator =(const Itr &B) {S = B.S; Owner = B.Owner;};
 	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 const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
 	inline PkgIterator PackageList() const;
 	inline PkgIterator PackageList() const;
 	PkgIterator FindPkg(string Arch = "any");
 	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);
 	PkgIterator NextPkg(PkgIterator const &Pkg);
 
 
 	// Constructors
 	// Constructors
@@ -198,8 +205,8 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 	inline PrvIterator ProvidesList() const;
 	inline PrvIterator ProvidesList() const;
 	inline VerFileIterator FileList() const;
 	inline VerFileIterator FileList() const;
 	bool Downloadable() 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 Automatic() const;
 	bool Pseudo() const;
 	bool Pseudo() const;

+ 280 - 0
apt-pkg/cacheset.cc

@@ -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();
+}
+									/*}}}*/
+}

+ 239 - 0
apt-pkg/cacheset.h

@@ -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

+ 2 - 2
apt-pkg/contrib/cmndline.cc

@@ -360,11 +360,11 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch)
    than nothing after all. */
    than nothing after all. */
 void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv)
 void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv)
 {
 {
-   char cmdline[300];
+   char cmdline[100 + argc * 50];
    unsigned int length = 0;
    unsigned int length = 0;
    bool lastWasOption = false;
    bool lastWasOption = false;
    bool closeQuote = 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)
       for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length)
       {
       {

+ 52 - 20
apt-pkg/contrib/strutl.cc

@@ -827,34 +827,66 @@ static int MonthConv(char *Month)
    }   
    }   
 }
 }
 									/*}}}*/
 									/*}}}*/
-// timegm - Internal timegm function if gnu is not available		/*{{{*/
+// timegm - Internal timegm if the gnu version is not available		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Ripped this evil little function from wget - I prefer the use of 
-   GNU timegm if possible as this technique will have interesting problems
-   with leap seconds, timezones and other.
-   
-   Converts struct tm to time_t, assuming the data in tm is UTC rather
+/* Converts struct tm to time_t, assuming the data in tm is UTC rather
    than local timezone (mktime assumes the latter).
    than local timezone (mktime assumes the latter).
-   
-   Contributed by Roger Beeman <beeman@cisco.com>, with the help of
-   Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO. */
-
-/* Turned it into an autoconf check, because GNU is not the only thing which
-   can provide timegm. -- 2002-09-22, Joel Baker */
 
 
-#ifndef HAVE_TIMEGM // Now with autoconf!
+   This function is a nonstandard GNU extension that is also present on
+   the BSDs and maybe other systems. For others we follow the advice of
+   the manpage of timegm and use his portable replacement. */
+#ifndef HAVE_TIMEGM
 static time_t timegm(struct tm *t)
 static time_t timegm(struct tm *t)
 {
 {
-   time_t tl, tb;
-   
-   tl = mktime (t);
-   if (tl == -1)
-      return -1;
-   tb = mktime (gmtime (&tl));
-   return (tl <= tb ? (tl + (tl - tb)) : (tl - (tb - tl)));
+   char *tz = getenv("TZ");
+   setenv("TZ", "", 1);
+   tzset();
+   time_t ret = mktime(t);
+   if (tz)
+      setenv("TZ", tz, 1);
+   else
+      unsetenv("TZ");
+   tzset();
+   return ret;
 }
 }
 #endif
 #endif
 									/*}}}*/
 									/*}}}*/
+// FullDateToTime - Converts a HTTP1.1 full date strings into a time_t	/*{{{*/
+// ---------------------------------------------------------------------
+/* tries to parses a full date as specified in RFC2616 Section 3.3.1
+   with one exception: All timezones (%Z) are accepted but the protocol
+   says that it MUST be GMT, but this one is equal to UTC which we will
+   encounter from time to time (e.g. in Release files) so we accept all
+   here and just assume it is GMT (or UTC) later on */
+bool RFC1123StrToTime(const char* const str,time_t &time)
+{
+   struct tm Tm;
+   // Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
+   if (strptime(str, "%a, %d %b %Y %H:%M:%S %Z", &Tm) == NULL &&
+   // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+       strptime(str, "%A, %d-%b-%y %H:%M:%S %Z", &Tm) == NULL &&
+   // Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
+       strptime(str, "%a %b %d %H:%M:%S %Y", &Tm) == NULL)
+      return false;
+
+   time = timegm(&Tm);
+   return true;
+}
+									/*}}}*/
+// FTPMDTMStrToTime - Converts a ftp modification date into a time_t	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool FTPMDTMStrToTime(const char* const str,time_t &time)
+{
+   struct tm Tm;
+   // MDTM includes no whitespaces but recommend and ignored by strptime
+   if (strptime(str, "%Y %m %d %H %M %S", &Tm) == NULL)
+      return false;
+
+   time = timegm(&Tm);
+   return true;
+}
+									/*}}}*/
 // StrToTime - Converts a string into a time_t				/*{{{*/
 // StrToTime - Converts a string into a time_t				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This handles all 3 populare time formats including RFC 1123, RFC 1036
 /* This handles all 3 populare time formats including RFC 1123, RFC 1036

+ 3 - 1
apt-pkg/contrib/strutl.h

@@ -45,7 +45,9 @@ string Base64Encode(const string &Str);
 string OutputInDepth(const unsigned long Depth, const char* Separator="  ");
 string OutputInDepth(const unsigned long Depth, const char* Separator="  ");
 string URItoFileName(const string &URI);
 string URItoFileName(const string &URI);
 string TimeRFC1123(time_t Date);
 string TimeRFC1123(time_t Date);
-bool StrToTime(const string &Val,time_t &Result);
+bool RFC1123StrToTime(const char* const str,time_t &time) __must_check;
+bool FTPMDTMStrToTime(const char* const str,time_t &time) __must_check;
+__deprecated bool StrToTime(const string &Val,time_t &Result);
 string LookupTag(const string &Message,const char *Tag,const char *Default = 0);
 string LookupTag(const string &Message,const char *Tag,const char *Default = 0);
 int StringToBool(const string &Text,int Default = -1);
 int StringToBool(const string &Text,int Default = -1);
 bool ReadMessages(int Fd, vector<string> &List);
 bool ReadMessages(int Fd, vector<string> &List);

+ 10 - 8
apt-pkg/deb/debindexfile.cc

@@ -262,15 +262,15 @@ unsigned long debPackagesIndex::Size() const
 // PackagesIndex::Merge - Load the index file into a cache		/*{{{*/
 // 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");
    string PackageFile = IndexFile("Packages");
    FileFd Pkg(PackageFile,FileFd::ReadOnly);
    FileFd Pkg(PackageFile,FileFd::ReadOnly);
    debListParser Parser(&Pkg, Architecture);
    debListParser Parser(&Pkg, Architecture);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return _error->Error("Problem opening %s",PackageFile.c_str());
       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);
    ::URI Tmp(URI);
    if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
    if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
       return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
       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		/*{{{*/
 // 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
    // Check the translation file, if in use
    string TranslationFile = IndexFile(Language);
    string TranslationFile = IndexFile(Language);
@@ -456,7 +456,8 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
      if (_error->PendingError() == true)
      if (_error->PendingError() == true)
        return false;
        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)
      if (Gen.SelectFile(TranslationFile,string(),*this) == false)
        return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
        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		/*{{{*/
 // 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);
    FileFd Pkg(File,FileFd::ReadOnly);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
@@ -537,8 +538,9 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
    debListParser Parser(&Pkg);
    debListParser Parser(&Pkg);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       return false;
-   
-   Prog.SubProgress(0,File);
+
+   if (Prog != NULL)
+      Prog->SubProgress(0,File);
    if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
    if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
       return _error->Error("Problem with SelectFile %s",File.c_str());
       return _error->Error("Problem with SelectFile %s",File.c_str());
 
 

+ 3 - 3
apt-pkg/deb/debindexfile.h

@@ -35,7 +35,7 @@ class debStatusIndex : public pkgIndexFile
    virtual bool Exists() const;
    virtual bool Exists() const;
    virtual bool HasPackages() const {return true;};
    virtual bool HasPackages() const {return true;};
    virtual unsigned long Size() 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;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
 
    debStatusIndex(string File);
    debStatusIndex(string File);
@@ -67,7 +67,7 @@ class debPackagesIndex : public pkgIndexFile
    virtual bool Exists() const;
    virtual bool Exists() const;
    virtual bool HasPackages() const {return true;};
    virtual bool HasPackages() const {return true;};
    virtual unsigned long Size() 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;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
 
    debPackagesIndex(string const &URI, string const &Dist, string const &Section,
    debPackagesIndex(string const &URI, string const &Dist, string const &Section,
@@ -99,7 +99,7 @@ class debTranslationsIndex : public pkgIndexFile
    virtual bool Exists() const;
    virtual bool Exists() const;
    virtual bool HasPackages() const;
    virtual bool HasPackages() const;
    virtual unsigned long Size() 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;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
 
    debTranslationsIndex(string URI,string Dist,string Section, char const * const Language);
    debTranslationsIndex(string URI,string Dist,string Section, char const * const Language);

+ 2 - 3
apt-pkg/deb/deblistparser.cc

@@ -133,10 +133,9 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
    }
    }
 
 
    // Archive Size
    // Archive Size
-   Ver->Size = (unsigned)Section.FindI("Size");
-   
+   Ver->Size = Section.FindULL("Size");
    // Unpacked Size (in K)
    // Unpacked Size (in K)
-   Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
+   Ver->InstalledSize = Section.FindULL("Installed-Size");
    Ver->InstalledSize *= 1024;
    Ver->InstalledSize *= 1024;
 
 
    // Priority
    // Priority

+ 1 - 1
apt-pkg/deb/debsystem.cc

@@ -164,7 +164,7 @@ bool debSystem::Initialize(Configuration &Cnf)
    /* These really should be jammed into a generic 'Local Database' engine
    /* These really should be jammed into a generic 'Local Database' engine
       which is yet to be determined. The functions in pkgcachegen should
       which is yet to be determined. The functions in pkgcachegen should
       be the only users of these */
       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::State::status","/var/lib/dpkg/status");
    Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg");
    Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg");
 
 

+ 70 - 10
apt-pkg/deb/dpkgpm.cc

@@ -472,7 +472,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 	 std::clog << "send: '" << status.str() << "'" << endl;
 	 std::clog << "send: '" << status.str() << "'" << endl;
 
 
       if (strncmp(action, "disappear", strlen("disappear")) == 0)
       if (strncmp(action, "disappear", strlen("disappear")) == 0)
-	 disappearedPkgs.insert(string(pkg_or_trigger));
+	 handleDisappearAction(pkg_or_trigger);
       return;
       return;
    }
    }
 
 
@@ -542,6 +542,51 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 		<< " action: " << action << endl;
 		<< " 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						/*{{{*/
 // DPkgPM::DoDpkgStatusFd						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /*
 /*
@@ -580,15 +625,15 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
 }
 }
 									/*}}}*/
 									/*}}}*/
 // DPkgPM::WriteHistoryTag						/*{{{*/
 // 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							/*{{{*/
 // DPkgPM::OpenLog							/*{{{*/
 bool pkgDPkgPM::OpenLog()
 bool pkgDPkgPM::OpenLog()
@@ -675,7 +720,22 @@ bool pkgDPkgPM::CloseLog()
 
 
    if(history_out)
    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, "Error: %s\n", dpkg_error.c_str());
       fprintf(history_out, "End-Date: %s\n", timestr);
       fprintf(history_out, "End-Date: %s\n", timestr);
       fclose(history_out);
       fclose(history_out);

+ 16 - 1
apt-pkg/deb/dpkgpm.h

@@ -32,6 +32,21 @@ class pkgDPkgPM : public pkgPackageManager
    FILE *history_out;
    FILE *history_out;
    string dpkg_error;
    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:
    protected:
    int pkgFailures;
    int pkgFailures;
 
 
@@ -70,7 +85,7 @@ class pkgDPkgPM : public pkgPackageManager
    // Helpers
    // Helpers
    bool RunScriptsWithPkgs(const char *Cnf);
    bool RunScriptsWithPkgs(const char *Cnf);
    bool SendV2Pkgs(FILE *F);
    bool SendV2Pkgs(FILE *F);
-   void WriteHistoryTag(string tag, string value);
+   void WriteHistoryTag(string const &tag, string value);
 
 
    // apport integration
    // apport integration
    void WriteApportReport(const char *pkgpath, const char *errormsg);
    void WriteApportReport(const char *pkgpath, const char *errormsg);

+ 90 - 21
apt-pkg/depcache.cc

@@ -165,7 +165,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
 bool pkgDepCache::readStateFile(OpProgress *Prog)			/*{{{*/
 bool pkgDepCache::readStateFile(OpProgress *Prog)			/*{{{*/
 {
 {
    FileFd state_file;
    FileFd state_file;
-   string const state = _config->FindDir("Dir::State") + "extended_states";
+   string const state = _config->FindFile("Dir::State::extended_states");
    if(FileExists(state)) {
    if(FileExists(state)) {
       state_file.Open(state, FileFd::ReadOnly);
       state_file.Open(state, FileFd::ReadOnly);
       int const file_size = state_file.Size();
       int const file_size = state_file.Size();
@@ -222,7 +222,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)	/*{{{*/
       std::clog << "pkgDepCache::writeStateFile()" << std::endl;
       std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 
 
    FileFd StateFile;
    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 it does not exist, create a empty one
    if(!FileExists(state)) 
    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		/*{{{*/
 // 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];
    StateCache &P = PkgState[Pkg->ID];
    
    
@@ -422,8 +425,8 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
    // Compute the size data
    // Compute the size data
    if (P.NewInstall() == true)
    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;
       return;
    }
    }
    
    
@@ -432,9 +435,9 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
        (P.InstallVer != (Version *)Pkg.CurrentVer() || 
        (P.InstallVer != (Version *)Pkg.CurrentVer() || 
 	(P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
 	(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;
       return;
    }
    }
    
    
@@ -442,14 +445,80 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
    if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
    if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
        P.Delete() == false)
        P.Delete() == false)
    {
    {
-      iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
+      iDownloadSize += (signed long long)(Mult*P.InstVerIter(*this)->Size);
       return;
       return;
    }
    }
    
    
    // Removing
    // Removing
    if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
    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;
       return;
    }   
    }   
 }
 }
@@ -806,7 +875,7 @@ void pkgDepCache::Update(OpProgress *Prog)
 		a bit we increase with a kill, but we should do something more clever… */
 		a bit we increase with a kill, but we should do something more clever… */
       while(recheck.empty() == false)
       while(recheck.empty() == false)
 	 for (std::set<unsigned long>::const_iterator p = recheck.begin();
 	 for (std::set<unsigned long>::const_iterator p = recheck.begin();
-	     p != recheck.end(); ++p) {
+	     p != recheck.end();) {
 	    if (Prog != 0 && Done%20 == 0)
 	    if (Prog != 0 && Done%20 == 0)
 	       Prog->Progress(Done);
 	       Prog->Progress(Done);
 	    PkgIterator P = PkgIterator(*Cache, Cache->PkgP + *p);
 	    PkgIterator P = PkgIterator(*Cache, Cache->PkgP + *p);
@@ -814,7 +883,7 @@ void pkgDepCache::Update(OpProgress *Prog)
 	       ++killed;
 	       ++killed;
 	       ++Done;
 	       ++Done;
 	    }
 	    }
-	    recheck.erase(p);
+	    recheck.erase(p++);
 	 }
 	 }
 
 
       /* Okay, we have killed a great amount of pseudopackages -
       /* Okay, we have killed a great amount of pseudopackages -
@@ -849,7 +918,7 @@ void pkgDepCache::Update(OpProgress *Prog)
 	 unsigned long const G = *g;
 	 unsigned long const G = *g;
 	 recheck.erase(g);
 	 recheck.erase(g);
 	 if (unlikely(ReInstallPseudoForGroup(G, recheck) == false))
 	 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) ||
       if(!(PkgState[p->ID].Flags & Flag::Auto) ||
 	  (p->Flags & Flag::Essential) ||
 	  (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)
 	 // the package is installed (and set to keep)
 	 if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
 	 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
    // If the version belongs to a Multi-Arch all package
    // we will mark all others in this Group with this version also
    // 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 &&
    if (ver->MultiArch == pkgCache::Version::All &&
 	strcmp(ver.Arch(true), "all") == 0)
 	strcmp(ver.Arch(true), "all") == 0)
    {
    {
@@ -1731,7 +1799,8 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 	 for (VerIterator V = P.VersionList();
 	 for (VerIterator V = P.VersionList();
 	      V.end() != true; ++V)
 	      V.end() != true; ++V)
 	 {
 	 {
-	    if (strcmp(VerStr, V.VerStr()) != 0)
+	    if (ver->Hash != V->Hash ||
+		strcmp(VerStr, V.VerStr()) != 0)
 	       continue;
 	       continue;
 	    MarkPackage(P, V, follow_recommends, follow_suggests);
 	    MarkPackage(P, V, follow_recommends, follow_suggests);
 	    break;
 	    break;

+ 10 - 7
apt-pkg/depcache.h

@@ -286,9 +286,11 @@ class pkgDepCache : protected pkgCache::Namespace
    pkgCache *Cache;
    pkgCache *Cache;
    StateCache *PkgState;
    StateCache *PkgState;
    unsigned char *DepState;
    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 iInstCount;
    unsigned long iDelCount;
    unsigned long iDelCount;
    unsigned long iKeepCount;
    unsigned long iKeepCount;
@@ -321,8 +323,9 @@ class pkgDepCache : protected pkgCache::Namespace
    void Update(PkgIterator const &P);
    void Update(PkgIterator const &P);
    
    
    // Count manipulators
    // 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);
    void AddStates(const PkgIterator &Pkg,int Add = 1);
    inline void RemoveStates(const PkgIterator &Pkg) {AddStates(Pkg,-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);
    bool writeStateFile(OpProgress *prog, bool InstalledOnly=true);
    
    
    // Size queries
    // 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 DelCount() {return iDelCount;};
    inline unsigned long KeepCount() {return iKeepCount;};
    inline unsigned long KeepCount() {return iKeepCount;};
    inline unsigned long InstCount() {return iInstCount;};
    inline unsigned long InstCount() {return iInstCount;};

+ 6 - 2
apt-pkg/indexfile.h

@@ -74,8 +74,12 @@ class pkgIndexFile
    virtual bool Exists() const = 0;
    virtual bool Exists() const = 0;
    virtual bool HasPackages() const = 0;
    virtual bool HasPackages() const = 0;
    virtual unsigned long Size() 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;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
 
    static bool TranslationsAvailable();
    static bool TranslationsAvailable();

+ 47 - 3
apt-pkg/indexrecords.cc

@@ -7,8 +7,11 @@
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/configuration.h>
 #include <apti18n.h>
 #include <apti18n.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
+#include <clocale>
+
 									/*}}}*/
 									/*}}}*/
 string indexRecords::GetDist() const
 string indexRecords::GetDist() const
 {
 {
@@ -26,11 +29,21 @@ string indexRecords::GetExpectedDist() const
    return this->ExpectedDist;
    return this->ExpectedDist;
 }
 }
 
 
+time_t indexRecords::GetValidUntil() const
+{
+   return this->ValidUntil;
+}
+
 const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 {
 {
    return Entries[MetaKey];
    return Entries[MetaKey];
 }
 }
 
 
+bool indexRecords::Exists(string const &MetaKey) const
+{
+   return Entries.count(MetaKey) == 1;
+}
+
 bool indexRecords::Load(const string Filename)				/*{{{*/
 bool indexRecords::Load(const string Filename)				/*{{{*/
 {
 {
    FileFd Fd(Filename, FileFd::ReadOnly);
    FileFd Fd(Filename, FileFd::ReadOnly);
@@ -80,9 +93,40 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
    {
    {
       strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
       strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
       return false;
       return false;
-   }  
+   }
+
+   string Label = Section.FindS("Label");
+   string StrDate = Section.FindS("Date");
+   string StrValidUntil = Section.FindS("Valid-Until");
+
+   // if we have a Valid-Until header in the Release file, use it as default
+   if (StrValidUntil.empty() == false)
+   {
+      if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false)
+      {
+	 strprintf(ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str());
+	 return false;
+      }
+   }
+   // get the user settings for this archive and use what expires earlier
+   int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0);
+   if (Label.empty() == true)
+      MaxAge = _config->FindI(string("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge);
+
+   if(MaxAge == 0) // No user settings, use the one from the Release file
+      return true;
+
+   time_t date;
+   if (RFC1123StrToTime(StrDate.c_str(), date) == false)
+   {
+      strprintf(ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str());
+      return false;
+   }
+   date += 24*60*60*MaxAge;
+
+   if (ValidUntil == 0 || ValidUntil > date)
+      ValidUntil = date;
 
 
-   string Strdate = Section.FindS("Date"); // FIXME: verify this somehow?
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -160,6 +204,6 @@ indexRecords::indexRecords()
 }
 }
 
 
 indexRecords::indexRecords(const string ExpectedDist) :
 indexRecords::indexRecords(const string ExpectedDist) :
-   ExpectedDist(ExpectedDist)
+   ExpectedDist(ExpectedDist), ValidUntil(0)
 {
 {
 }
 }

+ 6 - 0
apt-pkg/indexrecords.h

@@ -12,6 +12,7 @@
 
 
 #include <map>
 #include <map>
 #include <vector>
 #include <vector>
+#include <ctime>
 
 
 class indexRecords
 class indexRecords
 {
 {
@@ -25,6 +26,8 @@ class indexRecords
    string Dist;
    string Dist;
    string Suite;
    string Suite;
    string ExpectedDist;
    string ExpectedDist;
+   time_t ValidUntil;
+
    std::map<string,checkSum *> Entries;
    std::map<string,checkSum *> Entries;
 
 
    public:
    public:
@@ -34,10 +37,13 @@ class indexRecords
 
 
    // Lookup function
    // Lookup function
    virtual const checkSum *Lookup(const string MetaKey);
    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();
    std::vector<std::string> MetaKeys();
 
 
    virtual bool Load(string Filename);
    virtual bool Load(string Filename);
    string GetDist() const;
    string GetDist() const;
+   time_t GetValidUntil() const;
    virtual bool CheckDist(const string MaybeDist) const;
    virtual bool CheckDist(const string MaybeDist) const;
    string GetExpectedDist() const;
    string GetExpectedDist() const;
    virtual ~indexRecords(){};
    virtual ~indexRecords(){};

+ 3 - 2
apt-pkg/makefile

@@ -35,14 +35,15 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
 	 srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
 	 srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
 	 pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
 	 pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
 	 indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.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 \
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
 	  orderlist.h sourcelist.h packagemanager.h tagfile.h \
 	  orderlist.h sourcelist.h packagemanager.h tagfile.h \
 	  init.h pkgcache.h version.h progress.h pkgrecords.h \
 	  init.h pkgcache.h version.h progress.h pkgrecords.h \
 	  acquire.h acquire-worker.h acquire-item.h acquire-method.h \
 	  acquire.h acquire-worker.h acquire-item.h acquire-method.h \
 	  clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
 	  clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
 	  pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.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
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..
 # In theory the deb headers do not need to be exported..

+ 20 - 1
apt-pkg/pkgcache.cc

@@ -340,6 +340,25 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
 			break;
 			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);
 	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 
 /* This describes the version from a release-centric manner. The output is a 
    list of Label:Version/Archive */
    list of Label:Version/Archive */
-string pkgCache::VerIterator::RelStr()
+string pkgCache::VerIterator::RelStr() const
 {
 {
    bool First = true;
    bool First = true;
    string Res;
    string Res;

+ 2 - 2
apt-pkg/pkgcache.h

@@ -532,9 +532,9 @@ struct pkgCache::Version
    /** \brief archive size for this version
    /** \brief archive size for this version
 
 
        For Debian this is the size of the .deb file. */
        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 */
    /** \brief uncompressed size for this version */
-   map_ptrloc InstalledSize;
+   unsigned long long InstalledSize;
    /** \brief characteristic value representing this version
    /** \brief characteristic value representing this version
 
 
        No two packages in existence should have the same VerStr
        No two packages in existence should have the same VerStr

+ 28 - 17
apt-pkg/pkgcachegen.cc

@@ -526,7 +526,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
 // CacheGenerator::FinishCache - do various finish operations		/*{{{*/
 // CacheGenerator::FinishCache - do various finish operations		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This prepares the Cache for delivery */
 /* This prepares the Cache for delivery */
-bool pkgCacheGenerator::FinishCache(OpProgress &Progress)
+bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
 {
 {
    // FIXME: add progress reporting for this operation
    // FIXME: add progress reporting for this operation
    // Do we have different architectures in your groups ?
    // 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,
 static bool BuildCache(pkgCacheGenerator &Gen,
-		       OpProgress &Progress,
+		       OpProgress *Progress,
 		       unsigned long &CurrentSize,unsigned long TotalSize,
 		       unsigned long &CurrentSize,unsigned long TotalSize,
 		       FileIterator Start, FileIterator End)
 		       FileIterator Start, FileIterator End)
 {
 {
@@ -944,7 +944,8 @@ static bool BuildCache(pkgCacheGenerator &Gen,
       }
       }
       
       
       unsigned long Size = (*I)->Size();
       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;
       CurrentSize += Size;
       
       
       if ((*I)->Merge(Gen,Progress) == false)
       if ((*I)->Merge(Gen,Progress) == false)
@@ -953,13 +954,15 @@ static bool BuildCache(pkgCacheGenerator &Gen,
 
 
    if (Gen.HasFileDeps() == true)
    if (Gen.HasFileDeps() == true)
    {
    {
-      Progress.Done();
+      if (Progress != NULL)
+	 Progress->Done();
       TotalSize = ComputeSize(Start, End);
       TotalSize = ComputeSize(Start, End);
       CurrentSize = 0;
       CurrentSize = 0;
       for (I = Start; I != End; I++)
       for (I = Start; I != End; I++)
       {
       {
 	 unsigned long Size = (*I)->Size();
 	 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;
 	 CurrentSize += Size;
 	 if ((*I)->MergeFileProvides(Gen,Progress) == false)
 	 if ((*I)->MergeFileProvides(Gen,Progress) == false)
 	    return false;
 	    return false;
@@ -969,7 +972,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
    return true;
    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 
 /* This makes sure that the status cache (the cache that has all 
    index files from the sources list and all local ones) is ready
    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
    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
    are using AllowMem. AllowMem lets the function be run as non-root
    where it builds the cache 'fast' into a memory buffer. */
    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)
 			MMap **OutMap,bool AllowMem)
 {
 {
    bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
    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)
    if (Writeable == false && AllowMem == false && CacheFile.empty() == false)
       return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str());
       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.
    // Cache is OK, Fin.
    if (CheckValidity(CacheFile,Files.begin(),Files.end(),OutMap) == true)
    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)
       if (Debug == true)
 	 std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
 	 std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
       return true;
       return true;
@@ -1084,7 +1092,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
       TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
       TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
 
 
       // Build the status cache
       // Build the status cache
-      pkgCacheGenerator Gen(Map.Get(),&Progress);
+      pkgCacheGenerator Gen(Map.Get(),Progress);
       if (_error->PendingError() == true)
       if (_error->PendingError() == true)
 	 return false;
 	 return false;
       if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
       if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
@@ -1101,7 +1109,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
       TotalSize = ComputeSize(Files.begin(),Files.end());
       TotalSize = ComputeSize(Files.begin(),Files.end());
       
       
       // Build the source cache
       // Build the source cache
-      pkgCacheGenerator Gen(Map.Get(),&Progress);
+      pkgCacheGenerator Gen(Map.Get(),Progress);
       if (_error->PendingError() == true)
       if (_error->PendingError() == true)
 	 return false;
 	 return false;
       if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
       if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
@@ -1160,10 +1168,12 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
    return true;
    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);
    unsigned long MapSize = _config->FindI("APT::Cache-Limit",20*1024*1024);
    vector<pkgIndexFile *> Files;
    vector<pkgIndexFile *> Files;
@@ -1178,8 +1188,9 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
    TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
    TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
    
    
    // Build the status cache
    // 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)
    if (_error->PendingError() == true)
       return false;
       return false;
    if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
    if (BuildCache(Gen,Progress,CurrentSize,TotalSize,

+ 8 - 2
apt-pkg/pkgcachegen.h

@@ -76,7 +76,11 @@ class pkgCacheGenerator							/*{{{*/
 
 
    bool HasFileDeps() {return FoundFileDeps;};
    bool HasFileDeps() {return FoundFileDeps;};
    bool MergeFileProvides(ListParser &List);
    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(DynamicMMap *Map,OpProgress *Progress);
    ~pkgCacheGenerator();
    ~pkgCacheGenerator();
@@ -134,10 +138,12 @@ class pkgCacheGenerator::ListParser
    virtual ~ListParser() {};
    virtual ~ListParser() {};
 };
 };
 									/*}}}*/
 									/*}}}*/
+
 bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
 bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
 			MMap **OutMap = 0,bool AllowMem = false);
 			MMap **OutMap = 0,bool AllowMem = false);
 bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);
 bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);
 
 
+
 #ifdef APT_COMPATIBILITY
 #ifdef APT_COMPATIBILITY
 #if APT_COMPATIBILITY != 986
 #if APT_COMPATIBILITY != 986
 #warning "Using APT_COMPATIBILITY"
 #warning "Using APT_COMPATIBILITY"
@@ -145,7 +151,7 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);
 MMap *pkgMakeStatusCacheMem(pkgSourceList &List,OpProgress &Progress)
 MMap *pkgMakeStatusCacheMem(pkgSourceList &List,OpProgress &Progress)
 {
 {
    MMap *Map = 0;
    MMap *Map = 0;
-   if (pkgMakeStatusCache(List,Progress,&Map,true) == false)
+   if (pkgCacheGenerator::MakeStatusCache(List,&Progress,&Map,true) == false)
       return 0;
       return 0;
    return Map;
    return Map;
 }
 }

+ 24 - 0
apt-pkg/tagfile.cc

@@ -365,6 +365,30 @@ signed int pkgTagSection::FindI(const char *Tag,signed long Default) const
    return Result;
    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			/*{{{*/
 // TagSection::FindFlag - Locate a yes/no type flag			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* The bits marked in Flag are masked on/off in Flags */
 /* The bits marked in Flag are masked on/off in Flags */

+ 1 - 0
apt-pkg/tagfile.h

@@ -57,6 +57,7 @@ class pkgTagSection
    bool Find(const char *Tag,unsigned &Pos) const;
    bool Find(const char *Tag,unsigned &Pos) const;
    string FindS(const char *Tag) const;
    string FindS(const char *Tag) const;
    signed int FindI(const char *Tag,signed long Default = 0) 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,
    bool FindFlag(const char *Tag,unsigned long &Flags,
 		 unsigned long Flag) const;
 		 unsigned long Flag) const;
    bool Scan(const char *Start,unsigned long MaxLength);
    bool Scan(const char *Start,unsigned long MaxLength);

Разница между файлами не показана из-за своего большого размера
+ 309 - 364
cmdline/apt-cache.cc


+ 1 - 2
cmdline/apt-extracttemplates.cc

@@ -296,8 +296,7 @@ bool Go(CommandLine &CmdL)
 	MMap *Map = 0;
 	MMap *Map = 0;
 	pkgSourceList List;
 	pkgSourceList List;
 	List.ReadMainList();
 	List.ReadMainList();
-	OpProgress Prog;
-	pkgMakeStatusCache(List,Prog,&Map,true);
+	pkgCacheGenerator::MakeStatusCache(List,NULL,&Map,true);
 	if (Map == 0)
 	if (Map == 0)
 	   return false;
 	   return false;
 	DebFile::Cache = new pkgCache(Map);
 	DebFile::Cache = new pkgCache(Map);

+ 16 - 42
cmdline/apt-get.cc

@@ -40,7 +40,8 @@
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
 #include <apt-pkg/versionmatch.h>
-    
+#include <apt-pkg/cacheset.h>
+
 #include <config.h>
 #include <config.h>
 #include <apti18n.h>
 #include <apti18n.h>
 
 
@@ -90,14 +91,14 @@ class CacheFile : public pkgCacheFile
    bool BuildCaches(bool WithLock = true)
    bool BuildCaches(bool WithLock = true)
    {
    {
       OpTextProgress Prog(*_config);
       OpTextProgress Prog(*_config);
-      if (pkgCacheFile::BuildCaches(Prog,WithLock) == false)
+      if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false)
 	 return false;
 	 return false;
       return true;
       return true;
    }
    }
    bool Open(bool WithLock = true) 
    bool Open(bool WithLock = true) 
    {
    {
       OpTextProgress Prog(*_config);
       OpTextProgress Prog(*_config);
-      if (pkgCacheFile::Open(Prog,WithLock) == false)
+      if (pkgCacheFile::Open(&Prog,WithLock) == false)
 	 return false;
 	 return false;
       Sort();
       Sort();
       
       
@@ -837,9 +838,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       return false;
       return false;
 
 
    // Display statistics
    // 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())
    if (DebBytes != Cache->DebSize())
    {
    {
       c0out << DebBytes << ',' << Cache->DebSize() << endl;
       c0out << DebBytes << ',' << Cache->DebSize() << endl;
@@ -1780,51 +1781,24 @@ bool DoInstall(CommandLine &CmdL)
 	 Packages++;
 	 Packages++;
 	 if (Pkg.end() == true)
 	 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);
 	       return _error->Error(_("Couldn't find package %s"),S);
 
 
 	    // Regexs must always be confirmed
 	    // Regexs must always be confirmed
 	    ExpectedInst += 1000;
 	    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;
 	    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 (VerTag != 0)
 		  if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
 		  if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
 		     return false;
 		     return false;
-	    
+
 	       Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
 	       Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
 				   ExpectedInst,false);
 				   ExpectedInst,false);
 	    }
 	    }
-	    regfree(&Pattern);
-	 
+
 	    if (Hit == false)
 	    if (Hit == false)
 	       return _error->Error(_("Couldn't find package %s"),S);
 	       return _error->Error(_("Couldn't find package %s"),S);
 	 }
 	 }
@@ -2389,9 +2363,9 @@ bool DoSource(CommandLine &CmdL)
    }
    }
    
    
    // Display statistics
    // 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
    // Check for enough free space
    struct statvfs Buf;
    struct statvfs Buf;

+ 63 - 2
debian/changelog

@@ -1,4 +1,4 @@
-apt (0.7.26~exp6) experimental; urgency=low
+apt (0.7.26~exp6) UNRELEASED; urgency=low
 
 
   [ Michael Vogt ]
   [ Michael Vogt ]
   * merge the remaining Ubuntu change:
   * merge the remaining Ubuntu change:
@@ -20,8 +20,69 @@ apt (0.7.26~exp6) experimental; urgency=low
     - write apport crash file on package failure (disabled by default
     - write apport crash file on package failure (disabled by default
       on debian until apport is available)
       on debian until apport is available)
     - support mirror failure reporting (disabled by default on debian)
     - support mirror failure reporting (disabled by default on debian)
+  
+  [ David Kalnischkies ]
+  * 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
+    - 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
 
 
- -- Michael Vogt <mvo@debian.org>  Wed, 09 Jun 2010 10:50:17 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Wed, 09 Jun 2010 10:52:31 +0200
 
 
 apt (0.7.26~exp5) experimental; urgency=low
 apt (0.7.26~exp5) experimental; urgency=low
 
 

+ 2 - 1
doc/apt-ftparchive.1.xml

@@ -122,7 +122,8 @@
      e.g. <literal>APT::FTPArchive::Release::Origin</literal>.  The supported fields
      e.g. <literal>APT::FTPArchive::Release::Origin</literal>.  The supported fields
      are: <literal>Origin</literal>, <literal>Label</literal>, <literal>Suite</literal>,
      are: <literal>Origin</literal>, <literal>Label</literal>, <literal>Suite</literal>,
      <literal>Version</literal>, <literal>Codename</literal>, <literal>Date</literal>,
      <literal>Version</literal>, <literal>Codename</literal>, <literal>Date</literal>,
-     <literal>Architectures</literal>, <literal>Components</literal>, <literal>Description</literal>.</para></listitem>
+     <literal>Valid-Until</literal>, <literal>Architectures</literal>,
+     <literal>Components</literal>, <literal>Description</literal>.</para></listitem>
 
 
      </varlistentry>
      </varlistentry>
 
 

+ 1 - 6
doc/apt-mark.8.xml

@@ -121,12 +121,7 @@
 
 
  <refsect1><title>Files</title>
  <refsect1><title>Files</title>
    <variablelist>
    <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>
    </variablelist>
  </refsect1>
  </refsect1>
 
 

+ 24 - 0
doc/apt.conf.5.xml

@@ -230,6 +230,30 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
    and the URI handlers. 
    and the URI handlers. 
 
 
    <variablelist>
    <variablelist>
+     <varlistentry><term>Check-Valid-Until</term>
+	 <listitem><para>Security related option defaulting to true as an
+	 expiring validation for a Release file prevents longtime replay attacks
+	 and can e.g. also help users to identify no longer updated mirrors -
+	 but the feature depends on the correctness of the time on the user system.
+	 Archive maintainers are encouraged to create Release files with the
+	 <literal>Valid-Until</literal> header, but if they don't or a stricter value
+	 is volitional the following <literal>Max-ValidTime</literal> option can be used.
+	 </para></listitem>
+     </varlistentry>
+
+     <varlistentry><term>Max-ValidTime</term>
+	 <listitem><para>Seconds the Release file should be considered valid after
+	 it was created. The default is "for ever" (0) if the Release file of the
+	 archive doesn't include a <literal>Valid-Until</literal> header.
+	 If it does then this date is the default. The date from the Release file or
+	 the date specified by the creation time of the Release file
+	 (<literal>Date</literal> header) plus the seconds specified with this
+	 options are used to check if the validation of a file has expired by using
+	 the earlier date of the two. Archive specific settings can be made by
+	 appending the label of the archive to the option name.
+	 </para></listitem>
+     </varlistentry>
+
      <varlistentry><term>PDiffs</term>
      <varlistentry><term>PDiffs</term>
 	 <listitem><para>Try to download deltas called <literal>PDiffs</literal> for
 	 <listitem><para>Try to download deltas called <literal>PDiffs</literal> for
 	 Packages or Sources files instead of downloading whole ones. True
 	 Packages or Sources files instead of downloading whole ones. True

+ 8 - 0
doc/apt.ent

@@ -363,6 +363,14 @@
      </varlistentry>
      </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
 <!-- TRANSLATOR: This is the section header for the following paragraphs - comparable
      to the other headers like NAME and DESCRIPTION and should therefore be uppercase. -->
      to the other headers like NAME and DESCRIPTION and should therefore be uppercase. -->
 <!ENTITY translation-title "TRANSLATION">
 <!ENTITY translation-title "TRANSLATION">

+ 5 - 2
doc/examples/configure-index

@@ -176,6 +176,10 @@ Acquire
   PDiffs::SizeLimit "50"; // don't use diffs if size of all patches excess
   PDiffs::SizeLimit "50"; // don't use diffs if size of all patches excess
 			  // 50% of the size of the original file
 			  // 50% of the size of the original file
 
 
+  Check-Valid-Until "true";
+  Max-ValidTime "864000"; // 10 days
+  Max-ValidTime::Debian-Security "604800"; // 7 days, label specific configuration
+
   // HTTP method configuration
   // HTTP method configuration
   http 
   http 
   {
   {
@@ -294,9 +298,8 @@ Dir "/"
   State "var/lib/apt/" 
   State "var/lib/apt/" 
   {
   {
      Lists "lists/";
      Lists "lists/";
-     xstatus "xstatus";
-     userstatus "status.user";
      status "/var/lib/dpkg/status";
      status "/var/lib/dpkg/status";
+     extended_states "extended_states";
      cdroms "cdroms.list";
      cdroms "cdroms.list";
   };
   };
   
   

+ 10 - 0
ftparchive/writer.cc

@@ -924,6 +924,15 @@ ReleaseWriter::ReleaseWriter(string const &DB)
       datestr[0] = '\0';
       datestr[0] = '\0';
    }
    }
 
 
+   time_t const validuntil = now + _config->FindI("APT::FTPArchive::Release::ValidTime", 0);
+   char validstr[128];
+   if (now == validuntil ||
+       strftime(validstr, sizeof(validstr), "%a, %d %b %Y %H:%M:%S UTC",
+                gmtime(&validuntil)) == 0)
+   {
+      datestr[0] = '\0';
+   }
+
    map<string,string> Fields;
    map<string,string> Fields;
    Fields["Origin"] = "";
    Fields["Origin"] = "";
    Fields["Label"] = "";
    Fields["Label"] = "";
@@ -931,6 +940,7 @@ ReleaseWriter::ReleaseWriter(string const &DB)
    Fields["Version"] = "";
    Fields["Version"] = "";
    Fields["Codename"] = "";
    Fields["Codename"] = "";
    Fields["Date"] = datestr;
    Fields["Date"] = datestr;
+   Fields["Valid-Until"] = validstr;
    Fields["Architectures"] = "";
    Fields["Architectures"] = "";
    Fields["Components"] = "";
    Fields["Components"] = "";
    Fields["Description"] = "";
    Fields["Description"] = "";

+ 1 - 0
ftparchive/writer.h

@@ -72,6 +72,7 @@ class FTWScanner
    bool SetExts(string const &Vals);
    bool SetExts(string const &Vals);
       
       
    FTWScanner(string const &Arch = string());
    FTWScanner(string const &Arch = string());
+   virtual ~FTWScanner() {};
 };
 };
 
 
 class TranslationWriter
 class TranslationWriter

+ 1 - 2
methods/ftp.cc

@@ -661,8 +661,7 @@ bool FTPConn::ModTime(const char *Path, time_t &Time)
       return true;
       return true;
    
    
    // Parse it
    // Parse it
-   StrToTime(Msg,Time);
-   return true;
+   return FTPMDTMStrToTime(Msg.c_str(), Time);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FTPConn::CreateDataFd - Get a data connection			/*{{{*/
 // FTPConn::CreateDataFd - Get a data connection			/*{{{*/

+ 1 - 1
methods/http.cc

@@ -631,7 +631,7 @@ bool ServerState::HeaderLine(string Line)
    
    
    if (stringcasecmp(Tag,"Last-Modified:") == 0)
    if (stringcasecmp(Tag,"Last-Modified:") == 0)
    {
    {
-      if (StrToTime(Val,Date) == false)
+      if (RFC1123StrToTime(Val.c_str(), Date) == false)
 	 return _error->Error(_("Unknown date format"));
 	 return _error->Error(_("Unknown date format"));
       return true;
       return true;
    }
    }

+ 1 - 2
methods/rsh.cc

@@ -278,8 +278,7 @@ bool RSHConn::ModTime(const char *Path, time_t &Time)
       return false;
       return false;
 
 
    // Parse it
    // Parse it
-   StrToTime(Msg,Time);
-   return true;
+   return FTPMDTMStrToTime(Msg.c_str(), Time);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // RSHConn::Get - Get a file						/*{{{*/
 // RSHConn::Get - Get a file						/*{{{*/

+ 61 - 0
test/libapt/getarchitectures_test.cc

@@ -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;
+}

+ 5 - 0
test/libapt/makefile

@@ -12,6 +12,11 @@ SLIBS = -lapt-pkg
 SOURCE = getlanguages_test.cc
 SOURCE = getlanguages_test.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)
 
 
+PROGRAM = getArchitectures${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = getarchitectures_test.cc
+include $(PROGRAM_H)
+
 # Program for testing ParseDepends
 # Program for testing ParseDepends
 PROGRAM = ParseDepends${BASENAME}
 PROGRAM = ParseDepends${BASENAME}
 SLIBS = -lapt-pkg
 SLIBS = -lapt-pkg

+ 1 - 0
test/libapt/run-tests.sh

@@ -2,6 +2,7 @@
 set -e
 set -e
 
 
 echo "Compiling the tests ..."
 echo "Compiling the tests ..."
+test -d '../../build/obj/test/libapt/' || mkdir -p '../../build/obj/test/libapt/'
 make
 make
 echo "Running all testcases ..."
 echo "Running all testcases ..."
 LDPATH=$(pwd)/../../build/bin
 LDPATH=$(pwd)/../../build/bin

+ 14 - 0
test/pre-upload-check.py

@@ -192,6 +192,20 @@ class testAuthentication(unittest.TestCase):
                 self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0,
                 self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0,
                              "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*"))
                              "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*"))
 
 
+    def testValid(self):
+        for f in glob.glob("testsources.list/sources.list*validuntil*"):
+            self._cleanup()
+            (prefix, testtype, result) = f.split("-")
+            expected_res = self._expectedRes(result)
+            cmd = ["update"]
+            res = call([self.apt,"-o","Dir::Etc::sourcelist=./%s" % f]+cmd+apt_args,
+                       stdout=stdout, stderr=stderr)
+            self.assert_(res == expected_res,
+                         "test '%s' failed (got %s expected %s" % (f,res,expected_res))
+            if expected_res == 0:
+                self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0,
+                             "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*"))
+
 
 
 class testLocalRepositories(unittest.TestCase):
 class testLocalRepositories(unittest.TestCase):
     " test local repository regressions "
     " test local repository regressions "

+ 1 - 0
test/testsources.list/sources.list.all-validuntil-broken

@@ -0,0 +1 @@
+deb http://people.ubuntu.com/~mvo/apt/auth-test-suit/all-validuntil-broken/ /