Michael Vogt лет назад: 16
Родитель
Сommit
358f10d9d4

+ 1 - 1
apt-pkg/algorithms.h

@@ -48,7 +48,7 @@ class pkgSimulate : public pkgPackageManager				/*{{{*/
       pkgDepCache *Cache;
       public:
       
-      virtual VerIterator GetCandidateVer(PkgIterator Pkg)
+      virtual VerIterator GetCandidateVer(PkgIterator const &Pkg)
       {
 	 return (*Cache)[Pkg].CandidateVerIter(*Cache);
       }

+ 4 - 0
apt-pkg/aptconfiguration.cc

@@ -10,6 +10,7 @@
 // Include Files							/*{{{*/
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/strutl.h>
@@ -196,6 +197,9 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 	// it was undocumented and so it should be not very widthly used
 	string const oldAcquire = _config->Find("APT::Acquire::Translation","");
 	if (oldAcquire.empty() == false && oldAcquire != "environment") {
+		// TRANSLATORS: the two %s are APT configuration options
+		_error->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
+				"APT::Acquire::Translation", "Acquire::Languages");
 		if (oldAcquire != "none")
 			codes.push_back(oldAcquire);
 		codes.push_back("en");

+ 1 - 1
apt-pkg/cachefile.cc

@@ -28,7 +28,7 @@
 // ---------------------------------------------------------------------
 /* */
 pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL),
-				Policy(NULL), SrcList(NULL)
+				SrcList(NULL), Policy(NULL)
 {
 }
 									/*}}}*/

+ 6 - 2
apt-pkg/cachefile.h

@@ -20,10 +20,9 @@
 
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/acquire.h>
+#include <apt-pkg/policy.h>
 #include <apt-pkg/sourcelist.h>
 
-class pkgPolicy;
-class pkgSourceList;
 class pkgCacheFile
 {
    protected:
@@ -65,6 +64,11 @@ class pkgCacheFile
    inline pkgPolicy* GetPolicy() { BuildPolicy(); return Policy; };
    inline pkgSourceList* GetSourceList() { BuildSourceList(); return SrcList; };
 
+   inline bool IsPkgCacheBuilt() const { return (Cache != NULL); };
+   inline bool IsDepCacheBuilt() const { return (DCache != NULL); };
+   inline bool IsPolicyBuilt() const { return (Policy != NULL); };
+   inline bool IsSrcListBuilt() const { return (SrcList != NULL); };
+
    pkgCacheFile();
    virtual ~pkgCacheFile();
 };

+ 31 - 16
apt-pkg/cacheiterators.h

@@ -30,6 +30,8 @@
 #ifndef PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 #include<iterator>
+
+#include<string.h>
 // abstract Iterator template						/*{{{*/
 /* This template provides the very basic iterator methods we
    need to have for doing some walk-over-the-cache magic */
@@ -73,6 +75,12 @@ template<typename Str, typename Itr> class pkgCache::Iterator :
 	inline bool IsGood() const { return S && Owner && ! end();};
 	inline unsigned long Index() const {return S - OwnerPointer();};
 
+	void ReOwn(pkgCache &newOwner, void const * const oldMap, void const * const newMap) {
+		if (S == 0)
+			return;
+		S += (Str*)(newMap) - (Str*)(oldMap);
+	}
+
 	// Constructors - look out for the variable assigning
 	inline Iterator() : S(0), Owner(0) {};
 	inline Iterator(pkgCache &Owner,Str *T = 0) : S(T), Owner(&Owner) {};
@@ -103,13 +111,13 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
 
 	inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
 	inline PkgIterator PackageList() const;
-	PkgIterator FindPkg(string Arch = "any");
+	PkgIterator FindPkg(string Arch = "any") const;
 	/** \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 FindPreferredPkg() const;
+	PkgIterator NextPkg(PkgIterator const &Pkg) const;
 
 	// Constructors
 	inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator<Group, GrpIterator>(Owner, Trg), HashIndex(0) {
@@ -183,6 +191,13 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 
 	// Comparison
 	int CompareVer(const VerIterator &B) const;
+	/** \brief compares two version and returns if they are similar
+
+	    This method should be used to identify if two pseudo versions are
+	    refering to the same "real" version */
+	inline bool SimilarVer(const VerIterator &B) const {
+		return (B.end() == false && S->Hash == B->Hash && strcmp(VerStr(), B.VerStr()) == 0);
+	};
 
 	// Accessors
 	inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;};
@@ -263,17 +278,17 @@ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> {
 
 	// Accessors
 	inline const char *TargetVer() const {return S->Version == 0?0:Owner->StrP + S->Version;};
-	inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + S->Package);};
-	inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;};
-	inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + S->ParentVer);};
-	inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);};
-	inline bool Reverse() {return Type == DepRev;};
-	bool IsCritical();
+	inline PkgIterator TargetPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->Package);};
+	inline PkgIterator SmartTargetPkg() const {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;};
+	inline VerIterator ParentVer() const {return VerIterator(*Owner,Owner->VerP + S->ParentVer);};
+	inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);};
+	inline bool Reverse() const {return Type == DepRev;};
+	bool IsCritical() const;
 	void GlobOr(DepIterator &Start,DepIterator &End);
-	Version **AllTargets();
-	bool SmartTargetPkg(PkgIterator &Result);
-	inline const char *CompType() {return Owner->CompType(S->CompareOp);};
-	inline const char *DepType() {return Owner->DepType(S->Type);};
+	Version **AllTargets() const;
+	bool SmartTargetPkg(PkgIterator &Result) const;
+	inline const char *CompType() const {return Owner->CompType(S->CompareOp);};
+	inline const char *DepType() const {return Owner->DepType(S->Type);};
 
 	inline DepIterator(pkgCache &Owner, Dependency *Trg, Version* = 0) :
 		Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepVer) {
@@ -306,9 +321,9 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
 	// Accessors
 	inline const char *Name() const {return Owner->StrP + Owner->PkgP[S->ParentPkg].Name;};
 	inline const char *ProvideVersion() const {return S->ProvideVersion == 0?0:Owner->StrP + S->ProvideVersion;};
-	inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);};
-	inline VerIterator OwnerVer() {return VerIterator(*Owner,Owner->VerP + S->Version);};
-	inline PkgIterator OwnerPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);};
+	inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);};
+	inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);};
+	inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);};
 
 	inline PrvIterator() : Iterator<Provides, PrvIterator>(), Type(PrvVer) {};
 

+ 0 - 280
apt-pkg/cacheset.cc

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

+ 43 - 0
apt-pkg/contrib/configuration.cc

@@ -843,3 +843,46 @@ bool ReadConfigDir(Configuration &Conf,const string &Dir,
    return true;
 }
 									/*}}}*/
+// MatchAgainstConfig Constructor					/*{{{*/
+Configuration::MatchAgainstConfig::MatchAgainstConfig(char const * Config)
+{
+   std::vector<std::string> const strings = _config->FindVector(Config);
+   for (std::vector<std::string>::const_iterator s = strings.begin();
+	s != strings.end(); ++s)
+   {
+      regex_t *p = new regex_t;
+      if (regcomp(p, s->c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0)
+	 patterns.push_back(p);
+      else
+      {
+	 regfree(p);
+	 delete p;
+	 _error->Warning("Regex compilation error for '%s' in configuration option '%s'",
+				s->c_str(), Config);
+      }
+    }
+
+}
+									/*}}}*/
+// MatchAgainstConfig Destructor					/*{{{*/
+Configuration::MatchAgainstConfig::~MatchAgainstConfig()
+{
+   for(std::vector<regex_t *>::const_iterator p = patterns.begin();
+	p != patterns.end(); ++p)
+   {
+      regfree(*p);
+      delete *p;
+   }
+}
+									/*}}}*/
+// MatchAgainstConfig::Match - returns true if a pattern matches	/*{{{*/
+bool Configuration::MatchAgainstConfig::Match(char const * str) const
+{
+   for(std::vector<regex_t *>::const_iterator p = patterns.begin();
+	p != patterns.end(); ++p)
+      if (regexec(*p, str, 0, 0, 0) == 0)
+	 return true;
+
+   return false;
+}
+									/*}}}*/

+ 18 - 1
apt-pkg/contrib/configuration.h

@@ -28,7 +28,7 @@
 #ifndef PKGLIB_CONFIGURATION_H
 #define PKGLIB_CONFIGURATION_H
 
-
+#include <regex.h>
 
 #include <string>
 #include <vector>
@@ -104,6 +104,23 @@ class Configuration
    Configuration(const Item *Root);
    Configuration();
    ~Configuration();
+
+   /** \brief match a string against a configurable list of patterns */
+   class MatchAgainstConfig
+   {
+     std::vector<regex_t *> patterns;
+
+   public:
+     MatchAgainstConfig(char const * Config);
+     virtual ~MatchAgainstConfig();
+
+     /** \brief Returns \b true for a string matching one of the patterns */
+     bool Match(char const * str) const;
+     bool Match(std::string const &str) const { return Match(str.c_str()); };
+
+     /** \brief returns if the matcher setup was successful */
+     bool wasConstructedSuccessfully() const { return patterns.empty() == false; }
+   };
 };
 
 extern Configuration *_config;

+ 187 - 180
apt-pkg/contrib/error.cc

@@ -1,16 +1,15 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: error.cc,v 1.11 2002/03/26 07:38:58 jgg Exp $
 /* ######################################################################
-   
-   Global Erorr Class - Global error mechanism
+
+   Global Error Class - Global error mechanism
 
    We use a simple STL vector to store each error record. A PendingFlag
    is kept which indicates when the vector contains a Sever error.
-   
+
    This source is placed in the Public Domain, do with it what you will
    It was originally written by Jason Gunthorpe.
-   
+
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
@@ -19,7 +18,6 @@
 #include <iostream>
 #include <errno.h>
 #include <stdio.h>
-#include <stdarg.h>
 #include <unistd.h>
 
 #include <string>
@@ -28,209 +26,218 @@
 #include "config.h"
    									/*}}}*/
 
-using namespace std;
-
 // Global Error Object							/*{{{*/
 /* If the implementation supports posix threads then the accessor function
    is compiled to be thread safe otherwise a non-safe version is used. A
    Per-Thread error object is maintained in much the same manner as libc
    manages errno */
 #if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD)
- #include <pthread.h>
-
- static pthread_key_t ErrorKey;
- static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
- static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
-
- GlobalError *_GetErrorObj()
- {
-    static pthread_once_t Once = PTHREAD_ONCE_INIT;
-    pthread_once(&Once,KeyAlloc);
-    
-    void *Res = pthread_getspecific(ErrorKey);
-    if (Res == 0)
-       pthread_setspecific(ErrorKey,Res = new GlobalError);
-    return (GlobalError *)Res;
- }
+	#include <pthread.h>
+
+	static pthread_key_t ErrorKey;
+	static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
+	static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
+
+	GlobalError *_GetErrorObj() {
+		static pthread_once_t Once = PTHREAD_ONCE_INIT;
+		pthread_once(&Once,KeyAlloc);
+
+		void *Res = pthread_getspecific(ErrorKey);
+		if (Res == 0)
+			pthread_setspecific(ErrorKey,Res = new GlobalError);
+		return (GlobalError *)Res;
+	}
 #else
- GlobalError *_GetErrorObj()
- {
-    static GlobalError *Obj = new GlobalError;
-    return Obj;
- }
+	GlobalError *_GetErrorObj() {
+		static GlobalError *Obj = new GlobalError;
+		return Obj;
+	}
 #endif
 									/*}}}*/
-
 // GlobalError::GlobalError - Constructor				/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-GlobalError::GlobalError() : List(0), PendingFlag(false)
-{
+GlobalError::GlobalError() : PendingFlag(false) {}
+									/*}}}*/
+// GlobalError::FatalE - Get part of the error string from errno	/*{{{*/
+bool GlobalError::FatalE(const char *Function,const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return InsertErrno(FATAL, Function, Description, args);
 }
 									/*}}}*/
 // GlobalError::Errno - Get part of the error string from errno		/*{{{*/
-// ---------------------------------------------------------------------
-/* Function indicates the stdlib function that failed and Description is
-   a user string that leads the text. Form is:
-     Description - Function (errno: strerror)
-   Carefull of the buffer overrun, sprintf.
- */
-bool GlobalError::Errno(const char *Function,const char *Description,...)
-{
-   va_list args;
-   va_start(args,Description);
-
-   // sprintf the description
-   char S[400];
-   vsnprintf(S,sizeof(S),Description,args);
-   snprintf(S + strlen(S),sizeof(S) - strlen(S),
-	    " - %s (%i: %s)",Function,errno,strerror(errno));
-
-   // Put it on the list
-   Item *Itm = new Item;
-   Itm->Text = S;
-   Itm->Error = true;
-   Insert(Itm);
-
-   PendingFlag = true;
-
-   return false;
-}
-									/*}}}*/
-// GlobalError::WarningE - Get part of the warn string from errno	/*{{{*/
-// ---------------------------------------------------------------------
-/* Function indicates the stdlib function that failed and Description is
-   a user string that leads the text. Form is:
-     Description - Function (errno: strerror)
-   Carefull of the buffer overrun, sprintf.
- */
-bool GlobalError::WarningE(const char *Function,const char *Description,...)
-{
-   va_list args;
-   va_start(args,Description);
-
-   // sprintf the description
-   char S[400];
-   vsnprintf(S,sizeof(S),Description,args);
-   snprintf(S + strlen(S),sizeof(S) - strlen(S),
-	    " - %s (%i: %s)",Function,errno,strerror(errno));
-
-   // Put it on the list
-   Item *Itm = new Item;
-   Itm->Text = S;
-   Itm->Error = false;
-   Insert(Itm);
-
-   return false;
+bool GlobalError::Errno(const char *Function,const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return InsertErrno(ERROR, Function, Description, args);
+}
+									/*}}}*/
+// GlobalError::WarningE - Get part of the warning string from errno	/*{{{*/
+bool GlobalError::WarningE(const char *Function,const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return InsertErrno(WARNING, Function, Description, args);
+}
+									/*}}}*/
+// GlobalError::NoticeE - Get part of the notice string from errno	/*{{{*/
+bool GlobalError::NoticeE(const char *Function,const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return InsertErrno(NOTICE, Function, Description, args);
+}
+									/*}}}*/
+// GlobalError::DebugE - Get part of the debug string from errno	/*{{{*/
+bool GlobalError::DebugE(const char *Function,const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return InsertErrno(DEBUG, Function, Description, args);
+}
+									/*}}}*/
+// GlobalError::InsertErrno - formats an error message with the errno	/*{{{*/
+bool GlobalError::InsertErrno(MsgType type, const char* Function,
+			      const char* Description, va_list const &args) {
+	char S[400];
+	vsnprintf(S,sizeof(S),Description,args);
+	snprintf(S + strlen(S),sizeof(S) - strlen(S),
+	         " - %s (%i: %s)", Function, errno, strerror(errno));
+	return Insert(type, S, args);
+}
+									/*}}}*/
+// GlobalError::Fatal - Add a fatal error to the list			/*{{{*/
+bool GlobalError::Fatal(const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return Insert(FATAL, Description, args);
 }
 									/*}}}*/
 // GlobalError::Error - Add an error to the list			/*{{{*/
-// ---------------------------------------------------------------------
-/* Just vsprintfs and pushes */
-bool GlobalError::Error(const char *Description,...)
-{
-   va_list args;
-   va_start(args,Description);
-
-   // sprintf the description
-   char S[400];
-   vsnprintf(S,sizeof(S),Description,args);
-
-   // Put it on the list
-   Item *Itm = new Item;
-   Itm->Text = S;
-   Itm->Error = true;
-   Insert(Itm);
-   
-   PendingFlag = true;
-   
-   return false;
+bool GlobalError::Error(const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return Insert(ERROR, Description, args);
 }
 									/*}}}*/
 // GlobalError::Warning - Add a warning to the list			/*{{{*/
-// ---------------------------------------------------------------------
-/* This doesn't set the pending error flag */
-bool GlobalError::Warning(const char *Description,...)
+bool GlobalError::Warning(const char *Description,...) {
+	va_list args;
+	va_start(args,Description);
+	return Insert(WARNING, Description, args);
+}
+									/*}}}*/
+// GlobalError::Notice - Add a notice to the list			/*{{{*/
+bool GlobalError::Notice(const char *Description,...)
 {
-   va_list args;
-   va_start(args,Description);
+	va_list args;
+	va_start(args,Description);
+	return Insert(NOTICE, Description, args);
+}
+									/*}}}*/
+// GlobalError::Debug - Add a debug to the list				/*{{{*/
+bool GlobalError::Debug(const char *Description,...)
+{
+	va_list args;
+	va_start(args,Description);
+	return Insert(DEBUG, Description, args);
+}
+									/*}}}*/
+// GlobalError::Insert - Insert a new item at the end			/*{{{*/
+bool GlobalError::Insert(MsgType type, const char* Description,
+			 va_list const &args) {
+	char S[400];
+	vsnprintf(S,sizeof(S),Description,args);
+
+	Item const m(S, type);
+	Messages.push_back(m);
+
+	if (type == ERROR || type == FATAL)
+		PendingFlag = true;
 
-   // sprintf the description
-   char S[400];
-   vsnprintf(S,sizeof(S),Description,args);
+	if (type == FATAL || type == DEBUG)
+		std::clog << m << std::endl;
 
-   // Put it on the list
-   Item *Itm = new Item;
-   Itm->Text = S;
-   Itm->Error = false;
-   Insert(Itm);
-   
-   return false;
+	return false;
 }
 									/*}}}*/
 // GlobalError::PopMessage - Pulls a single message out			/*{{{*/
-// ---------------------------------------------------------------------
-/* This should be used in a loop checking empty() each cycle. It returns
-   true if the message is an error. */
-bool GlobalError::PopMessage(string &Text)
-{
-   if (List == 0)
-      return false;
-      
-   bool Ret = List->Error;
-   Text = List->Text;
-   Item *Old = List;
-   List = List->Next;
-   delete Old;
-   
-   // This really should check the list to see if only warnings are left..
-   if (List == 0)
-      PendingFlag = false;
-   
-   return Ret;
+bool GlobalError::PopMessage(std::string &Text) {
+	if (Messages.empty() == true)
+		return false;
+
+	Item const msg = Messages.front();
+	Messages.pop_front();
+
+	bool const Ret = (msg.Type == ERROR || msg.Type == FATAL);
+	Text = msg.Text;
+	if (PendingFlag == false || Ret == false)
+		return Ret;
+
+	// check if another error message is pending
+	for (std::list<Item>::const_iterator m = Messages.begin();
+	     m != Messages.end(); m++)
+		if (m->Type == ERROR || m->Type == FATAL)
+			return Ret;
+
+	PendingFlag = false;
+	return Ret;
 }
 									/*}}}*/
 // GlobalError::DumpErrors - Dump all of the errors/warns to cerr	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void GlobalError::DumpErrors()
-{
-   // Print any errors or warnings found
-   string Err;
-   while (empty() == false)
-   {
-      bool Type = PopMessage(Err);
-      if (Type == true)
-	 cerr << "E: " << Err << endl;
-      else
-	 cerr << "W: " << Err << endl;
-   }
-}
-									/*}}}*/
-// GlobalError::Discard - Discard									/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void GlobalError::Discard()
-{
-   while (List != 0)
-   {
-      Item *Old = List;
-      List = List->Next;
-      delete Old;
-   }
-   
-   PendingFlag = false;
+void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold,
+			     bool const &mergeStack) {
+	if (mergeStack == true)
+		for (std::list<MsgStack>::const_reverse_iterator s = Stacks.rbegin();
+		     s != Stacks.rend(); ++s)
+			Messages.insert(Messages.begin(), s->Messages.begin(), s->Messages.end());
+
+	for (std::list<Item>::const_iterator m = Messages.begin();
+	     m != Messages.end(); m++)
+		if (m->Type >= trashhold)
+			out << (*m) << std::endl;
+	Discard();
+}
+									/*}}}*/
+// GlobalError::Discard - Discard					/*{{{*/
+void GlobalError::Discard() {
+	Messages.clear();
+	PendingFlag = false;
 };
 									/*}}}*/
-// GlobalError::Insert - Insert a new item at the end			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void GlobalError::Insert(Item *Itm)
-{
-   Item **End = &List;
-   for (Item *I = List; I != 0; I = I->Next)
-      End = &I->Next;
-   Itm->Next = *End;
-   *End = Itm;
+// GlobalError::empty - does our error list include anything?		/*{{{*/
+bool GlobalError::empty(MsgType const &trashhold) const {
+	if (PendingFlag == true)
+		return false;
+
+	if (Messages.empty() == true)
+		return true;
+
+	for (std::list<Item>::const_iterator m = Messages.begin();
+	     m != Messages.end(); m++)
+		if (m->Type >= trashhold)
+			return false;
+
+	return true;
+}
+									/*}}}*/
+// GlobalError::PushToStack						/*{{{*/
+void GlobalError::PushToStack() {
+	MsgStack pack(Messages, PendingFlag);
+	Stacks.push_back(pack);
+	Discard();
+}
+									/*}}}*/
+// GlobalError::RevertToStack						/*{{{*/
+void GlobalError::RevertToStack() {
+	Discard();
+	MsgStack pack = Stacks.back();
+	Messages = pack.Messages;
+	PendingFlag = pack.PendingFlag;
+	Stacks.pop_back();
+}
+									/*}}}*/
+// GlobalError::MergeWithStack						/*{{{*/
+void GlobalError::MergeWithStack() {
+	MsgStack pack = Stacks.back();
+	Messages.insert(Messages.begin(), pack.Messages.begin(), pack.Messages.end());
+	PendingFlag = PendingFlag || pack.PendingFlag;
+	Stacks.pop_back();
 }
 									/*}}}*/

+ 234 - 29
apt-pkg/contrib/error.h

@@ -42,43 +42,248 @@
 
 #include <apt-pkg/macros.h>
 
+#include <iostream>
+#include <list>
 #include <string>
 
-class GlobalError
+#include <stdarg.h>
+
+class GlobalError							/*{{{*/
 {
-   struct Item
-   {
-      std::string Text;
-      bool Error;
-      Item *Next;
-   };
-   
-   Item *List;
-   bool PendingFlag;
-   void Insert(Item *I);
-   
-   public:
+public:									/*{{{*/
+	/** \brief a message can have one of following severity */
+	enum MsgType {
+		/** \brief Message will be printed instantly as it is likely that
+			this error will lead to a complete crash */
+		FATAL = 40,
+		/** \brief An error does hinder the correct execution and should be corrected */
+		ERROR = 30,
+		/** \brief indicates problem that can lead to errors later on */
+		WARNING = 20,
+		/** \brief deprecation warnings, old fallback behavior, … */
+		NOTICE = 10,
+		/** \brief for developers only in areas it is hard to print something directly */
+		DEBUG = 0
+	};
 
-   // Call to generate an error from a library call.
-   bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold;
-   bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold;
+	/** \brief add a fatal error message with errno to the list
+	 *
+	 *  \param Function name of the function generating the error
+	 *  \param Description format string for the error message
+	 *
+	 *  \return \b false
+	 */
+	bool FatalE(const char *Function,const char *Description,...) __like_printf(3) __cold;
 
-   /* A warning should be considered less severe than an error, and may be
-      ignored by the client. */
-   bool Error(const char *Description,...) __like_printf(2) __cold;
-   bool Warning(const char *Description,...) __like_printf(2) __cold;
+	/** \brief add an Error message with errno to the list
+	 *
+	 *  \param Function name of the function generating the error
+	 *  \param Description format string for the error message
+	 *
+	 *  \return \b false
+	 */
+	bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold;
 
-   // Simple accessors
-   inline bool PendingError() {return PendingFlag;};
-   inline bool empty() {return List == 0;};
-   bool PopMessage(std::string &Text);
-   void Discard();
+	/** \brief add a warning message with errno to the list
+	 *
+	 *  A warning should be considered less severe than an error and
+	 *  may be ignored by the client.
+	 *
+	 *  \param Function Name of the function generates the warning.
+	 *  \param Description Format string for the warning message.
+	 *
+	 *  \return \b false
+	 */
+	bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold;
 
-   // Usefull routine to dump to cerr
-   void DumpErrors();
-   
-   GlobalError();
+	/** \brief add a notice message with errno to the list
+	 *
+	 *  \param Function name of the function generating the error
+	 *  \param Description format string for the error message
+	 *
+	 *  \return \b false
+	 */
+	bool NoticeE(const char *Function,const char *Description,...) __like_printf(3) __cold;
+
+	/** \brief add a debug message with errno to the list
+	 *
+	 *  \param Function name of the function generating the error
+	 *  \param Description format string for the error message
+	 *
+	 *  \return \b false
+	 */
+	bool DebugE(const char *Function,const char *Description,...) __like_printf(3) __cold;
+
+	/** \brief add an fatal error message to the list
+	 *
+	 *  Most of the stuff we consider as "error" is also "fatal" for
+	 *  the user as the application will not have the expected result,
+	 *  but a fatal message here means that it gets printed directly
+	 *  to stderr in addiction to adding it to the list as the error
+	 *  leads sometimes to crashes and a maybe duplicated message
+	 *  is better than "Segfault" as the only displayed text
+	 *
+	 *  \param Description Format string for the fatal error message.
+	 *
+	 *  \return \b false
+	 */
+	bool Fatal(const char *Description,...) __like_printf(2) __cold;
+
+	/** \brief add an Error message to the list
+	 *
+	 *  \param Description Format string for the error message.
+	 *
+	 *  \return \b false
+	 */
+	bool Error(const char *Description,...) __like_printf(2) __cold;
+
+	/** \brief add a warning message to the list
+	 *
+	 *  A warning should be considered less severe than an error and
+	 *  may be ignored by the client.
+	 *
+	 *  \param Description Format string for the message
+	 *
+	 *  \return \b false
+	 */
+	bool Warning(const char *Description,...) __like_printf(2) __cold;
+
+	/** \brief add a notice message to the list
+	 *
+	 *  A notice should be considered less severe than an error or a
+	 *  warning and can be ignored by the client without further problems
+	 *  for some times, but he should consider fixing the problem.
+	 *  This error type can be used for e.g. deprecation warnings of options.
+	 *
+	 *  \param Description Format string for the message
+	 *
+	 *  \return \b false
+	 */
+	bool Notice(const char *Description,...) __like_printf(2) __cold;
+
+	/** \brief add a debug message to the list
+	 *
+	 *  \param Description Format string for the message
+	 *
+	 *  \return \b false
+	 */
+	bool Debug(const char *Description,...) __like_printf(2) __cold;
+
+	/** \brief is an error in the list?
+	 *
+	 *  \return \b true if an error is included in the list, \b false otherwise
+	 */
+	inline bool PendingError() const {return PendingFlag;};
+
+	/** \brief is the list empty?
+	 *
+	 *  The default checks if the list is empty or contains only notices,
+	 *  if you want to check if also no notices happend set the parameter
+	 *  flag to \b false.
+	 *
+	 *  \param WithoutNotice does notices count, default is \b true, so no
+	 *
+	 *  \return \b true if an the list is empty, \b false otherwise
+	 */
+	bool empty(MsgType const &trashhold = WARNING) const;
+
+	/** \brief returns and removes the first (or last) message in the list
+	 *
+	 *  \param[out] Text message of the first/last item
+	 *
+	 *  \return \b true if the message was an error, \b false otherwise
+	 */
+	bool PopMessage(std::string &Text);
+
+	/** \brief clears the list of messages */
+	void Discard();
+
+	/** \brief outputs the list of messages to the given stream
+	 *
+	 *  Note that all messages are discarded, also the notices
+	 *  displayed or not.
+	 *
+	 *  \param[out] out output stream to write the messages in
+	 *  \param WithoutNotice output notices or not
+	 */
+	void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING,
+			bool const &mergeStack = true);
+
+	/** \brief dumps the list of messages to std::cerr
+	 *
+	 *  Note that all messages are discarded, also the notices
+	 *  displayed or not.
+	 *
+	 *  \param WithoutNotice print notices or not
+	 */
+	void inline DumpErrors(MsgType const &trashhold = WARNING) {
+		DumpErrors(std::cerr, trashhold);
+	}
+
+	/** \brief put the current Messages into the stack
+	 *
+	 *  All "old" messages will be pushed into a stack to
+	 *  them later back, but for now the Message query will be
+	 *  empty and performs as no messages were present before.
+	 *
+	 * The stack can be as deep as you want - all stack operations
+	 * will only operate on the last element in the stack.
+	 */
+	void PushToStack();
+
+	/** \brief throw away all current messages */
+	void RevertToStack();
+
+	/** \brief merge current and stack together */
+	void MergeWithStack();
+
+	/** \brief return the deep of the stack */
+	size_t StackCount() const {
+		return Stacks.size();
+	}
+
+	GlobalError();
+									/*}}}*/
+private:								/*{{{*/
+	struct Item {
+		std::string Text;
+		MsgType Type;
+
+		Item(char const *Text, MsgType const &Type) :
+			Text(Text), Type(Type) {};
+
+		friend std::ostream& operator<< (std::ostream &out, Item i) {
+			switch(i.Type) {
+			case FATAL:
+			case ERROR: out << "E"; break;
+			case WARNING: out << "W"; break;
+			case NOTICE: out << "N"; break;
+			case DEBUG: out << "D"; break;
+			}
+			return out << ": " << i.Text;
+		}
+	};
+
+	std::list<Item> Messages;
+	bool PendingFlag;
+
+	struct MsgStack {
+		std::list<Item> const Messages;
+		bool const PendingFlag;
+
+		MsgStack(std::list<Item> const &Messages, bool const &Pending) :
+			 Messages(Messages), PendingFlag(Pending) {};
+	};
+
+	std::list<MsgStack> Stacks;
+
+	bool InsertErrno(MsgType type, const char* Function,
+			 const char* Description, va_list const &args);
+	bool Insert(MsgType type, const char* Description,
+			 va_list const &args);
+									/*}}}*/
 };
+									/*}}}*/
 
 // The 'extra-ansi' syntax is used to help with collisions. 
 GlobalError *_GetErrorObj();

+ 4 - 0
apt-pkg/contrib/fileutl.cc

@@ -282,6 +282,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
    }
 
    std::vector<string> List;
+   Configuration::MatchAgainstConfig SilentIgnore("Dir::Ignore-Files-Silently");
    DIR *D = opendir(Dir.c_str());
    if (D == 0) 
    {
@@ -307,6 +308,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
 	    {
 	       if (Debug == true)
 		  std::clog << "Bad file: " << Ent->d_name << " → no extension" << std::endl;
+	       _error->Notice("Ignoring file '%s' in directory '%s' as it has no filename extension", Ent->d_name, Dir.c_str());
 	       continue;
 	    }
 	 }
@@ -314,6 +316,8 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
 	 {
 	    if (Debug == true)
 	       std::clog << "Bad file: " << Ent->d_name << " → bad extension »" << flExtension(Ent->d_name) << "«" << std::endl;
+	    if (SilentIgnore.Match(Ent->d_name) == false)
+	       _error->Notice("Ignoring file '%s' in directory '%s' as it has an invalid filename extension", Ent->d_name, Dir.c_str());
 	    continue;
 	 }
       }

+ 19 - 10
apt-pkg/contrib/mmap.cc

@@ -225,22 +225,22 @@ DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace,
 
 	// disable Moveable if we don't grow
 	if (Grow == 0)
-		Flags &= ~Moveable;
+		this->Flags &= ~Moveable;
 
 #ifndef __linux__
 	// kfreebsd doesn't have mremap, so we use the fallback
-	if ((Flags & Moveable) == Moveable)
-		Flags |= Fallback;
+	if ((this->Flags & Moveable) == Moveable)
+		this->Flags |= Fallback;
 #endif
 
 #ifdef _POSIX_MAPPED_FILES
-	if ((Flags & Fallback) != Fallback) {
+	if ((this->Flags & Fallback) != Fallback) {
 		// Set the permissions.
 		int Prot = PROT_READ;
 		int Map = MAP_PRIVATE | MAP_ANONYMOUS;
-		if ((Flags & ReadOnly) != ReadOnly)
+		if ((this->Flags & ReadOnly) != ReadOnly)
 			Prot |= PROT_WRITE;
-		if ((Flags & Public) == Public)
+		if ((this->Flags & Public) == Public)
 			Map = MAP_SHARED | MAP_ANONYMOUS;
 
 		// use anonymous mmap() to get the memory
@@ -297,7 +297,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
    {
       if(!Grow())
       {
-	 _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
+	 _error->Fatal(_("Dynamic MMap ran out of room. Please increase the size "
 			 "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
 	 return 0;
       }
@@ -314,7 +314,7 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
    // Look for a matching pool entry
    Pool *I;
    Pool *Empty = 0;
-   for (I = Pools; I != Pools + PoolCount; I++)
+   for (I = Pools; I != Pools + PoolCount; ++I)
    {
       if (I->ItemSize == 0)
 	 Empty = I;
@@ -342,7 +342,11 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
    {
       const unsigned long size = 20*1024;
       I->Count = size/ItemSize;
+      Pool* oldPools = Pools;
       Result = RawAllocate(size,ItemSize);
+      if (Pools != oldPools)
+	 I += Pools - oldPools;
+
       // Does the allocation failed ?
       if (Result == 0 && _error->PendingError())
 	 return 0;
@@ -365,7 +369,7 @@ unsigned long DynamicMMap::WriteString(const char *String,
    if (Len == (unsigned long)-1)
       Len = strlen(String);
 
-   unsigned long Result = RawAllocate(Len+1,0);
+   unsigned long const Result = RawAllocate(Len+1,0);
 
    if (Result == 0 && _error->PendingError())
       return 0;
@@ -395,16 +399,20 @@ bool DynamicMMap::Grow() {
 		return _error->Error(_("Unable to increase the size of the MMap as the "
 		                       "limit of %lu bytes is already reached."), Limit);
 
-	unsigned long const newSize = WorkSpace + 1024*1024;
+	unsigned long const newSize = WorkSpace + GrowFactor;
 
 	if(Fd != 0) {
 		Fd->Seek(newSize - 1);
 		char C = 0;
 		Fd->Write(&C,sizeof(C));
 	}
+
+	unsigned long const poolOffset = Pools - ((Pool*) Base);
+
 	if ((Flags & Fallback) != Fallback) {
 #if defined(_POSIX_MAPPED_FILES) && defined(__linux__)
    #ifdef MREMAP_MAYMOVE
+
 		if ((Flags & Moveable) == Moveable)
 			Base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE);
 		else
@@ -425,6 +433,7 @@ bool DynamicMMap::Grow() {
 			return false;
 	}
 
+	Pools =(Pool*) Base + poolOffset;
 	WorkSpace = newSize;
 	return true;
 }

+ 1 - 0
apt-pkg/deb/debindexfile.cc

@@ -277,6 +277,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 
    // Store the IMS information
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
+   pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
    struct stat St;
    if (fstat(Pkg.Fd(),&St) != 0)
       return _error->Errno("fstat","Failed to stat");

+ 18 - 21
apt-pkg/deb/deblistparser.cc

@@ -39,6 +39,8 @@ debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
 				Arch(Arch) {
    if (Arch == "native")
       this->Arch = _config->Find("APT::Architecture");
+   Architectures = APT::Configuration::getArchitectures();
+   MultiArchEnabled = Architectures.size() > 1;
 }
 									/*}}}*/
 // ListParser::UniqFindTagWrite - Find the tag and write a unq string	/*{{{*/
@@ -104,7 +106,7 @@ string debListParser::Version()
 // ListParser::NewVersion - Fill in the version structure		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool debListParser::NewVersion(pkgCache::VerIterator Ver)
+bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
 {
    // Parse the section
    Ver->Section = UniqFindTagWrite("Section");
@@ -156,10 +158,9 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
 	 to a NOP in the download/install step - this package will ensure that
 	 it is downloaded only one time and installed only one time -- even if
 	 the architecture bound versions coming in and out on regular basis. */
-      bool const static multiArch = APT::Configuration::getArchitectures().size() > 1;
       if (strcmp(Ver.Arch(true),"all") == 0)
 	 return true;
-      else if (multiArch == true)
+      else if (MultiArchEnabled == true)
       {
 	 // our pseudo packages have no size to not confuse the fetcher
 	 Ver->Size = 0;
@@ -250,8 +251,8 @@ MD5SumValue debListParser::Description_md5()
 // ---------------------------------------------------------------------
 /* This is called to update the package with any new information 
    that might be found in the section */
-bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
-			       pkgCache::VerIterator Ver)
+bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
+			       pkgCache::VerIterator &Ver)
 {
    if (Pkg->Section == 0)
       Pkg->Section = UniqFindTagWrite("Section");
@@ -331,8 +332,8 @@ unsigned short debListParser::VersionHash()
    Some of the above are obsolete (I think?) flag = hold-* and 
    status = post-inst-failed, removal-failed at least.
  */
-bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
-				pkgCache::VerIterator Ver)
+bool debListParser::ParseStatus(pkgCache::PkgIterator &Pkg,
+				pkgCache::VerIterator &Ver)
 {
    const char *Start;
    const char *Stop;
@@ -633,7 +634,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
 // ---------------------------------------------------------------------
 /* This is the higher level depends parser. It takes a tag and generates
    a complete depends tree for the given version. */
-bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
+bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
 				 const char *Tag,unsigned int Type)
 {
    const char *Start;
@@ -641,9 +642,6 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
    if (Section.Find(Tag,Start,Stop) == false)
       return true;
 
-   static std::vector<std::string> const archs = APT::Configuration::getArchitectures();
-   static bool const multiArch = archs.size() <= 1;
-
    string Package;
    string const pkgArch = Ver.Arch(true);
    string Version;
@@ -655,13 +653,13 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
       if (Start == 0)
 	 return _error->Error("Problem parsing dependency %s",Tag);
 
-      if (multiArch == true &&
+      if (MultiArchEnabled == true &&
 	  (Type == pkgCache::Dep::Conflicts ||
 	   Type == pkgCache::Dep::DpkgBreaks ||
 	   Type == pkgCache::Dep::Replaces))
       {
-	 for (std::vector<std::string>::const_iterator a = archs.begin();
-	      a != archs.end(); ++a)
+	 for (std::vector<std::string>::const_iterator a = Architectures.begin();
+	      a != Architectures.end(); ++a)
 	    if (NewDepends(Ver,Package,*a,Version,Op,Type) == false)
 	       return false;
       }
@@ -676,7 +674,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
 // ListParser::ParseProvides - Parse the provides list			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
+bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 {
    const char *Start;
    const char *Stop;
@@ -713,14 +711,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
    if (Ver->MultiArch != pkgCache::Version::Foreign)
       return true;
 
-   std::vector<string> const archs = APT::Configuration::getArchitectures();
-   if (archs.size() <= 1)
+   if (MultiArchEnabled == false)
       return true;
 
    string const Package = Ver.ParentPkg().Name();
    string const Version = Ver.VerStr();
-   for (std::vector<string>::const_iterator a = archs.begin();
-	a != archs.end(); ++a)
+   for (std::vector<string>::const_iterator a = Architectures.begin();
+	a != Architectures.end(); ++a)
    {
       if (NewProvides(Ver, Package, *a, Version) == false)
 	 return false;
@@ -760,7 +757,7 @@ bool debListParser::Step()
       if (Architecture.empty() == true)
 	 return true;
 
-      if (Arch.empty() == true)
+      if (Arch.empty() == true || MultiArchEnabled == false)
       {
 	 if (APT::Configuration::checkArchitecture(Architecture) == true)
 	    return true;
@@ -782,7 +779,7 @@ bool debListParser::Step()
 // ListParser::LoadReleaseInfo - Load the release information		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
+bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
 				    FileFd &File, string component)
 {
    pkgTagFile Tags(&File, File.Size() + 256); // XXX

+ 10 - 8
apt-pkg/deb/deblistparser.h

@@ -32,12 +32,14 @@ class debListParser : public pkgCacheGenerator::ListParser
    pkgTagSection Section;
    unsigned long iOffset;
    string Arch;
-   
+   std::vector<std::string> Architectures;
+   bool MultiArchEnabled;
+
    unsigned long UniqFindTagWrite(const char *Tag);
-   bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver);
-   bool ParseDepends(pkgCache::VerIterator Ver,const char *Tag,
+   bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver);
+   bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag,
 		     unsigned int Type);
-   bool ParseProvides(pkgCache::VerIterator Ver);
+   bool ParseProvides(pkgCache::VerIterator &Ver);
    static bool GrabWord(string Word,WordList *List,unsigned char &Out);
    
    public:
@@ -49,19 +51,19 @@ class debListParser : public pkgCacheGenerator::ListParser
    virtual string Architecture();
    virtual bool ArchitectureAll();
    virtual string Version();
-   virtual bool NewVersion(pkgCache::VerIterator Ver);
+   virtual bool NewVersion(pkgCache::VerIterator &Ver);
    virtual string Description();
    virtual string DescriptionLanguage();
    virtual MD5SumValue Description_md5();
    virtual unsigned short VersionHash();
-   virtual bool UsePackage(pkgCache::PkgIterator Pkg,
-			   pkgCache::VerIterator Ver);
+   virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
+			   pkgCache::VerIterator &Ver);
    virtual unsigned long Offset() {return iOffset;};
    virtual unsigned long Size() {return Section.size();};
 
    virtual bool Step();
    
-   bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File,
+   bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File,
 			string section);
    
    static const char *ParseDepends(const char *Start,const char *Stop,

+ 37 - 51
apt-pkg/depcache.cc

@@ -1255,6 +1255,10 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    Update(Pkg);
    AddSizes(Pkg);
 
+   // always trigger the install of the all package for a pseudo package
+   if (P.CandidateVerIter(*Cache).Pseudo() == true)
+      MarkInstall(Pkg.Group().FindPkg("all"), AutoInst, Depth, FromUser, ForceImportantDeps);
+
    if (AutoInst == false)
       return;
 
@@ -1453,6 +1457,9 @@ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
 /* */
 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 {
+   if (unlikely(Pkg.end() == true))
+      return;
+
    ActionGroup group(*this);
 
    RemoveSizes(Pkg);
@@ -1466,12 +1473,17 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
    
    AddStates(Pkg);
    AddSizes(Pkg);
+
+   if (unlikely(Pkg.CurrentVer().end() == true) || Pkg.CurrentVer().Pseudo() == false)
+      return;
+
+   SetReInstall(Pkg.Group().FindPkg("all"), To);
 }
 									/*}}}*/
 // DepCache::SetCandidateVersion - Change the candidate version		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
+void pkgDepCache::SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo)
 {
    ActionGroup group(*this);
 
@@ -1489,6 +1501,28 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
    AddStates(Pkg);
    Update(Pkg);
    AddSizes(Pkg);
+
+   if (TargetVer.Pseudo() == false || Pseudo == false)
+      return;
+
+   // the version was pseudo: set all other pseudos also
+   pkgCache::GrpIterator Grp = Pkg.Group();
+   for (Pkg = Grp.FindPkg("any"); Pkg.end() == false; ++Pkg)
+   {
+      StateCache &P = PkgState[Pkg->ID];
+      if (TargetVer.SimilarVer(P.CandidateVerIter(*this)) == true ||
+	  (P.CandidateVerIter(*this).Pseudo() == false &&
+	   strcmp(Pkg.Arch(), "all") != 0))
+	 continue;
+
+      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
+      {
+	 if (TargetVer.SimilarVer(Ver) == false)
+	    continue;
+	 SetCandidateVersion(Ver, false);
+	 break;
+      }
+   }
 }
 
 void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
@@ -1551,7 +1585,7 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
 // ---------------------------------------------------------------------
 /* The default just returns the highest available version that is not
    a source and automatic. */
-pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
+pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pkg)
 {
    /* Not source/not automatic versions cannot be a candidate version 
       unless they are already installed */
@@ -1586,7 +1620,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
 // Policy::IsImportantDep - True if the dependency is important		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
+bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep)
 {
    if(Dep.IsCritical())
       return true;
@@ -1605,54 +1639,6 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);
 
-   return false;
-}
-									/*}}}*/
-pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()			/*{{{*/
-  : constructedSuccessfully(false)
-{
-  Configuration::Item const *Opts;
-  Opts = _config->Tree("APT::NeverAutoRemove");
-  if (Opts != 0 && Opts->Child != 0)
-    {
-      Opts = Opts->Child;
-      for (; Opts != 0; Opts = Opts->Next)
-	{
-	  if (Opts->Value.empty() == true)
-	    continue;
-
-	  regex_t *p = new regex_t;
-	  if(regcomp(p,Opts->Value.c_str(),
-		     REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
-	    {
-	      regfree(p);
-	      delete p;
-	      _error->Error("Regex compilation error for APT::NeverAutoRemove");
-	      return;
-	    }
-
-	  rootSetRegexp.push_back(p);
-	}
-    }
-
-  constructedSuccessfully = true;
-}
-									/*}}}*/
-pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()			/*{{{*/
-{
-  for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
-    {
-      regfree(rootSetRegexp[i]);
-      delete rootSetRegexp[i];
-    }
-}
-									/*}}}*/
-bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) /*{{{*/
-{
-   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
-      if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
-	 return true;
-
    return false;
 }
 									/*}}}*/

+ 10 - 20
apt-pkg/depcache.h

@@ -38,11 +38,10 @@
 #ifndef PKGLIB_DEPCACHE_H
 #define PKGLIB_DEPCACHE_H
 
-
+#include <apt-pkg/configuration.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/progress.h>
-
-#include <regex.h>
+#include <apt-pkg/error.h>
 
 #include <vector>
 #include <memory>
@@ -184,22 +183,13 @@ class pkgDepCache : protected pkgCache::Namespace
    /** \brief Returns \b true for packages matching a regular
     *  expression in APT::NeverAutoRemove.
     */
-   class DefaultRootSetFunc : public InRootSetFunc
+   class DefaultRootSetFunc : public InRootSetFunc, public Configuration::MatchAgainstConfig
    {
-     std::vector<regex_t *> rootSetRegexp;
-     bool constructedSuccessfully;
-
    public:
-     DefaultRootSetFunc();
-     ~DefaultRootSetFunc();
-
-     /** \return \b true if the class initialized successfully, \b
-      *  false otherwise.  Used to avoid throwing an exception, since
-      *  APT classes generally don't.
-      */
-     bool wasConstructedSuccessfully() const { return constructedSuccessfully; }
+     DefaultRootSetFunc() : Configuration::MatchAgainstConfig("APT::NeverRemove") {};
+     virtual ~DefaultRootSetFunc() {};
 
-     bool InRootSet(const pkgCache::PkgIterator &pkg);
+     bool InRootSet(const pkgCache::PkgIterator &pkg) { return pkg.end() == true && Match(pkg.Name()); };
    };
 
    struct StateCache
@@ -266,8 +256,8 @@ class pkgDepCache : protected pkgCache::Namespace
    {
       public:
       
-      virtual VerIterator GetCandidateVer(PkgIterator Pkg);
-      virtual bool IsImportantDep(DepIterator Dep);
+      virtual VerIterator GetCandidateVer(PkgIterator const &Pkg);
+      virtual bool IsImportantDep(DepIterator const &Dep);
       
       virtual ~Policy() {};
    };
@@ -344,7 +334,7 @@ class pkgDepCache : protected pkgCache::Namespace
    inline pkgVersioningSystem &VS() {return *Cache->VS;};
    
    // Policy implementation
-   inline VerIterator GetCandidateVer(PkgIterator Pkg) {return LocalPolicy->GetCandidateVer(Pkg);};
+   inline VerIterator GetCandidateVer(PkgIterator const &Pkg) {return LocalPolicy->GetCandidateVer(Pkg);};
    inline bool IsImportantDep(DepIterator Dep) {return LocalPolicy->IsImportantDep(Dep);};
    inline Policy &GetPolicy() {return *LocalPolicy;};
    
@@ -405,7 +395,7 @@ class pkgDepCache : protected pkgCache::Namespace
 		    bool ForceImportantDeps = false);
 
    void SetReInstall(PkgIterator const &Pkg,bool To);
-   void SetCandidateVersion(VerIterator TargetVer);
+   void SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo = true);
 
    /** Set the "is automatically installed" flag of Pkg. */
    void MarkAuto(const PkgIterator &Pkg, bool Auto);

+ 5 - 0
apt-pkg/init.cc

@@ -78,6 +78,11 @@ bool pkgInitConfig(Configuration &Cnf)
    Cnf.Set("Dir::Log::Terminal","term.log");
    Cnf.Set("Dir::Log::History","history.log");
 
+   Cnf.Set("Dir::Ignore-Files-Silently::", "~$");
+   Cnf.Set("Dir::Ignore-Files-Silently::", "\\.disabled$");
+   Cnf.Set("Dir::Ignore-Files-Silently::", "\\.bak$");
+   Cnf.Set("Dir::Ignore-Files-Silently::", "\\.dpkg-[a-z]+$");
+
    // Translation
    Cnf.Set("APT::Acquire::Translation", "environment");
 

+ 2 - 3
apt-pkg/makefile

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

+ 2 - 1
apt-pkg/orderlist.cc

@@ -117,7 +117,8 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
       return false;
 
    // Skip Packages that need configure only.
-   if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && 
+   if ((Pkg.State() == pkgCache::PkgIterator::NeedsConfigure ||
+        Pkg.State() == pkgCache::PkgIterator::NeedsNothing) &&
        Cache[Pkg].Keep() == true)
       return false;
 

+ 2 - 1
apt-pkg/packagemanager.cc

@@ -602,7 +602,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
       // configured we don't need to unpack it again…
       PkgIterator const P = Pkg.Group().FindPkg("all");
       if (List->IsFlag(P,pkgOrderList::UnPacked) != true &&
-	  List->IsFlag(P,pkgOrderList::Configured) != true) {
+	  List->IsFlag(P,pkgOrderList::Configured) != true &&
+	  P.State() != pkgCache::PkgIterator::NeedsNothing) {
 	 if (SmartUnPack(P) == false)
 	    return false;
       }

+ 10 - 7
apt-pkg/pkgcache.cc

@@ -119,7 +119,7 @@ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
 // Cache::ReMap - Reopen the cache file					/*{{{*/
 // ---------------------------------------------------------------------
 /* If the file is already closed then this will open it open it. */
-bool pkgCache::ReMap()
+bool pkgCache::ReMap(bool const &Errorchecks)
 {
    // Apply the typecasts.
    HeaderP = (Header *)Map.Data();
@@ -135,6 +135,9 @@ bool pkgCache::ReMap()
    StringItemP = (StringItem *)Map.Data();
    StrP = (char *)Map.Data();
 
+   if (Errorchecks == false)
+      return true;
+
    if (Map.Size() == 0 || HeaderP == 0)
       return _error->Error(_("Empty package cache"));
    
@@ -307,7 +310,7 @@ const char *pkgCache::Priority(unsigned char Prio)
 // GrpIterator::FindPkg - Locate a package by arch			/*{{{*/
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
 	if (unlikely(IsGood() == false || S->FirstPackage == 0))
 		return PkgIterator(*Owner, 0);
 
@@ -346,7 +349,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
 // GrpIterator::FindPreferredPkg - Locate the "best" package		/*{{{*/
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() {
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() const {
 	pkgCache::PkgIterator Pkg = FindPkg("native");
 	if (Pkg.end() == false)
 		return Pkg;
@@ -367,7 +370,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() {
 /* Returns an End-Pointer on error, pointer to the package otherwise.
    We can't simply ++ to the next as the next package of the last will
    be from a different group (with the same hash value) */
-pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) {
+pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const {
 	if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
 	    LastPkg.end() == true))
 		return PkgIterator(*Owner, 0);
@@ -504,7 +507,7 @@ std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const
 // ---------------------------------------------------------------------
 /* Currently critical deps are defined as depends, predepends and
    conflicts (including dpkg's Breaks fields). */
-bool pkgCache::DepIterator::IsCritical()
+bool pkgCache::DepIterator::IsCritical() const
 {
    if (S->Type == pkgCache::Dep::Conflicts ||
        S->Type == pkgCache::Dep::DpkgBreaks ||
@@ -528,7 +531,7 @@ bool pkgCache::DepIterator::IsCritical()
    In Conjunction with the DepCache the value of Result may not be 
    super-good since the policy may have made it uninstallable. Using
    AllTargets is better in this case. */
-bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
+bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const
 {
    Result = TargetPkg();
    
@@ -577,7 +580,7 @@ bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
    provides. It includes every possible package-version that could satisfy
    the dependency. The last item in the list has a 0. The resulting pointer
    must be delete [] 'd */
-pkgCache::Version **pkgCache::DepIterator::AllTargets()
+pkgCache::Version **pkgCache::DepIterator::AllTargets() const
 {
    Version **Res = 0;
    unsigned long Size =0;

+ 1 - 1
apt-pkg/pkgcache.h

@@ -174,7 +174,7 @@ class pkgCache								/*{{{*/
    StringItem *StringItemP;
    char *StrP;
 
-   virtual bool ReMap();
+   virtual bool ReMap(bool const &Errorchecks = true);
    inline bool Sync() {return Map.Sync();};
    inline MMap &GetMap() {return Map;};
    inline void *DataEnd() {return ((unsigned char *)Map.Data()) + Map.Size();};

+ 184 - 62
apt-pkg/pkgcachegen.cc

@@ -36,6 +36,7 @@
 #include <stdio.h>
 									/*}}}*/
 typedef vector<pkgIndexFile *>::iterator FileIterator;
+template <typename Iter> std::set<Iter*> pkgCacheGenerator::Dynamic<Iter>::toReMap;
 
 // CacheGenerator::pkgCacheGenerator - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
@@ -61,8 +62,12 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
 
       // Starting header
       *Cache.HeaderP = pkgCache::Header();
-      Cache.HeaderP->VerSysName = Map.WriteString(_system->VS->Label);
-      Cache.HeaderP->Architecture = Map.WriteString(_config->Find("APT::Architecture"));
+      map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
+      Cache.HeaderP->VerSysName = idxVerSysName;
+      map_ptrloc const idxArchitecture = WriteStringInMap(_config->Find("APT::Architecture"));
+      Cache.HeaderP->Architecture = idxArchitecture;
+      if (unlikely(idxVerSysName == 0 || idxArchitecture == 0))
+	 return;
       Cache.ReMap();
    }
    else
@@ -96,6 +101,67 @@ pkgCacheGenerator::~pkgCacheGenerator()
    Map.Sync(0,sizeof(pkgCache::Header));
 }
 									/*}}}*/
+void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap) {/*{{{*/
+   if (oldMap == newMap)
+      return;
+
+   Cache.ReMap(false);
+
+   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
+
+   for (size_t i = 0; i < _count(UniqHash); ++i)
+      if (UniqHash[i] != 0)
+	 UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
+
+   for (std::set<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i)
+      (*i)->ReOwn(Cache, oldMap, newMap);
+   for (std::set<pkgCache::PkgIterator*>::const_iterator i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
+      (*i)->ReOwn(Cache, oldMap, newMap);
+   for (std::set<pkgCache::VerIterator*>::const_iterator i = Dynamic<pkgCache::VerIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::VerIterator>::toReMap.end(); ++i)
+      (*i)->ReOwn(Cache, oldMap, newMap);
+   for (std::set<pkgCache::DepIterator*>::const_iterator i = Dynamic<pkgCache::DepIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::DepIterator>::toReMap.end(); ++i)
+      (*i)->ReOwn(Cache, oldMap, newMap);
+   for (std::set<pkgCache::DescIterator*>::const_iterator i = Dynamic<pkgCache::DescIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::DescIterator>::toReMap.end(); ++i)
+      (*i)->ReOwn(Cache, oldMap, newMap);
+   for (std::set<pkgCache::PrvIterator*>::const_iterator i = Dynamic<pkgCache::PrvIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::PrvIterator>::toReMap.end(); ++i)
+      (*i)->ReOwn(Cache, oldMap, newMap);
+   for (std::set<pkgCache::PkgFileIterator*>::const_iterator i = Dynamic<pkgCache::PkgFileIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::PkgFileIterator>::toReMap.end(); ++i)
+      (*i)->ReOwn(Cache, oldMap, newMap);
+}									/*}}}*/
+// CacheGenerator::WriteStringInMap					/*{{{*/
+map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String,
+					const unsigned long &Len) {
+   void const * const oldMap = Map.Data();
+   map_ptrloc const index = Map.WriteString(String, Len);
+   if (index != 0)
+      ReMap(oldMap, Map.Data());
+   return index;
+}
+									/*}}}*/
+// CacheGenerator::WriteStringInMap					/*{{{*/
+map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String) {
+   void const * const oldMap = Map.Data();
+   map_ptrloc const index = Map.WriteString(String);
+   if (index != 0)
+      ReMap(oldMap, Map.Data());
+   return index;
+}
+									/*}}}*/
+map_ptrloc pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
+   void const * const oldMap = Map.Data();
+   map_ptrloc const index = Map.Allocate(size);
+   if (index != 0)
+      ReMap(oldMap, Map.Data());
+   return index;
+}
+									/*}}}*/
 // CacheGenerator::MergeList - Merge the package list			/*{{{*/
 // ---------------------------------------------------------------------
 /* This provides the generation of the entries in the cache. Each loop
@@ -127,6 +193,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       {
       // Get a pointer to the package structure
       pkgCache::PkgIterator Pkg;
+      Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
       if (NewPackage(Pkg, PackageName, *arch) == false)
 	 return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str());
       Counter++;
@@ -142,18 +209,20 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 	 // we first process the package, then the descriptions
 	 // (this has the bonus that we get MMap error when we run out
 	 //  of MMap space)
-	 if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
+	 pkgCache::VerIterator Ver(Cache);
+	 Dynamic<pkgCache::VerIterator> DynVer(Ver);
+	 if (List.UsePackage(Pkg, Ver) == false)
 	    return _error->Error(_("Error occurred while processing %s (UsePackage1)"),
 				 PackageName.c_str());
 
  	 // Find the right version to write the description
  	 MD5SumValue CurMd5 = List.Description_md5();
- 	 pkgCache::VerIterator Ver = Pkg.VersionList();
- 	 map_ptrloc *LastVer = &Pkg->VersionList;
+ 	 Ver = Pkg.VersionList();
 
-	 for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
+	 for (; Ver.end() == false; ++Ver)
  	 {
  	    pkgCache::DescIterator Desc = Ver.DescriptionList();
+	    Dynamic<pkgCache::DescIterator> DynDesc(Desc);
  	    map_ptrloc *LastDesc = &Ver->DescriptionList;
 	    bool duplicate=false;
 
@@ -173,7 +242,11 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
  	       if (MD5SumValue(Desc.md5()) == CurMd5) 
                {
  		  // Add new description
- 		  *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
+		  void const * const oldMap = Map.Data();
+		  map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
+		  if (oldMap != Map.Data())
+		     LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+		  *LastDesc = descindex;
  		  Desc->ParentPkg = Pkg.Index();
 		  
 		  if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
@@ -187,7 +260,9 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       }
 
       pkgCache::VerIterator Ver = Pkg.VersionList();
+      Dynamic<pkgCache::VerIterator> DynVer(Ver);
       map_ptrloc *LastVer = &Pkg->VersionList;
+      void const * oldMap = Map.Data();
       int Res = 1;
       unsigned long const Hash = List.VersionHash();
       for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
@@ -226,21 +301,28 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       }
 
       // Add a new version
-      *LastVer = NewVersion(Ver,Version,*LastVer);
+      map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer);
+      if (verindex == 0 && _error->PendingError())
+	 return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
+			      PackageName.c_str(), 1);
+
+      if (oldMap != Map.Data())
+	 LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+      *LastVer = verindex;
       Ver->ParentPkg = Pkg.Index();
       Ver->Hash = Hash;
 
-      if ((*LastVer == 0 && _error->PendingError()) || List.NewVersion(Ver) == false)
-	 return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
-			      PackageName.c_str());
+      if (List.NewVersion(Ver) == false)
+	 return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
+			      PackageName.c_str(), 2);
 
       if (List.UsePackage(Pkg,Ver) == false)
 	 return _error->Error(_("Error occurred while processing %s (UsePackage3)"),
 			      PackageName.c_str());
       
       if (NewFileVer(Ver,List) == false)
-	 return _error->Error(_("Error occurred while processing %s (NewVersion2)"),
-			      PackageName.c_str());
+	 return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
+			      PackageName.c_str(), 3);
 
       // Read only a single record and return
       if (OutVer != 0)
@@ -253,13 +335,18 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       /* Record the Description data. Description data always exist in
 	 Packages and Translation-* files. */
       pkgCache::DescIterator Desc = Ver.DescriptionList();
+      Dynamic<pkgCache::DescIterator> DynDesc(Desc);
       map_ptrloc *LastDesc = &Ver->DescriptionList;
-      
+
       // Skip to the end of description set
       for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++);
 
       // Add new description
-      *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
+      oldMap = Map.Data();
+      map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
+      if (oldMap != Map.Data())
+	 LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+      *LastDesc = descindex;
       Desc->ParentPkg = Pkg.Index();
 
       if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
@@ -306,6 +393,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List)
 	 continue;
       
       pkgCache::PkgIterator Pkg = Cache.FindPkg(PackageName);
+      Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
       if (Pkg.end() == true)
 	 return _error->Error(_("Error occurred while processing %s (FindPkg)"),
 				PackageName.c_str());
@@ -315,6 +403,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List)
 
       unsigned long Hash = List.VersionHash();
       pkgCache::VerIterator Ver = Pkg.VersionList();
+      Dynamic<pkgCache::VerIterator> DynVer(Ver);
       for (; Ver.end() == false; Ver++)
       {
 	 if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr())
@@ -342,14 +431,15 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
       return true;
 
    // Get a structure
-   unsigned long const Group = Map.Allocate(sizeof(pkgCache::Group));
+   map_ptrloc const Group = AllocateInMap(sizeof(pkgCache::Group));
    if (unlikely(Group == 0))
       return false;
 
    Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
-   Grp->Name = Map.WriteString(Name);
-   if (unlikely(Grp->Name == 0))
+   map_ptrloc const idxName = WriteStringInMap(Name);
+   if (unlikely(idxName == 0))
       return false;
+   Grp->Name = idxName;
 
    // Insert it into the hash table
    unsigned long const Hash = Cache.Hash(Name);
@@ -366,6 +456,7 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name,
 					const string &Arch) {
    pkgCache::GrpIterator Grp;
+   Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
    if (unlikely(NewGroup(Grp, Name) == false))
       return false;
 
@@ -374,7 +465,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
 	 return true;
 
    // Get a structure
-   unsigned long const Package = Map.Allocate(sizeof(pkgCache::Package));
+   map_ptrloc const Package = AllocateInMap(sizeof(pkgCache::Package));
    if (unlikely(Package == 0))
       return false;
    Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
@@ -400,9 +491,10 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
    // Set the name, arch and the ID
    Pkg->Name = Grp->Name;
    Pkg->Group = Grp.Index();
-   Pkg->Arch = WriteUniqString(Arch.c_str());
-   if (unlikely(Pkg->Arch == 0))
+   map_ptrloc const idxArch = WriteUniqString(Arch.c_str());
+   if (unlikely(idxArch == 0))
       return false;
+   Pkg->Arch = idxArch;
    Pkg->ID = Cache.HeaderP->PackageCount++;
 
    return true;
@@ -418,7 +510,7 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
       return true;
    
    // Get a structure
-   unsigned long VerFile = Map.Allocate(sizeof(pkgCache::VerFile));
+   map_ptrloc const VerFile = AllocateInMap(sizeof(pkgCache::VerFile));
    if (VerFile == 0)
       return 0;
    
@@ -449,7 +541,7 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
 					    unsigned long Next)
 {
    // Get a structure
-   unsigned long Version = Map.Allocate(sizeof(pkgCache::Version));
+   map_ptrloc const Version = AllocateInMap(sizeof(pkgCache::Version));
    if (Version == 0)
       return 0;
    
@@ -457,9 +549,10 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
    Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
    Ver->NextVer = Next;
    Ver->ID = Cache.HeaderP->VersionCount++;
-   Ver->VerStr = Map.WriteString(VerStr);
-   if (Ver->VerStr == 0)
+   map_ptrloc const idxVerStr = WriteStringInMap(VerStr);
+   if (unlikely(idxVerStr == 0))
       return 0;
+   Ver->VerStr = idxVerStr;
    
    return Version;
 }
@@ -474,7 +567,7 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
       return true;
    
    // Get a structure
-   unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
+   map_ptrloc const DescFile = AllocateInMap(sizeof(pkgCache::DescFile));
    if (DescFile == 0)
       return false;
 
@@ -507,7 +600,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
 					    map_ptrloc Next)
 {
    // Get a structure
-   map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description));
+   map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description));
    if (Description == 0)
       return 0;
 
@@ -515,10 +608,12 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
    Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
    Desc->NextDesc = Next;
    Desc->ID = Cache.HeaderP->DescriptionCount++;
-   Desc->language_code = Map.WriteString(Lang);
-   Desc->md5sum = Map.WriteString(md5sum.Value());
-   if (Desc->language_code == 0 || Desc->md5sum == 0)
+   map_ptrloc const idxlanguage_code = WriteStringInMap(Lang);
+   map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value());
+   if (unlikely(idxlanguage_code == 0 || idxmd5sum == 0))
       return 0;
+   Desc->language_code = idxlanguage_code;
+   Desc->md5sum = idxmd5sum;
 
    return Description;
 }
@@ -534,15 +629,22 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
    if (archs.size() > 1)
    {
       // Create Conflicts in between the group
-      for (pkgCache::GrpIterator G = GetCache().GrpBegin(); G.end() != true; G++)
+      pkgCache::GrpIterator G = GetCache().GrpBegin();
+      Dynamic<pkgCache::GrpIterator> DynG(G);
+      for (; G.end() != true; G++)
       {
 	 string const PkgName = G.Name();
-	 for (pkgCache::PkgIterator P = G.PackageList(); P.end() != true; P = G.NextPkg(P))
+	 pkgCache::PkgIterator P = G.PackageList();
+	 Dynamic<pkgCache::PkgIterator> DynP(P);
+	 for (; P.end() != true; P = G.NextPkg(P))
 	 {
 	    if (strcmp(P.Arch(),"all") == 0)
 	       continue;
 	    pkgCache::PkgIterator allPkg;
-	    for (pkgCache::VerIterator V = P.VersionList(); V.end() != true; V++)
+	    Dynamic<pkgCache::PkgIterator> DynallPkg(allPkg);
+	    pkgCache::VerIterator V = P.VersionList();
+	    Dynamic<pkgCache::VerIterator> DynV(V);
+	    for (; V.end() != true; V++)
 	    {
 	       string const Arch = V.Arch(true);
 	       map_ptrloc *OldDepLast = NULL;
@@ -562,6 +664,7 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
 		     per group, therefore each group member conflicts
 		     with all other group members */
 		  pkgCache::PkgIterator D = G.FindPkg(*A);
+		  Dynamic<pkgCache::PkgIterator> DynD(D);
 		  if (D.end() == true)
 		     continue;
 		  if (coInstall == true)
@@ -572,10 +675,7 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
 				OldDepLast);
 		     // Breaks: ${self}:other (!= ${binary:Version})
 		     NewDepends(D, V, V.VerStr(),
-				pkgCache::Dep::Less, pkgCache::Dep::DpkgBreaks,
-				OldDepLast);
-		     NewDepends(D, V, V.VerStr(),
-				pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks,
+				pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
 				OldDepLast);
 		     if (V->MultiArch == pkgCache::Version::All)
 		     {
@@ -609,13 +709,15 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 				   unsigned int const &Type,
 				   map_ptrloc *OldDepLast)
 {
+   void const * const oldMap = Map.Data();
    // Get a structure
-   unsigned long const Dependency = Map.Allocate(sizeof(pkgCache::Dependency));
+   map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
    if (unlikely(Dependency == 0))
       return false;
    
    // Fill it in
    pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
+   Dynamic<pkgCache::DepIterator> DynDep(Dep);
    Dep->ParentVer = Ver.Index();
    Dep->Type = Type;
    Dep->CompareOp = Op;
@@ -627,9 +729,12 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 /*      for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
 	 if (I->Version != 0 && I.TargetVer() == Version)
 	    Dep->Version = I->Version;*/
-      if (Dep->Version == 0)
-	 if (unlikely((Dep->Version = Map.WriteString(Version)) == 0))
+      if (Dep->Version == 0) {
+	 map_ptrloc const index = WriteStringInMap(Version);
+	 if (unlikely(index == 0))
 	    return false;
+	 Dep->Version = index;
+      }
    }
 
    // Link it to the package
@@ -643,7 +748,8 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
       OldDepLast = &Ver->DependsList;
       for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
 	 OldDepLast = &D->NextDepends;
-   }
+   } else if (oldMap != Map.Data())
+      OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
 
    Dep->NextDepends = *OldDepLast;
    *OldDepLast = Dep.Index();
@@ -656,7 +762,7 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 // ---------------------------------------------------------------------
 /* This creates a Group and the Package to link this dependency to if
    needed and handles also the caching of the old endpoint */
-bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
+bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 					       const string &PackageName,
 					       const string &Arch,
 					       const string &Version,
@@ -664,11 +770,13 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
 					       unsigned int Type)
 {
    pkgCache::GrpIterator Grp;
+   Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
    if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
       return false;
 
    // Locate the target package
    pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch);
+   Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
    if (Pkg.end() == true) {
       if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
 	 return false;
@@ -690,7 +798,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
 // ListParser::NewProvides - Create a Provides element			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
+bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
 					        const string &PkgName,
 						const string &PkgArch,
 						const string &Version)
@@ -702,13 +810,14 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
       return true;
    
    // Get a structure
-   unsigned long const Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
+   map_ptrloc const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides));
    if (unlikely(Provides == 0))
       return false;
    Cache.HeaderP->ProvidesCount++;
    
    // Fill it in
    pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
+   Dynamic<pkgCache::PrvIterator> DynPrv(Prv);
    Prv->Version = Ver.Index();
    Prv->NextPkgProv = Ver->ProvidesList;
    Ver->ProvidesList = Prv.Index();
@@ -717,6 +826,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
    
    // Locate the target package
    pkgCache::PkgIterator Pkg;
+   Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
    if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false))
       return false;
    
@@ -737,24 +847,29 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
 				   unsigned long Flags)
 {
    // Get some space for the structure
-   CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile));
-   if (CurrentFile == Cache.PkgFileP)
+   map_ptrloc const idxFile = AllocateInMap(sizeof(*CurrentFile));
+   if (unlikely(idxFile == 0))
       return false;
-   
+   CurrentFile = Cache.PkgFileP + idxFile;
+
    // Fill it in
-   CurrentFile->FileName = Map.WriteString(File);
-   CurrentFile->Site = WriteUniqString(Site);
+   map_ptrloc const idxFileName = WriteStringInMap(File);
+   map_ptrloc const idxSite = WriteUniqString(Site);
+   if (unlikely(idxFileName == 0 || idxSite == 0))
+      return false;
+   CurrentFile->FileName = idxFileName;
+   CurrentFile->Site = idxSite;
    CurrentFile->NextFile = Cache.HeaderP->FileList;
    CurrentFile->Flags = Flags;
    CurrentFile->ID = Cache.HeaderP->PackageFileCount;
-   CurrentFile->IndexType = WriteUniqString(Index.GetType()->Label);
+   map_ptrloc const idxIndexType = WriteUniqString(Index.GetType()->Label);
+   if (unlikely(idxIndexType == 0))
+      return false;
+   CurrentFile->IndexType = idxIndexType;
    PkgFileName = File;
    Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
    Cache.HeaderP->PackageFileCount++;
 
-   if (CurrentFile->FileName == 0)
-      return false;
-   
    if (Progress != 0)
       Progress->SubProgress(Index.Size());
    return true;
@@ -794,18 +909,25 @@ unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
    }
    
    // Get a structure
-   unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
+   void const * const oldMap = Map.Data();
+   map_ptrloc const Item = AllocateInMap(sizeof(pkgCache::StringItem));
    if (Item == 0)
       return 0;
 
+   map_ptrloc const idxString = WriteStringInMap(S,Size);
+   if (unlikely(idxString == 0))
+      return 0;
+   if (oldMap != Map.Data()) {
+      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
+   }
+   *Last = Item;
+
    // Fill in the structure
    pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
    ItemP->NextItem = I - Cache.StringItemP;
-   *Last = Item;
-   ItemP->String = Map.WriteString(S,Size);
-   if (ItemP->String == 0)
-      return 0;
-   
+   ItemP->String = idxString;
+
    Bucket = ItemP;
    return ItemP->String;
 }
@@ -1059,7 +1181,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
       unlink(CacheFile.c_str());
       CacheF = new FileFd(CacheFile,FileFd::WriteEmpty);
       fchmod(CacheF->Fd(),0644);
-      Map = new DynamicMMap(*CacheF,MMap::Public,MapSize);
+      Map = new DynamicMMap(*CacheF,MMap::Public | MMap::Moveable, MapSize);
       if (_error->PendingError() == true)
 	 return false;
       if (Debug == true)
@@ -1068,7 +1190,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
    else
    {
       // Just build it in memory..
-      Map = new DynamicMMap(0,MapSize);
+      Map = new DynamicMMap(MMap::Moveable, MapSize);
       if (Debug == true)
 	 std::clog << "Open memory Map (not filebased)" << std::endl;
    }
@@ -1181,7 +1303,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O
    if (_system->AddStatusFiles(Files) == false)
       return false;
    
-   SPtr<DynamicMMap> Map = new DynamicMMap(0,MapSize);
+   SPtr<DynamicMMap> Map = new DynamicMMap(MMap::Moveable, MapSize);
    unsigned long CurrentSize = 0;
    unsigned long TotalSize = 0;
    

+ 34 - 12
apt-pkg/pkgcachegen.h

@@ -23,6 +23,8 @@
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/md5.h>
 
+#include <set>
+
 class pkgSourceList;
 class OpProgress;
 class MMap;
@@ -31,16 +33,34 @@ class pkgIndexFile;
 class pkgCacheGenerator							/*{{{*/
 {
    private:
-   
+
    pkgCache::StringItem *UniqHash[26];
-   
+   map_ptrloc WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); };
+   map_ptrloc WriteStringInMap(const char *String);
+   map_ptrloc WriteStringInMap(const char *String, const unsigned long &Len);
+   map_ptrloc AllocateInMap(const unsigned long &size);
+
    public:
    
    class ListParser;
    friend class ListParser;
-   
+
+   template<typename Iter> class Dynamic {
+      Iter *I;
+
+      public:
+      static std::set<Iter*> toReMap;
+      Dynamic(Iter &It) : I(&It) {
+	 toReMap.insert(I);
+      }
+
+      ~Dynamic() {
+	 toReMap.erase(I);
+      }
+   };
+
    protected:
-   
+
    DynamicMMap &Map;
    pkgCache Cache;
    OpProgress *Progress;
@@ -82,6 +102,8 @@ class pkgCacheGenerator							/*{{{*/
 			MMap **OutMap = 0,bool AllowMem = false);
    static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap);
 
+   void ReMap(void const * const oldMap, void const * const newMap);
+
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
    ~pkgCacheGenerator();
 };
@@ -103,12 +125,12 @@ class pkgCacheGenerator::ListParser
 
    inline unsigned long WriteUniqString(string S) {return Owner->WriteUniqString(S);};
    inline unsigned long WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);};
-   inline unsigned long WriteString(const string &S) {return Owner->Map.WriteString(S);};
-   inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->Map.WriteString(S,Size);};
-   bool NewDepends(pkgCache::VerIterator Ver,const string &Package, const string &Arch,
+   inline unsigned long WriteString(const string &S) {return Owner->WriteStringInMap(S);};
+   inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);};
+   bool NewDepends(pkgCache::VerIterator &Ver,const string &Package, const string &Arch,
 		   const string &Version,unsigned int Op,
 		   unsigned int Type);
-   bool NewProvides(pkgCache::VerIterator Ver,const string &PkgName,
+   bool NewProvides(pkgCache::VerIterator &Ver,const string &PkgName,
 		    const string &PkgArch, const string &Version);
    
    public:
@@ -118,13 +140,13 @@ class pkgCacheGenerator::ListParser
    virtual string Architecture() = 0;
    virtual bool ArchitectureAll() = 0;
    virtual string Version() = 0;
-   virtual bool NewVersion(pkgCache::VerIterator Ver) = 0;
+   virtual bool NewVersion(pkgCache::VerIterator &Ver) = 0;
    virtual string Description() = 0;
    virtual string DescriptionLanguage() = 0;
    virtual MD5SumValue Description_md5() = 0;
    virtual unsigned short VersionHash() = 0;
-   virtual bool UsePackage(pkgCache::PkgIterator Pkg,
-			   pkgCache::VerIterator Ver) = 0;
+   virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
+			   pkgCache::VerIterator &Ver) = 0;
    virtual unsigned long Offset() = 0;
    virtual unsigned long Size() = 0;
    
@@ -132,7 +154,7 @@ class pkgCacheGenerator::ListParser
    
    inline bool HasFileDeps() {return FoundFileDeps;};
    virtual bool CollectFileProvides(pkgCache &Cache,
-				    pkgCache::VerIterator Ver) {return true;};
+				    pkgCache::VerIterator &Ver) {return true;};
 
    ListParser() : FoundFileDeps(false) {};
    virtual ~ListParser() {};

+ 1 - 1
apt-pkg/policy.h

@@ -76,7 +76,7 @@ class pkgPolicy : public pkgDepCache::Policy
 
    // Things for the cache interface.
    virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg);
-   virtual bool IsImportantDep(pkgCache::DepIterator Dep) {return pkgDepCache::Policy::IsImportantDep(Dep);};
+   virtual bool IsImportantDep(pkgCache::DepIterator const &Dep) {return pkgDepCache::Policy::IsImportantDep(Dep);};
    bool InitDefaults();
    
    pkgPolicy(pkgCache *Owner);

+ 11 - 10
cmdline/apt-cache.cc

@@ -29,7 +29,8 @@
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/sptr.h>
-#include <apt-pkg/cacheset.h>
+
+#include "cacheset.h"
 
 #include <config.h>
 #include <apti18n.h>
@@ -1867,21 +1868,21 @@ int main(int argc,const char *argv[])					/*{{{*/
    }
    
    // Deal with stdout not being a tty
-   if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
 
-//       if (_config->FindB("APT::Cache::Generate",true) == false)
+   if (_config->Exists("APT::Cache::Generate") == true)
+      _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
+
    if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
       CmdL.DispatchArg(CmdsB);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-          
-   return 0;
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
 									/*}}}*/

+ 6 - 8
cmdline/apt-cdrom.cc

@@ -266,20 +266,18 @@ int main(int argc,const char *argv[])					/*{{{*/
       return ShowHelp();
 
    // Deal with stdout not being a tty
-   if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
    
    // Match the operation
    CmdL.DispatchArg(Cmds);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-   
-   return 0;
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
 									/*}}}*/

+ 322 - 387
cmdline/apt-get.cc

@@ -40,12 +40,12 @@
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
-#include <apt-pkg/cacheset.h>
 
 #include <config.h>
 #include <apti18n.h>
 
 #include "acqprogress.h"
+#include "cacheset.h"
 
 #include <set>
 #include <locale.h>
@@ -609,6 +609,253 @@ void Stats(ostream &out,pkgDepCache &Dep)
 	       Dep.BadCount());
 }
 									/*}}}*/
+// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
+class CacheSetHelperAPTGet : public APT::CacheSetHelper {
+	/** \brief stream message should be printed to */
+	std::ostream &out;
+	/** \brief were things like Task or RegEx used to select packages? */
+	bool explicitlyNamed;
+
+	APT::PackageSet virtualPkgs;
+
+public:
+	CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
+		explicitlyNamed = true;
+	}
+
+	virtual void showTaskSelection(APT::PackageSet const &pkgset, string const &pattern) {
+		for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+			ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
+				 Pkg.FullName(true).c_str(), pattern.c_str());
+		explicitlyNamed = false;
+	}
+	virtual void showRegExSelection(APT::PackageSet const &pkgset, string const &pattern) {
+		for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+			ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
+				 Pkg.FullName(true).c_str(), pattern.c_str());
+		explicitlyNamed = false;
+	}
+	virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+				 string const &ver, bool const &verIsRel) {
+		if (ver != Ver.VerStr())
+			ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+				 Ver.VerStr(), Ver.RelStr().c_str(), Pkg.FullName(true).c_str());
+	}
+
+	bool showVirtualPackageErrors(pkgCacheFile &Cache) {
+		if (virtualPkgs.empty() == true)
+			return true;
+		for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin();
+		     Pkg != virtualPkgs.end(); ++Pkg) {
+			if (Pkg->ProvidesList != 0) {
+				ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
+					 Pkg.FullName(true).c_str());
+
+				pkgCache::PrvIterator I = Pkg.ProvidesList();
+				unsigned short provider = 0;
+				for (; I.end() == false; ++I) {
+					pkgCache::PkgIterator Pkg = I.OwnerPkg();
+
+					if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) {
+						out << "  " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
+						if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
+							out << _(" [Installed]");
+						out << endl;
+						++provider;
+					}
+				}
+				// if we found no candidate which provide this package, show non-candidates
+				if (provider == 0)
+					for (I = Pkg.ProvidesList(); I.end() == false; I++)
+						out << "  " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
+						    << _(" [Not candidate version]") << endl;
+				else
+					out << _("You should explicitly select one to install.") << endl;
+			} else {
+				ioprintf(out,
+					_("Package %s is not available, but is referred to by another package.\n"
+					  "This may mean that the package is missing, has been obsoleted, or\n"
+					  "is only available from another source\n"),Pkg.FullName(true).c_str());
+
+				string List;
+				string VersionsList;
+				SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount];
+				memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen));
+				for (pkgCache::DepIterator Dep = Pkg.RevDependsList();
+				     Dep.end() == false; Dep++) {
+					if (Dep->Type != pkgCache::Dep::Replaces)
+						continue;
+					if (Seen[Dep.ParentPkg()->ID] == true)
+						continue;
+					Seen[Dep.ParentPkg()->ID] = true;
+					List += Dep.ParentPkg().FullName(true) + " ";
+					//VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
+				}
+				ShowList(out,_("However the following packages replace it:"),List,VersionsList);
+			}
+			out << std::endl;
+		}
+		return false;
+	}
+
+	virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+		APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE);
+		if (verset.empty() == false)
+			return *(verset.begin());
+		if (ShowError == true) {
+			_error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str());
+			virtualPkgs.insert(Pkg);
+		}
+		return pkgCache::VerIterator(Cache, 0);
+	}
+
+	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+		APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
+		if (verset.empty() == false)
+			return *(verset.begin());
+		if (ShowError == true)
+			ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+		return pkgCache::VerIterator(Cache, 0);
+	}
+
+	APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
+						APT::VersionSet::Version const &select) {
+		/* This is a pure virtual package and there is a single available
+		   candidate providing it. */
+		if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
+			return APT::VersionSet();
+
+		pkgCache::PkgIterator Prov;
+		bool found_one = false;
+		for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
+			pkgCache::VerIterator const PVer = P.OwnerVer();
+			pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
+
+			/* Ignore versions that are not a candidate. */
+			if (Cache[PPkg].CandidateVer != PVer)
+				continue;
+
+			if (found_one == false) {
+				Prov = PPkg;
+				found_one = true;
+			} else if (PPkg != Prov) {
+				found_one = false; // we found at least two
+				break;
+			}
+		}
+
+		if (found_one == true) {
+			ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
+				 Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
+			return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
+		}
+		return APT::VersionSet();
+	}
+
+	inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
+
+};
+									/*}}}*/
+// TryToInstall - Mark a package for installation			/*{{{*/
+struct TryToInstall {
+   pkgCacheFile* Cache;
+   pkgProblemResolver* Fix;
+   bool FixBroken;
+   unsigned long AutoMarkChanged;
+   APT::PackageSet doAutoInstallLater;
+
+   TryToInstall(pkgCacheFile &Cache, pkgProblemResolver &PM, bool const &FixBroken) : Cache(&Cache), Fix(&PM),
+			FixBroken(FixBroken), AutoMarkChanged(0) {};
+
+   void operator() (pkgCache::VerIterator const &Ver) {
+      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+      Cache->GetDepCache()->SetCandidateVersion(Ver);
+      pkgDepCache::StateCache &State = (*Cache)[Pkg];
+
+      // Handle the no-upgrade case
+      if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
+	 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
+		  Pkg.FullName(true).c_str());
+      // Ignore request for install if package would be new
+      else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
+	 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
+		  Pkg.FullName(true).c_str());
+      else {
+	 Fix->Clear(Pkg);
+	 Fix->Protect(Pkg);
+	 Cache->GetDepCache()->MarkInstall(Pkg,false);
+
+	 if (State.Install() == false) {
+	    if (_config->FindB("APT::Get::ReInstall",false) == true) {
+	       if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
+		  ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
+			   Pkg.FullName(true).c_str());
+	       else
+		  Cache->GetDepCache()->SetReInstall(Pkg, true);
+	    } else
+	       ioprintf(c1out,_("%s is already the newest version.\n"),
+			Pkg.FullName(true).c_str());
+	 }
+
+	 // Install it with autoinstalling enabled (if we not respect the minial
+	 // required deps or the policy)
+	 if (FixBroken == false)
+	    doAutoInstallLater.insert(Pkg);
+      }
+
+      // see if we need to fix the auto-mark flag
+      // e.g. apt-get install foo
+      // where foo is marked automatic
+      if (State.Install() == false &&
+	  (State.Flags & pkgCache::Flag::Auto) &&
+	  _config->FindB("APT::Get::ReInstall",false) == false &&
+	  _config->FindB("APT::Get::Only-Upgrade",false) == false &&
+	  _config->FindB("APT::Get::Download-Only",false) == false)
+      {
+	 ioprintf(c1out,_("%s set to manually installed.\n"),
+		  Pkg.FullName(true).c_str());
+	 Cache->GetDepCache()->MarkAuto(Pkg,false);
+	 AutoMarkChanged++;
+      }
+   }
+
+   void doAutoInstall() {
+      for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
+	   P != doAutoInstallLater.end(); ++P) {
+	 pkgDepCache::StateCache &State = (*Cache)[P];
+	 if (State.InstBroken() == false && State.InstPolicyBroken() == false)
+	    continue;
+	 Cache->GetDepCache()->MarkInstall(P, true);
+      }
+      doAutoInstallLater.clear();
+   }
+};
+									/*}}}*/
+// TryToRemove - Mark a package for removal				/*{{{*/
+struct TryToRemove {
+   pkgCacheFile* Cache;
+   pkgProblemResolver* Fix;
+   bool FixBroken;
+   unsigned long AutoMarkChanged;
+
+   TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM) {};
+
+   void operator() (pkgCache::VerIterator const &Ver)
+   {
+      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+      Fix->Clear(Pkg);
+      Fix->Protect(Pkg);
+      Fix->Remove(Pkg);
+
+      if (Pkg->CurrentVer == 0)
+	 ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+      else
+	 Cache->GetDepCache()->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
+   }
+};
+									/*}}}*/
 // CacheFile::NameComp - QSort compare by name				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1073,219 +1320,35 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    return true;
 }
 									/*}}}*/
-// TryToInstall - Try to install a single package			/*{{{*/
+// TryToInstallBuildDep - Try to install a single package		/*{{{*/
 // ---------------------------------------------------------------------
 /* This used to be inlined in DoInstall, but with the advent of regex package
    name matching it was split out.. */
-bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
+bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache,
 		  pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
-		  unsigned int &ExpectedInst,bool AllowFail = true)
+		  bool AllowFail = true)
 {
-   /* This is a pure virtual package and there is a single available
-      candidate providing it. */
    if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
    {
-      pkgCache::PkgIterator Prov;
-      bool found_one = false;
-
-      for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; P++)
-      {
-	 pkgCache::VerIterator const PVer = P.OwnerVer();
-	 pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
-
-	 /* Ignore versions that are not a candidate. */
-	 if (Cache[PPkg].CandidateVer != PVer)
-	     continue;
-
-	 if (found_one == false)
-	 {
-	    Prov = PPkg;
-	    found_one = true;
-	 }
-	 else if (PPkg != Prov)
-	 {
-	    found_one = false; // we found at least two
-	    break;
-	 }
-      }
-
-      if (found_one == true)
-      {
-	 ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
-		  Prov.FullName(true).c_str(),Pkg.FullName(true).c_str());
-	 Pkg = Prov;
-      }
+      CacheSetHelperAPTGet helper(c1out);
+      helper.showErrors(AllowFail == false);
+      pkgCache::VerIterator Ver = helper.canNotFindNewestVer(Cache, Pkg);
+      if (Ver.end() == false)
+	 Pkg = Ver.ParentPkg();
+      else if (helper.showVirtualPackageErrors(Cache) == false)
+	 return AllowFail;
    }
 
-   // Handle the no-upgrade case
-   if (_config->FindB("APT::Get::upgrade",true) == false &&
-       Pkg->CurrentVer != 0)
-   {
-      if (AllowFail == true)
-	 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
-		  Pkg.FullName(true).c_str());
-      return true;
-   }
-
-   // Ignore request for install if package would be new
-   if (_config->FindB("APT::Get::Only-Upgrade", false) == true &&
-       Pkg->CurrentVer == 0)
-   {
-      if (AllowFail == true)
-	 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
-		  Pkg.Name());
-      return true;
-   }
-
-   // Check if there is something at all to install
-   pkgDepCache::StateCache &State = Cache[Pkg];
-   if (Remove == true && Pkg->CurrentVer == 0)
-   {
-      Fix.Clear(Pkg);
-      Fix.Protect(Pkg);
-      Fix.Remove(Pkg);
-      
-      /* We want to continue searching for regex hits, so we return false here
-         otherwise this is not really an error. */
-      if (AllowFail == false)
-	 return false;
-      
-      ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
-      return true;
-   }
-   
-   if (State.CandidateVer == 0 && Remove == false)
-   {
-      if (AllowFail == false)
-	 return false;
-      
-      if (Pkg->ProvidesList != 0)
-      {
-	 ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
-		  Pkg.FullName(true).c_str());
-	 
-	 pkgCache::PrvIterator I = Pkg.ProvidesList();
-	 unsigned short provider = 0;
-	 for (; I.end() == false; I++)
-	 {
-	    pkgCache::PkgIterator Pkg = I.OwnerPkg();
-	    
-	    if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
-	    {
-	       c1out << "  " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
-	       if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
-		  c1out << _(" [Installed]");
-	       c1out << endl;
-	       ++provider;
-	    }
-	 }
-	 // if we found no candidate which provide this package, show non-candidates
-	 if (provider == 0)
-	    for (I = Pkg.ProvidesList(); I.end() == false; I++)
-	       c1out << "  " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
-		<< _(" [Not candidate version]") << endl;
-	 else
-	    c1out << _("You should explicitly select one to install.") << endl;
-      }
-      else
-      {
-	 ioprintf(c1out,
-	 _("Package %s is not available, but is referred to by another package.\n"
-	   "This may mean that the package is missing, has been obsoleted, or\n"
-           "is only available from another source\n"),Pkg.FullName(true).c_str());
-	 
-	 string List;
-	 string VersionsList;
-	 SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
-	 memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
-	 pkgCache::DepIterator Dep = Pkg.RevDependsList();
-	 for (; Dep.end() == false; Dep++)
-	 {
-	    if (Dep->Type != pkgCache::Dep::Replaces)
-	       continue;
-	    if (Seen[Dep.ParentPkg()->ID] == true)
-	       continue;
-	    Seen[Dep.ParentPkg()->ID] = true;
-	    List += Dep.ParentPkg().FullName(true) + " ";
-        //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
-	 }	    
-	 ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
-      }
-      
-      _error->Error(_("Package %s has no installation candidate"),Pkg.FullName(true).c_str());
-      return false;
-   }
-
-   Fix.Clear(Pkg);
-   Fix.Protect(Pkg);   
    if (Remove == true)
    {
-      Fix.Remove(Pkg);
-      Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
-      return true;
-   }
-   
-   // Install it
-   Cache.MarkInstall(Pkg,false);
-   if (State.Install() == false)
-   {
-      if (_config->FindB("APT::Get::ReInstall",false) == true)
-      {
-	 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
-	    ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
-		     Pkg.FullName(true).c_str());
-	 else
-	    Cache.SetReInstall(Pkg,true);
-      }      
-      else
-      {
-	 if (AllowFail == true)
-	    ioprintf(c1out,_("%s is already the newest version.\n"),
-		     Pkg.FullName(true).c_str());
-      }      
-   }   
-   else
-      ExpectedInst++;
-   
-   // Install it with autoinstalling enabled (if we not respect the minial
-   // required deps or the policy)
-   if ((State.InstBroken() == true || State.InstPolicyBroken() == true) && BrokenFix == false)
-      Cache.MarkInstall(Pkg,true);
-
-   return true;
-}
-									/*}}}*/
-// TryToChangeVer - Try to change a candidate version			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
-		    const char *VerTag,bool IsRel)
-{
-   pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : 
-				 pkgVersionMatch::Version));
-   
-   pkgCache::VerIterator Ver = Match.Find(Pkg);
-			 
-   if (Ver.end() == true)
-   {
-      if (IsRel == true)
-	 return _error->Error(_("Release '%s' for '%s' was not found"),
-			      VerTag,Pkg.FullName(true).c_str());
-      return _error->Error(_("Version '%s' for '%s' was not found"),
-			   VerTag,Pkg.FullName(true).c_str());
-   }
-   
-   if (strcmp(VerTag,Ver.VerStr()) != 0)
-   {
-      ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
-	       Ver.VerStr(),Ver.RelStr().c_str(),Pkg.FullName(true).c_str());
-   }
-   
-   Cache.SetCandidateVersion(Ver);
-
-   // Set the all package to the same candidate
-   if (Ver.Pseudo() == true)
-      Cache.SetCandidateVersion(Match.Find(Pkg.Group().FindPkg("all")));
+      TryToRemove RemoveAction(Cache, Fix);
+      RemoveAction(Pkg.VersionList());
+   } else if (Cache[Pkg].CandidateVer != 0) {
+      TryToInstall InstallAction(Cache, Fix, BrokenFix);
+      InstallAction(Cache[Pkg].CandidateVerIter(Cache));
+      InstallAction.doAutoInstall();
+   } else
+      return AllowFail;
 
    return true;
 }
@@ -1624,61 +1687,6 @@ bool DoUpgrade(CommandLine &CmdL)
    return InstallPackages(Cache,true);
 }
 									/*}}}*/
-// DoInstallTask - Install task from the command line			/*{{{*/
-// ---------------------------------------------------------------------
-/* Install named task */
-bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix, 
-		    bool BrokenFix,
-		    unsigned int& ExpectedInst, 
-		    const char *taskname,
-		    bool Remove)
-{
-   const char *start, *end;
-   pkgCache::PkgIterator Pkg;
-   char buf[64*1024];
-   regex_t Pattern;
-
-   // get the records
-   pkgRecords Recs(Cache);
-
-   // build regexp for the task
-   char S[300];
-   snprintf(S, sizeof(S), "^Task:.*[, ]%s([, ]|$)", taskname);
-   if(regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE) != 0)
-      return _error->Error("Failed to compile task regexp");
-   
-   bool found = false;
-   bool res = true;
-
-   // two runs, first ignore dependencies, second install any missing
-   for(int IgnoreBroken=1; IgnoreBroken >= 0; IgnoreBroken--)
-   {
-      for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-	 pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache);
-	 if(ver.end())
-	    continue;
-	 pkgRecords::Parser &parser = Recs.Lookup(ver.FileList());
-	 parser.GetRec(start,end);
-	 strncpy(buf, start, end-start);
-	 buf[end-start] = 0x0;
-	 if (regexec(&Pattern,buf,0,0,0) != 0)
-	    continue;
-	 res &= TryToInstall(Pkg,Cache,Fix,Remove,IgnoreBroken,ExpectedInst);
-	 found = true;
-      }
-   }
-   
-   // now let the problem resolver deal with any issues
-   Fix.Resolve(true);
-
-   if(!found)
-      _error->Error(_("Couldn't find task %s"),taskname);
-
-   regfree(&Pattern);
-   return res;
-}
-									/*}}}*/
 // DoInstall - Install packages from the command line			/*{{{*/
 // ---------------------------------------------------------------------
 /* Install named packages */
@@ -1694,140 +1702,69 @@ bool DoInstall(CommandLine &CmdL)
    if (Cache->BrokenCount() != 0)
       BrokenFix = true;
    
-   unsigned int AutoMarkChanged = 0;
-   unsigned int ExpectedInst = 0;
-   unsigned int Packages = 0;
    pkgProblemResolver Fix(Cache);
-   
-   bool DefRemove = false;
+
+   static const unsigned short MOD_REMOVE = 1;
+   static const unsigned short MOD_INSTALL = 2;
+
+   unsigned short fallback = MOD_INSTALL;
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
    {
       _config->Set("APT::Get::Purge", true);
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    }
    else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
    {
       _config->Set("APT::Get::AutomaticRemove", "true");
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    }
-   // new scope for the ActionGroup
-   {
-      pkgDepCache::ActionGroup group(Cache);
-      for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-      {
-	 // Duplicate the string
-	 unsigned int Length = strlen(*I);
-	 char S[300];
-	 if (Length >= sizeof(S))
-	    continue;
-	 strcpy(S,*I);
-      
-	 // See if we are removing and special indicators..
-	 bool Remove = DefRemove;
-	 char *VerTag = 0;
-	 bool VerIsRel = false;
 
-         // this is a task!
-         if (Length >= 1 && S[Length - 1] == '^')
-         {
-            S[--Length] = 0;
-            // tasks must always be confirmed
-            ExpectedInst += 1000;
-            // see if we can install it
-            TryInstallTask(Cache, Fix, BrokenFix, ExpectedInst, S, Remove);
-            continue;
-         }
+   std::list<APT::VersionSet::Modifier> mods;
+   mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
+		APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
+   mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
+		APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
+   CacheSetHelperAPTGet helper(c0out);
+   std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
+		CmdL.FileList + 1, mods, fallback, helper);
 
-	 while (Cache->FindPkg(S).end() == true)
-	 {
-	    // Handle an optional end tag indicating what to do
-	    if (Length >= 1 && S[Length - 1] == '-')
-	    {
-	       Remove = true;
-	       S[--Length] = 0;
-	       continue;
-	    }
-	 
-	    if (Length >= 1 && S[Length - 1] == '+')
-	    {
-	       Remove = false;
-	       S[--Length] = 0;
-	       continue;
-	    }
-	 
-	    char *Slash = strchr(S,'=');
-	    if (Slash != 0)
-	    {
-	       VerIsRel = false;
-	       *Slash = 0;
-	       VerTag = Slash + 1;
-	    }
-	 
-	    Slash = strchr(S,'/');
-	    if (Slash != 0)
-	    {
-	       VerIsRel = true;
-	       *Slash = 0;
-	       VerTag = Slash + 1;
-	    }
-	 
-	    break;
-	 }
-      
-	 // Locate the package
-	 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
-	 Packages++;
-	 if (Pkg.end() == true)
-	 {
-	    APT::PackageSet pkgset = APT::PackageSet::FromRegEx(Cache, S, c1out);
-	    if (pkgset.empty() == true)
-	       return _error->Error(_("Couldn't find package %s"),S);
+   if (_error->PendingError() == true)
+   {
+      helper.showVirtualPackageErrors(Cache);
+      return false;
+   }
 
-	    // Regexs must always be confirmed
-	    ExpectedInst += 1000;
+   unsigned short order[] = { 0, 0, 0 };
+   if (fallback == MOD_INSTALL) {
+      order[0] = MOD_INSTALL;
+      order[1] = MOD_REMOVE;
+   } else {
+      order[0] = MOD_REMOVE;
+      order[1] = MOD_INSTALL;
+   }
 
-	    bool Hit = false;
-	    for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
-	    {
-	       if (VerTag != 0)
-		  if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
-		     return false;
+  TryToInstall InstallAction(Cache, Fix, BrokenFix);
+  TryToRemove RemoveAction(Cache, Fix);
 
-	       Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
-				   ExpectedInst,false);
-	    }
+   // new scope for the ActionGroup
+   {
+      pkgDepCache::ActionGroup group(Cache);
 
-	    if (Hit == false)
-	       return _error->Error(_("Couldn't find package %s"),S);
+      for (unsigned short i = 0; order[i] != 0; ++i)
+      {
+	 if (order[i] == MOD_INSTALL) {
+	    InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
+	    InstallAction.doAutoInstall();
 	 }
-	 else
-	 {
-	    if (VerTag != 0)
-	       if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
-		  return false;
-	    if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
-	       return false;
-
-	    // see if we need to fix the auto-mark flag 
-	    // e.g. apt-get install foo 
-	    // where foo is marked automatic
-	    if(!Remove && 
-	       Cache[Pkg].Install() == false && 
-	       (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
-	       _config->FindB("APT::Get::ReInstall",false) == false &&
-	       _config->FindB("APT::Get::Only-Upgrade",false) == false &&
-	       _config->FindB("APT::Get::Download-Only",false) == false)
-	    {
-	       ioprintf(c1out,_("%s set to manually installed.\n"),
-			Pkg.FullName(true).c_str());
-	       Cache->MarkAuto(Pkg,false);
-	       AutoMarkChanged++;
-	    }
-	 }      
+	 else if (order[i] == MOD_REMOVE)
+	    RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
       }
 
+      if (_error->PendingError() == true)
+	 return false;
+
       /* If we are in the Broken fixing mode we do not attempt to fix the
 	 problems. This is if the user invoked install without -f and gave
 	 packages */
@@ -1874,7 +1811,7 @@ bool DoInstall(CommandLine &CmdL)
 
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
-   if (Cache->InstCount() != ExpectedInst)
+   if (Cache->InstCount() != verset[MOD_INSTALL].size())
    {
       string List;
       string VersionsList;
@@ -1993,14 +1930,15 @@ bool DoInstall(CommandLine &CmdL)
    // if nothing changed in the cache, but only the automark information
    // we write the StateFile here, otherwise it will be written in 
    // cache.commit()
-   if (AutoMarkChanged > 0 &&
+   if (InstallAction.AutoMarkChanged > 0 &&
        Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
        Cache->BadCount() == 0 &&
        _config->FindB("APT::Get::Simulate",false) == false)
       Cache->writeStateFile(NULL);
 
    // See if we need to prompt
-   if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
+   // FIXME: check if really the packages in the set are going to be installed
+   if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
 
    return InstallPackages(Cache,false);   
@@ -2584,7 +2522,6 @@ bool DoBuildDep(CommandLine &CmdL)
       }
       
       // Install the requested packages
-      unsigned int ExpectedInst = 0;
       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
       pkgProblemResolver Fix(Cache);
       bool skipAlternatives = false; // skip remaining alternatives in an or group
@@ -2615,7 +2552,7 @@ bool DoBuildDep(CommandLine &CmdL)
              */
             if (IV.end() == false && 
                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
-               TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
+               TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
          }
 	 else // BuildDep || BuildDepIndep
          {
@@ -2731,7 +2668,7 @@ bool DoBuildDep(CommandLine &CmdL)
             if (_config->FindB("Debug::BuildDeps",false) == true)
                cout << "  Trying to install " << (*D).Package << endl;
 
-            if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
+            if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false) == true)
             {
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
@@ -3021,7 +2958,7 @@ int main(int argc,const char *argv[])					/*{{{*/
    }
 
    // Deal with stdout not being a tty
-   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
 
    // Setup the output streams
@@ -3042,13 +2979,11 @@ int main(int argc,const char *argv[])					/*{{{*/
    CmdL.DispatchArg(Cmds);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-   
-   return 0;   
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
 									/*}}}*/

+ 515 - 0
cmdline/cacheset.cc

@@ -0,0 +1,515 @@
+// -*- 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/strutl.h>
+#include <apt-pkg/versionmatch.h>
+
+#include <apti18n.h>
+
+#include "cacheset.h"
+
+#include <vector>
+
+#include <regex.h>
+									/*}}}*/
+namespace APT {
+// FromTask - Return all packages in the cache from a specific task	/*{{{*/
+PackageSet PackageSet::FromTask(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+	size_t const archfound = pattern.find_last_of(':');
+	std::string arch = "native";
+	if (archfound != std::string::npos) {
+		arch = pattern.substr(archfound+1);
+		pattern.erase(archfound);
+	}
+
+	if (pattern[pattern.length() -1] != '^')
+		return APT::PackageSet(TASK);
+	pattern.erase(pattern.length()-1);
+
+	if (unlikely(Cache.GetPkgCache() == 0 || Cache.GetDepCache() == 0))
+		return APT::PackageSet(TASK);
+
+	PackageSet pkgset(TASK);
+	// get the records
+	pkgRecords Recs(Cache);
+
+	// build regexp for the task
+	regex_t Pattern;
+	char S[300];
+	snprintf(S, sizeof(S), "^Task:.*[, ]%s([, ]|$)", pattern.c_str());
+	if(regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE) != 0) {
+		_error->Error("Failed to compile task regexp");
+		return pkgset;
+	}
+
+	for (pkgCache::GrpIterator Grp = Cache->GrpBegin(); Grp.end() == false; ++Grp) {
+		pkgCache::PkgIterator Pkg = Grp.FindPkg(arch);
+		if (Pkg.end() == true)
+			continue;
+		pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache);
+		if(ver.end() == true)
+			continue;
+
+		pkgRecords::Parser &parser = Recs.Lookup(ver.FileList());
+		const char *start, *end;
+		parser.GetRec(start,end);
+		unsigned int const length = end - start;
+		char buf[length];
+		strncpy(buf, start, length);
+		buf[length-1] = '\0';
+		if (regexec(&Pattern, buf, 0, 0, 0) != 0)
+			continue;
+
+		pkgset.insert(Pkg);
+	}
+	regfree(&Pattern);
+
+	if (pkgset.empty() == true)
+		return helper.canNotFindTask(Cache, pattern);
+
+	helper.showTaskSelection(pkgset, pattern);
+	return pkgset;
+}
+									/*}}}*/
+// FromRegEx - Return all packages in the cache matching a pattern	/*{{{*/
+PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
+	static const char * const isregex = ".?+*|[^$";
+	if (pattern.find_first_of(isregex) == std::string::npos)
+		return PackageSet(REGEX);
+
+	size_t archfound = pattern.find_last_of(':');
+	std::string arch = "native";
+	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 PackageSet(REGEX);
+	}
+
+	if (unlikely(Cache.GetPkgCache() == 0))
+		return PackageSet(REGEX);
+
+	PackageSet pkgset(REGEX);
+	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;
+		}
+
+		pkgset.insert(Pkg);
+	}
+	regfree(&Pattern);
+
+	if (pkgset.empty() == true)
+		return helper.canNotFindRegEx(Cache, pattern);
+
+	helper.showRegExSelection(pkgset, pattern);
+	return pkgset;
+}
+									/*}}}*/
+// FromName - Returns the package defined  by this string		/*{{{*/
+pkgCache::PkgIterator PackageSet::FromName(pkgCacheFile &Cache,
+			std::string const &str, CacheSetHelper &helper) {
+	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);
+	}
+
+	if (Cache.GetPkgCache() == 0)
+		return pkgCache::PkgIterator(Cache, 0);
+
+	pkgCache::PkgIterator Pkg(Cache, 0);
+	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() == true)
+		return helper.canNotFindPkgName(Cache, str);
+	return Pkg;
+}
+									/*}}}*/
+// 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, CacheSetHelper &helper) {
+	std::map<unsigned short, PackageSet> pkgsets;
+	for (const char **I = cmdline; *I != 0; ++I) {
+		unsigned short modID = fallback;
+		std::string str = *I;
+		bool modifierPresent = false;
+		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;
+			}
+			modifierPresent = true;
+			break;
+		}
+		if (modifierPresent == true) {
+			bool const errors = helper.showErrors(false);
+			pkgCache::PkgIterator Pkg = FromName(Cache, *I, helper);
+			helper.showErrors(errors);
+			if (Pkg.end() == false) {
+				pkgsets[fallback].insert(Pkg);
+				continue;
+			}
+		}
+		pkgsets[modID].insert(PackageSet::FromString(Cache, str, helper));
+	}
+	return pkgsets;
+}
+									/*}}}*/
+// FromCommandLine - Return all packages specified on commandline	/*{{{*/
+PackageSet PackageSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper) {
+	PackageSet pkgset;
+	for (const char **I = cmdline; *I != 0; ++I) {
+		PackageSet pset = FromString(Cache, *I, helper);
+		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, CacheSetHelper &helper) {
+	_error->PushToStack();
+
+	PackageSet pkgset;
+	pkgCache::PkgIterator Pkg = FromName(Cache, str, helper);
+	if (Pkg.end() == false)
+		pkgset.insert(Pkg);
+	else {
+		pkgset = FromTask(Cache, str, helper);
+		if (pkgset.empty() == true) {
+			pkgset = FromRegEx(Cache, str, helper);
+			if (pkgset.empty() == true)
+				pkgset = helper.canNotFindPackage(Cache, str);
+		}
+	}
+
+	if (pkgset.empty() == false)
+		_error->RevertToStack();
+	else
+		_error->MergeWithStack();
+	return pkgset;
+}
+									/*}}}*/
+// GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
+std::map<unsigned short, VersionSet> VersionSet::GroupedFromCommandLine(
+		pkgCacheFile &Cache, const char **cmdline,
+		std::list<VersionSet::Modifier> const &mods,
+		unsigned short const &fallback, CacheSetHelper &helper) {
+	std::map<unsigned short, VersionSet> versets;
+	for (const char **I = cmdline; *I != 0; ++I) {
+		unsigned short modID = fallback;
+		VersionSet::Version select = VersionSet::NEWEST;
+		std::string str = *I;
+		bool modifierPresent = false;
+		for (std::list<VersionSet::Modifier>::const_iterator mod = mods.begin();
+		     mod != mods.end(); ++mod) {
+			if (modID == fallback && mod->ID == fallback)
+				select = mod->SelectVersion;
+			size_t const alength = strlen(mod->Alias);
+			switch(mod->Pos) {
+			case VersionSet::Modifier::POSTFIX:
+				if (str.compare(str.length() - alength, alength,
+						mod->Alias, 0, alength) != 0)
+					continue;
+				str.erase(str.length() - alength);
+				modID = mod->ID;
+				select = mod->SelectVersion;
+				break;
+			case VersionSet::Modifier::PREFIX:
+				continue;
+			case VersionSet::Modifier::NONE:
+				continue;
+			}
+			modifierPresent = true;
+			break;
+		}
+
+		if (modifierPresent == true) {
+			bool const errors = helper.showErrors(false);
+			VersionSet const vset = VersionSet::FromString(Cache, std::string(*I), select, helper, true);
+			helper.showErrors(errors);
+			if (vset.empty() == false) {
+				versets[fallback].insert(vset);
+				continue;
+			}
+		}
+		versets[modID].insert(VersionSet::FromString(Cache, str, select , helper));
+	}
+	return versets;
+}
+									/*}}}*/
+// FromCommandLine - Return all versions specified on commandline	/*{{{*/
+APT::VersionSet VersionSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+		APT::VersionSet::Version const &fallback, CacheSetHelper &helper) {
+	VersionSet verset;
+	for (const char **I = cmdline; *I != 0; ++I)
+		verset.insert(VersionSet::FromString(Cache, *I, fallback, helper));
+	return verset;
+}
+									/*}}}*/
+// FromString - Returns all versions spedcified by a string		/*{{{*/
+APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg,
+		APT::VersionSet::Version const &fallback, CacheSetHelper &helper,
+		bool const &onlyFromName) {
+	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;
+	if (onlyFromName == false)
+		pkgset = PackageSet::FromString(Cache, pkg, helper);
+	else {
+		pkgset.insert(PackageSet::FromName(Cache, pkg, helper));
+	}
+
+	VersionSet verset;
+	bool errors = true;
+	if (pkgset.getConstructor() != PackageSet::UNKNOWN)
+		errors = helper.showErrors(false);
+	for (PackageSet::const_iterator P = pkgset.begin();
+	     P != pkgset.end(); ++P) {
+		if (vertag == string::npos) {
+			verset.insert(VersionSet::FromPackage(Cache, P, fallback, helper));
+			continue;
+		}
+		pkgCache::VerIterator V;
+		if (ver == "installed")
+			V = getInstalledVer(Cache, P, helper);
+		else if (ver == "candidate")
+			V = getCandidateVer(Cache, P, helper);
+		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;
+		helper.showSelectedVersion(P, V, ver, verIsRel);
+		verset.insert(V);
+	}
+	if (pkgset.getConstructor() != PackageSet::UNKNOWN)
+		helper.showErrors(errors);
+	return verset;
+}
+									/*}}}*/
+// FromPackage - versions from package based on fallback		/*{{{*/
+VersionSet VersionSet::FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
+		VersionSet::Version const &fallback, CacheSetHelper &helper) {
+	VersionSet verset;
+	pkgCache::VerIterator V;
+	bool showErrors;
+	switch(fallback) {
+	case VersionSet::ALL:
+		if (P->VersionList != 0)
+			for (V = P.VersionList(); V.end() != true; ++V)
+				verset.insert(V);
+		else
+			verset.insert(helper.canNotFindAllVer(Cache, P));
+		break;
+	case VersionSet::CANDANDINST:
+		verset.insert(getInstalledVer(Cache, P, helper));
+		verset.insert(getCandidateVer(Cache, P, helper));
+		break;
+	case VersionSet::CANDIDATE:
+		verset.insert(getCandidateVer(Cache, P, helper));
+		break;
+	case VersionSet::INSTALLED:
+		verset.insert(getInstalledVer(Cache, P, helper));
+		break;
+	case VersionSet::CANDINST:
+		showErrors = helper.showErrors(false);
+		V = getCandidateVer(Cache, P, helper);
+		if (V.end() == true)
+			V = getInstalledVer(Cache, P, helper);
+		helper.showErrors(showErrors);
+		if (V.end() == false)
+			verset.insert(V);
+		else
+			verset.insert(helper.canNotFindInstCandVer(Cache, P));
+		break;
+	case VersionSet::INSTCAND:
+		showErrors = helper.showErrors(false);
+		V = getInstalledVer(Cache, P, helper);
+		if (V.end() == true)
+			V = getCandidateVer(Cache, P, helper);
+		helper.showErrors(showErrors);
+		if (V.end() == false)
+			verset.insert(V);
+		else
+			verset.insert(helper.canNotFindInstCandVer(Cache, P));
+		break;
+	case VersionSet::NEWEST:
+		if (P->VersionList != 0)
+			verset.insert(P.VersionList());
+		else
+			verset.insert(helper.canNotFindNewestVer(Cache, P));
+		break;
+	}
+	return verset;
+}
+									/*}}}*/
+// getCandidateVer - Returns the candidate version of the given package	/*{{{*/
+pkgCache::VerIterator VersionSet::getCandidateVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) {
+	pkgCache::VerIterator Cand;
+	if (Cache.IsPolicyBuilt() == true || Cache.IsDepCacheBuilt() == false)
+	{
+		if (unlikely(Cache.GetPolicy() == 0))
+			return pkgCache::VerIterator(Cache);
+		Cand = Cache.GetPolicy()->GetCandidateVer(Pkg);
+	} else {
+		Cand = Cache[Pkg].CandidateVerIter(Cache);
+	}
+	if (Cand.end() == true)
+		return helper.canNotFindCandidateVer(Cache, Pkg);
+	return Cand;
+}
+									/*}}}*/
+// getInstalledVer - Returns the installed version of the given package	/*{{{*/
+pkgCache::VerIterator VersionSet::getInstalledVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) {
+	if (Pkg->CurrentVer == 0)
+		return helper.canNotFindInstalledVer(Cache, Pkg);
+	return Pkg.CurrentVer();
+}
+									/*}}}*/
+// canNotFindPkgName - handle the case no package has this name		/*{{{*/
+pkgCache::PkgIterator CacheSetHelper::canNotFindPkgName(pkgCacheFile &Cache,
+			std::string const &str) {
+	if (ShowError == true)
+		_error->Error(_("Unable to locate package %s"), str.c_str());
+	return pkgCache::PkgIterator(Cache, 0);
+}
+									/*}}}*/
+// canNotFindTask - handle the case no package is found for a task	/*{{{*/
+PackageSet CacheSetHelper::canNotFindTask(pkgCacheFile &Cache, std::string pattern) {
+	if (ShowError == true)
+		_error->Error(_("Couldn't find task '%s'"), pattern.c_str());
+	return PackageSet();
+}
+									/*}}}*/
+// canNotFindRegEx - handle the case no package is found by a regex	/*{{{*/
+PackageSet CacheSetHelper::canNotFindRegEx(pkgCacheFile &Cache, std::string pattern) {
+	if (ShowError == true)
+		_error->Error(_("Couldn't find any package by regex '%s'"), pattern.c_str());
+	return PackageSet();
+}
+									/*}}}*/
+// canNotFindPackage - handle the case no package is found from a string/*{{{*/
+PackageSet CacheSetHelper::canNotFindPackage(pkgCacheFile &Cache, std::string const &str) {
+	return PackageSet();
+}
+									/*}}}*/
+// canNotFindAllVer							/*{{{*/
+VersionSet CacheSetHelper::canNotFindAllVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Error(_("Can't select versions from package '%s' as it purely virtual"), Pkg.FullName(true).c_str());
+	return VersionSet();
+}
+									/*}}}*/
+// canNotFindInstCandVer						/*{{{*/
+VersionSet CacheSetHelper::canNotFindInstCandVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str());
+	return VersionSet();
+}
+									/*}}}*/
+// canNotFindInstCandVer						/*{{{*/
+VersionSet CacheSetHelper::canNotFindCandInstVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str());
+	return VersionSet();
+}
+									/*}}}*/
+// canNotFindNewestVer							/*{{{*/
+pkgCache::VerIterator CacheSetHelper::canNotFindNewestVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Error(_("Can't select newest version from package '%s' as it is purely virtual"), Pkg.FullName(true).c_str());
+	return pkgCache::VerIterator(Cache, 0);
+}
+									/*}}}*/
+// canNotFindCandidateVer						/*{{{*/
+pkgCache::VerIterator CacheSetHelper::canNotFindCandidateVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg.FullName(true).c_str());
+	return pkgCache::VerIterator(Cache, 0);
+}
+									/*}}}*/
+// canNotFindInstalledVer						/*{{{*/
+pkgCache::VerIterator CacheSetHelper::canNotFindInstalledVer(pkgCacheFile &Cache,
+		pkgCache::PkgIterator const &Pkg) {
+	if (ShowError == true)
+		_error->Error(_("Can't select installed version from package %s as it is not installed"), Pkg.FullName(true).c_str());
+	return pkgCache::VerIterator(Cache, 0);
+}
+									/*}}}*/
+}

+ 169 - 33
apt-pkg/cacheset.h

@@ -20,6 +20,48 @@
 #include <apt-pkg/pkgcache.h>
 									/*}}}*/
 namespace APT {
+class PackageSet;
+class VersionSet;
+class CacheSetHelper {							/*{{{*/
+/** \class APT::CacheSetHelper
+    Simple base class with a lot of virtual methods which can be overridden
+    to alter the behavior or the output of the CacheSets.
+
+    This helper is passed around by the static methods in the CacheSets and
+    used every time they hit an error condition or something could be
+    printed out.
+*/
+public:									/*{{{*/
+	CacheSetHelper(bool const &ShowError = true) : ShowError(ShowError) {};
+	virtual ~CacheSetHelper() {};
+
+	virtual void showTaskSelection(PackageSet const &pkgset, string const &pattern) {};
+	virtual void showRegExSelection(PackageSet const &pkgset, string const &pattern) {};
+	virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+				 string const &ver, bool const &verIsRel) {};
+
+	virtual pkgCache::PkgIterator canNotFindPkgName(pkgCacheFile &Cache, std::string const &str);
+	virtual PackageSet canNotFindTask(pkgCacheFile &Cache, std::string pattern);
+	virtual PackageSet canNotFindRegEx(pkgCacheFile &Cache, std::string pattern);
+	virtual PackageSet canNotFindPackage(pkgCacheFile &Cache, std::string const &str);
+	virtual VersionSet canNotFindAllVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg);
+	virtual VersionSet canNotFindInstCandVer(pkgCacheFile &Cache,
+				pkgCache::PkgIterator const &Pkg);
+	virtual VersionSet canNotFindCandInstVer(pkgCacheFile &Cache,
+				pkgCache::PkgIterator const &Pkg);
+	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache,
+				pkgCache::PkgIterator const &Pkg);
+	virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache,
+				pkgCache::PkgIterator const &Pkg);
+	virtual pkgCache::VerIterator canNotFindInstalledVer(pkgCacheFile &Cache,
+				pkgCache::PkgIterator const &Pkg);
+
+	bool showErrors() const { return ShowError; };
+	bool showErrors(bool const &newValue) { if (ShowError == newValue) return ShowError; else return ((ShowError = newValue) == false); };
+									/*}}}*/
+protected:
+	bool ShowError;
+};									/*}}}*/
 class PackageSet : public std::set<pkgCache::PkgIterator> {		/*{{{*/
 /** \class APT::PackageSet
 
@@ -28,7 +70,7 @@ class PackageSet : public std::set<pkgCache::PkgIterator> {		/*{{{*/
     pkgCache. */
 public:									/*{{{*/
 	/** \brief smell like a pkgCache::PkgIterator */
-	class const_iterator : public std::set<pkgCache::PkgIterator>::const_iterator {
+	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) {}
@@ -62,9 +104,25 @@ public:									/*{{{*/
 	};
 	// 103. set::iterator is required to be modifiable, but this allows modification of keys
 	typedef 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); };
+	inline void insert(PackageSet const &pkgset) { insert(pkgset.begin(), pkgset.end()); };
+
+	/** \brief returns all packages in the cache who belong to the given task
+
+	    A simple helper responsible for search for all members of a task
+	    in the cache. Optional it prints a a notice about the
+	    packages chosen cause of the given task.
+	    \param Cache the packages are in
+	    \param pattern name of the task
+	    \param helper responsible for error and message handling */
+	static APT::PackageSet FromTask(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
+	static APT::PackageSet FromTask(pkgCacheFile &Cache, std::string const &pattern) {
+		CacheSetHelper helper;
+		return APT::PackageSet::FromTask(Cache, pattern, helper);
+	}
 
 	/** \brief returns all packages in the cache whose name matchs a given pattern
 
@@ -73,22 +131,33 @@ public:									/*{{{*/
 	    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);
+	    \param helper responsible for error and message handling */
+	static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
 	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);
+		CacheSetHelper helper;
+		return APT::PackageSet::FromRegEx(Cache, pattern, helper);
 	}
 
 	/** \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);
+	    \param helper responsible for error and message handling */
+	static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, CacheSetHelper &helper);
 	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);
+		CacheSetHelper helper;
+		return APT::PackageSet::FromString(Cache, string, helper);
+	}
+
+	/** \brief returns a package specified by a string
+
+	    \param Cache the package is in
+	    \param string String the package name should be extracted from
+	    \param helper responsible for error and message handling */
+	static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &string, CacheSetHelper &helper);
+	static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &string) {
+		CacheSetHelper helper;
+		return APT::PackageSet::FromName(Cache, string, helper);
 	}
 
 	/** \brief returns all packages specified on the commandline
@@ -97,11 +166,11 @@ public:									/*{{{*/
 	    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);
+	    \param helper responsible for error and message handling */
+	static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper);
 	static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
-		std::ostream out (std::ofstream("/dev/null").rdbuf());
-		return APT::PackageSet::FromCommandLine(Cache, cmdline, out);
+		CacheSetHelper helper;
+		return APT::PackageSet::FromCommandLine(Cache, cmdline, helper);
 	}
 
 	struct Modifier {
@@ -112,18 +181,38 @@ public:									/*{{{*/
 		Modifier (unsigned short const &id, const char * const alias, Position const &pos) : ID(id), Alias(alias), Pos(pos) {};
 	};
 
+	/** \brief group packages by a action modifiers
+
+	    At some point it is needed to get from the same commandline
+	    different package sets grouped by a modifier. Take
+		apt-get install apt awesome-
+	    as an example.
+	    \param Cache the packages are in
+	    \param cmdline Command line the package names should be extracted from
+	    \param mods list of modifiers the method should accept
+	    \param fallback the default modifier group for a package
+	    \param helper responsible for error and message handling */
 	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);
+		unsigned short const &fallback, CacheSetHelper &helper);
 	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());
+		CacheSetHelper helper;
 		return APT::PackageSet::GroupedFromCommandLine(Cache, cmdline,
-				mods, fallback, out);
+				mods, fallback, helper);
 	}
+
+	enum Constructor { UNKNOWN, REGEX, TASK };
+	Constructor getConstructor() const { return ConstructedBy; };
+
+	PackageSet() : ConstructedBy(UNKNOWN) {};
+	PackageSet(Constructor const &by) : ConstructedBy(by) {};
+									/*}}}*/
+private:								/*{{{*/
+	Constructor ConstructedBy;
 									/*}}}*/
 };									/*}}}*/
 class VersionSet : public std::set<pkgCache::VerIterator> {		/*{{{*/
@@ -134,7 +223,7 @@ class VersionSet : public std::set<pkgCache::VerIterator> {		/*{{{*/
     pkgCache. */
 public:									/*{{{*/
 	/** \brief smell like a pkgCache::VerIterator */
-	class const_iterator : public std::set<pkgCache::VerIterator>::const_iterator {
+	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) {}
@@ -168,11 +257,13 @@ public:									/*{{{*/
 		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 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); };
+	inline void insert(VersionSet const &verset) { insert(verset.begin(), verset.end()); };
 
 	/** \brief specifies which version(s) will be returned if non is given */
 	enum Version {
@@ -198,41 +289,86 @@ public:									/*{{{*/
 	    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 */
+	    \param helper responsible for error and message handling */
 	static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
-			APT::VersionSet::Version const &fallback, std::ostream &out);
+			APT::VersionSet::Version const &fallback, CacheSetHelper &helper);
 	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);
+		CacheSetHelper helper;
+		return APT::VersionSet::FromCommandLine(Cache, cmdline, fallback, helper);
 	}
 	static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
 		return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST);
 	}
+
+	static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg,
+			APT::VersionSet::Version const &fallback, CacheSetHelper &helper,
+			bool const &onlyFromName = false);
+	static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg,
+			APT::VersionSet::Version const &fallback) {
+		CacheSetHelper helper;
+		return APT::VersionSet::FromString(Cache, pkg, fallback, helper);
+	}
+	static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg) {
+		return APT::VersionSet::FromString(Cache, pkg, CANDINST);
+	}
+
+	/** \brief returns all versions specified for the package
+
+	    \param Cache the package and versions are in
+	    \param P the package in question
+	    \param fallback the version(s) you want to get
+	    \param helper the helper used for display and error handling */
+	static APT::VersionSet FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
+		VersionSet::Version const &fallback, CacheSetHelper &helper);
+	static APT::VersionSet FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
+			APT::VersionSet::Version const &fallback) {
+		CacheSetHelper helper;
+		return APT::VersionSet::FromPackage(Cache, P, fallback, helper);
+	}
+	static APT::VersionSet FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P) {
+		return APT::VersionSet::FromPackage(Cache, P, CANDINST);
+	}
+
+	struct Modifier {
+		enum Position { NONE, PREFIX, POSTFIX };
+		unsigned short ID;
+		const char * const Alias;
+		Position Pos;
+		VersionSet::Version SelectVersion;
+		Modifier (unsigned short const &id, const char * const alias, Position const &pos,
+			  VersionSet::Version const &select) : ID(id), Alias(alias), Pos(pos),
+			 SelectVersion(select) {};
+	};
+
+	static std::map<unsigned short, VersionSet> GroupedFromCommandLine(
+		pkgCacheFile &Cache, const char **cmdline,
+		std::list<VersionSet::Modifier> const &mods,
+		unsigned short const &fallback, CacheSetHelper &helper);
+	static std::map<unsigned short, VersionSet> GroupedFromCommandLine(
+		pkgCacheFile &Cache, const char **cmdline,
+		std::list<VersionSet::Modifier> const &mods,
+		unsigned short const &fallback) {
+		CacheSetHelper helper;
+		return APT::VersionSet::GroupedFromCommandLine(Cache, cmdline,
+				mods, fallback, helper);
+	}
 									/*}}}*/
 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 */
+	    \param Pkg we want the candidate version from this package */
 	static pkgCache::VerIterator getCandidateVer(pkgCacheFile &Cache,
-		pkgCache::PkgIterator const &Pkg, bool const &AllowError = false);
+		pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper);
 
 	/** \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 */
+	    \param Pkg we want the installed version from this package */
 	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);
-
+		pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper);
 									/*}}}*/
 };									/*}}}*/
 }

+ 2 - 2
cmdline/makefile

@@ -9,14 +9,14 @@ include ../buildlib/defaults.mak
 PROGRAM=apt-cache
 SLIBS = -lapt-pkg $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-cache.cc
+SOURCE = apt-cache.cc cacheset.cc
 include $(PROGRAM_H)
 
 # The apt-get program
 PROGRAM=apt-get
 SLIBS = -lapt-pkg -lutil $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-get.cc acqprogress.cc
+SOURCE = apt-get.cc acqprogress.cc cacheset.cc
 include $(PROGRAM_H)
 
 # The apt-config program

+ 44 - 2
debian/changelog

@@ -1,5 +1,47 @@
-apt (0.7.26~exp8) experimental; urgency=low
+apt (0.7.26~exp8) UNRELEASED; urgency=low
 
+  [ David Kalnischkies ]
+  * cmdline/cacheset.cc:
+    - doesn't include it in the library for now as it is too volatile
+    - get the candidate either from an already built depcache
+      or use the policy which is a bit faster than depcache generation
+    - get packages by task^ with FromTask()
+    - only print errors if all tries to get a package by string failed
+    - factor out code to get a single package FromName()
+    - check in Grouped* first without modifier interpretation
+  * cmdline/apt-get.cc:
+    - use the cachsets in the install commands
+    - make the specify order of packages irrelevant (Closes: #196021)
+  * apt-pkg/orderlist.cc:
+    - untouched packages are never missing
+  * apt-pkg/packagemanager.cc:
+    - packages that are not touched doesn't need to be unpacked
+  * debian/control:
+    - remove intltool's dependency as it is an ubuntu artefact
+  * apt-pkg/depcache.cc:
+    - SetCandidateVer for all pseudo packages
+    - SetReInstall for the "all" package of a pseudo package
+    - use the new MatchAgainstConfig for the DefaultRootSetFunc
+    - always mark the all package if a pseudo package is marked for install
+  * apt-pkg/contrib/error.{cc,h}:
+    - complete rewrite but use the same API
+    - add NOTICE and DEBUG as new types of a message
+    - add a simple stack handling to be able to delay error handling
+  * apt-pkg/aptconfiguration.cc:
+    - show a deprecation notice for APT::Acquire::Translation
+  * apt-pkg/contrib/configuration.{cc,h}:
+    - add a wrapper to match strings against configurable regex patterns
+  * apt-pkg/contrib/fileutl.cc:
+    - show notice about ignored file instead of being always silent
+    - add a Dir::Ignore-Files-Silently list option to control the notice
+  * apt-pkg/policy.h:
+    - add another round of const& madness as the previous round accidentally
+      NOT overrides the virtual GetCandidateVer() method (Closes: #587725)
+  * apt-pkg/pkgcachegen.{cc,h}:
+    - make the used MMap moveable (and therefore dynamic resizeable) by
+      applying (some) mad pointer magic (Closes: #195018)
+
+  [ Julian Andres Klode ]
   * methods/ftp.h:
     - Handle different logins on the same server (Closes: #586904).
   * apt-pkg/deb/deblistparser.cc:
@@ -13,7 +55,7 @@ apt (0.7.26~exp8) experimental; urgency=low
   * debian/control:
     - Set Standards-Version to 3.9.0
 
- -- Julian Andres Klode <jak@debian.org>  Thu, 24 Jun 2010 10:56:39 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Mon, 05 Jul 2010 12:05:30 +0200
 
 apt (0.7.26~exp7) experimental; urgency=low
 

+ 1 - 1
debian/control

@@ -6,7 +6,7 @@ Uploaders: Michael Vogt <mvo@debian.org>, Otavio Salvador <otavio@debian.org>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Luca Bruno <lethalman88@gmail.com>, Julian Andres Klode <jak@debian.org>
 Standards-Version: 3.9.0
-Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev, autoconf, automake, doxygen, intltool
+Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev, autoconf, automake, doxygen
 Build-Conflicts: autoconf2.13, automake1.4
 
 Package: apt

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

@@ -507,6 +507,15 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      will be looked up in
      <filename>/tmp/staging/var/lib/dpkg/status</filename>.
    </para>
+
+   <para>
+      The <literal>Ignore-Files-Silently</literal> list can be used to specify
+      which files APT should silently ignore while parsing the files in the
+      fragment directories. Per default a file which end with <literal>.disabled</literal>,
+      <literal>~</literal>, <literal>.bak</literal> or <literal>.dpkg-[a-z]+</literal>
+      is silently ignored. As seen in the last default value these patterns can use regular
+      expression syntax.
+   </para>
  </refsect1>
  
  <refsect1><title>APT in DSelect</title>

+ 77 - 0
test/libapt/globalerror_test.cc

@@ -0,0 +1,77 @@
+#include <apt-pkg/error.h>
+
+#include "assert.h"
+#include <string>
+
+int main(int argc,char *argv[])
+{
+	equals(_error->empty(), true);
+	equals(_error->PendingError(), false);
+	equals(_error->Notice("%s Notice", "A"), false);
+	equals(_error->empty(), true);
+	equals(_error->empty(GlobalError::DEBUG), false);
+	equals(_error->PendingError(), false);
+	equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+	equals(_error->PendingError(), true);
+	std::string text;
+	equals(_error->PopMessage(text), false);
+	equals(_error->PendingError(), true);
+	equals(text, "A Notice");
+	equals(_error->PopMessage(text), true);
+	equals(text, "Something horrible happend 2 times");
+	equals(_error->empty(GlobalError::DEBUG), true);
+	equals(_error->PendingError(), false);
+	equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+	equals(_error->PendingError(), true);
+	equals(_error->empty(GlobalError::FATAL), false);
+	_error->Discard();
+
+	equals(_error->empty(), true);
+	equals(_error->PendingError(), false);
+	equals(_error->Notice("%s Notice", "A"), false);
+	equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+	equals(_error->PendingError(), true);
+	equals(_error->empty(GlobalError::NOTICE), false);
+	_error->PushToStack();
+	equals(_error->empty(GlobalError::NOTICE), true);
+	equals(_error->PendingError(), false);
+	equals(_error->Warning("%s Warning", "A"), false);
+	equals(_error->empty(GlobalError::ERROR), true);
+	equals(_error->PendingError(), false);
+	_error->RevertToStack();
+	equals(_error->empty(GlobalError::ERROR), false);
+	equals(_error->PendingError(), true);
+	equals(_error->PopMessage(text), false);
+	equals(_error->PendingError(), true);
+	equals(text, "A Notice");
+	equals(_error->PopMessage(text), true);
+	equals(text, "Something horrible happend 2 times");
+	equals(_error->PendingError(), false);
+	equals(_error->empty(), true);
+
+	equals(_error->Notice("%s Notice", "A"), false);
+	equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+	equals(_error->PendingError(), true);
+	equals(_error->empty(GlobalError::NOTICE), false);
+	_error->PushToStack();
+	equals(_error->empty(GlobalError::NOTICE), true);
+	equals(_error->PendingError(), false);
+	equals(_error->Warning("%s Warning", "A"), false);
+	equals(_error->empty(GlobalError::ERROR), true);
+	equals(_error->PendingError(), false);
+	_error->MergeWithStack();
+	equals(_error->empty(GlobalError::ERROR), false);
+	equals(_error->PendingError(), true);
+	equals(_error->PopMessage(text), false);
+	equals(_error->PendingError(), true);
+	equals(text, "A Notice");
+	equals(_error->PopMessage(text), true);
+	equals(text, "Something horrible happend 2 times");
+	equals(_error->PendingError(), false);
+	equals(_error->empty(), false);
+	equals(_error->PopMessage(text), false);
+	equals(text, "A Warning");
+	equals(_error->empty(), true);
+
+	return 0;
+}

+ 8 - 2
test/libapt/makefile

@@ -30,13 +30,19 @@ SOURCE = getlistoffilesindir_test.cc
 include $(PROGRAM_H)
 
 # Program for testing CommandLine reconstruction
-PROGRAM = commandlineasstring${BASENAME}
+PROGRAM = CommandlineAsString${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = commandlineasstring_test.cc
 include $(PROGRAM_H)
 
 # Program for testing debians version comparing
-PROGRAM = compareversion${BASENAME}
+PROGRAM = CompareVersion${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = compareversion_test.cc
 include $(PROGRAM_H)
+
+# test the GlobalError stack class
+PROGRAM = GlobalError${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = globalerror_test.cc
+include $(PROGRAM_H)

+ 68 - 0
test/libapt/parsedepends_test.cc

@@ -21,6 +21,12 @@ int main(int argc,char *argv[]) {
 		"apt (>= 0.7.25), "
 		"not-for-me [ !dsk ], "
 		"only-for-me [ dsk ], "
+		"any-for-me [ any ], "
+		"not-for-darwin [ !darwin-any ], "
+		"cpu-for-me [ any-dsk ], "
+		"os-for-me [ linux-any ], "
+		"cpu-not-for-me [ any-amd64 ], "
+		"os-not-for-me [ kfreebsd-any ], "
 		"overlord-dev:any (= 7.15.3~) | overlord-dev:native (>> 7.15.5), "
 	;
 
@@ -100,6 +106,68 @@ test:
 		Start++;
 	}
 
+	if (ParseArchFlags == true) {
+		Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
+		equals("any-for-me", Package);
+		equals("", Version);
+		equals(Null | pkgCache::Dep::NoOp, Op);
+	} else {
+		equals(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch));
+		Start = strstr(Start, ",");
+		Start++;
+	}
+
+	if (ParseArchFlags == true) {
+		Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
+		equals("not-for-darwin", Package);
+		equals("", Version);
+		equals(Null | pkgCache::Dep::NoOp, Op);
+	} else {
+		equals(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch));
+		Start = strstr(Start, ",");
+		Start++;
+	}
+
+	if (ParseArchFlags == true) {
+		Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
+		equals("cpu-for-me", Package);
+		equals("", Version);
+		equals(Null | pkgCache::Dep::NoOp, Op);
+	} else {
+		equals(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch));
+		Start = strstr(Start, ",");
+		Start++;
+	}
+
+	if (ParseArchFlags == true) {
+		Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
+		equals("os-for-me", Package);
+		equals("", Version);
+		equals(Null | pkgCache::Dep::NoOp, Op);
+	} else {
+		equals(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch));
+		Start = strstr(Start, ",");
+		Start++;
+	}
+
+	if (ParseArchFlags == true) {
+		Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
+		equals("", Package); // cpu-not-for-me
+	} else {
+		equals(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch));
+		Start = strstr(Start, ",");
+		Start++;
+	}
+
+	if (ParseArchFlags == true) {
+		Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
+		equals("", Package); // os-not-for-me
+	} else {
+		equals(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch));
+		Start = strstr(Start, ",");
+		Start++;
+	}
+
 	Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
 	if (StripMultiArch == true)
 		equals("overlord-dev", Package);