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

+ 1 - 1
apt-pkg/algorithms.h

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

+ 4 - 0
apt-pkg/aptconfiguration.cc

@@ -10,6 +10,7 @@
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/strutl.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
 	// it was undocumented and so it should be not very widthly used
 	string const oldAcquire = _config->Find("APT::Acquire::Translation","");
 	string const oldAcquire = _config->Find("APT::Acquire::Translation","");
 	if (oldAcquire.empty() == false && oldAcquire != "environment") {
 	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")
 		if (oldAcquire != "none")
 			codes.push_back(oldAcquire);
 			codes.push_back(oldAcquire);
 		codes.push_back("en");
 		codes.push_back("en");

+ 1 - 1
apt-pkg/cachefile.cc

@@ -28,7 +28,7 @@
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL),
 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/depcache.h>
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire.h>
+#include <apt-pkg/policy.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sourcelist.h>
 
 
-class pkgPolicy;
-class pkgSourceList;
 class pkgCacheFile
 class pkgCacheFile
 {
 {
    protected:
    protected:
@@ -65,6 +64,11 @@ class pkgCacheFile
    inline pkgPolicy* GetPolicy() { BuildPolicy(); return Policy; };
    inline pkgPolicy* GetPolicy() { BuildPolicy(); return Policy; };
    inline pkgSourceList* GetSourceList() { BuildSourceList(); return SrcList; };
    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();
    pkgCacheFile();
    virtual ~pkgCacheFile();
    virtual ~pkgCacheFile();
 };
 };

+ 31 - 16
apt-pkg/cacheiterators.h

@@ -30,6 +30,8 @@
 #ifndef PKGLIB_CACHEITERATORS_H
 #ifndef PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 #include<iterator>
 #include<iterator>
+
+#include<string.h>
 // abstract Iterator template						/*{{{*/
 // abstract Iterator template						/*{{{*/
 /* This template provides the very basic iterator methods we
 /* This template provides the very basic iterator methods we
    need to have for doing some walk-over-the-cache magic */
    need to have for doing some walk-over-the-cache magic */
@@ -73,6 +75,12 @@ template<typename Str, typename Itr> class pkgCache::Iterator :
 	inline bool IsGood() const { return S && Owner && ! end();};
 	inline bool IsGood() const { return S && Owner && ! end();};
 	inline unsigned long Index() const {return S - OwnerPointer();};
 	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
 	// Constructors - look out for the variable assigning
 	inline Iterator() : S(0), Owner(0) {};
 	inline Iterator() : S(0), Owner(0) {};
 	inline Iterator(pkgCache &Owner,Str *T = 0) : S(T), Owner(&Owner) {};
 	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 const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
 	inline PkgIterator PackageList() const;
 	inline PkgIterator PackageList() const;
-	PkgIterator FindPkg(string Arch = "any");
+	PkgIterator FindPkg(string Arch = "any") const;
 	/** \brief find the package with the "best" architecture
 	/** \brief find the package with the "best" architecture
 
 
 	    The best architecture is either the "native" or the first
 	    The best architecture is either the "native" or the first
 	    in the list of Architectures which is not an end-Pointer */
 	    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
 	// Constructors
 	inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator<Group, GrpIterator>(Owner, Trg), HashIndex(0) {
 	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
 	// Comparison
 	int CompareVer(const VerIterator &B) const;
 	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
 	// Accessors
 	inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;};
 	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
 	// Accessors
 	inline const char *TargetVer() const {return S->Version == 0?0:Owner->StrP + S->Version;};
 	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);
 	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) :
 	inline DepIterator(pkgCache &Owner, Dependency *Trg, Version* = 0) :
 		Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepVer) {
 		Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepVer) {
@@ -306,9 +321,9 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
 	// Accessors
 	// Accessors
 	inline const char *Name() const {return Owner->StrP + Owner->PkgP[S->ParentPkg].Name;};
 	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 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) {};
 	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;
    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
 #ifndef PKGLIB_CONFIGURATION_H
 #define PKGLIB_CONFIGURATION_H
 #define PKGLIB_CONFIGURATION_H
 
 
-
+#include <regex.h>
 
 
 #include <string>
 #include <string>
 #include <vector>
 #include <vector>
@@ -104,6 +104,23 @@ class Configuration
    Configuration(const Item *Root);
    Configuration(const Item *Root);
    Configuration();
    Configuration();
    ~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;
 extern Configuration *_config;

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

@@ -1,16 +1,15 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // 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
    We use a simple STL vector to store each error record. A PendingFlag
    is kept which indicates when the vector contains a Sever error.
    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
    This source is placed in the Public Domain, do with it what you will
    It was originally written by Jason Gunthorpe.
    It was originally written by Jason Gunthorpe.
-   
+
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
@@ -19,7 +18,6 @@
 #include <iostream>
 #include <iostream>
 #include <errno.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdio.h>
-#include <stdarg.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
 #include <string>
 #include <string>
@@ -28,209 +26,218 @@
 #include "config.h"
 #include "config.h"
    									/*}}}*/
    									/*}}}*/
 
 
-using namespace std;
-
 // Global Error Object							/*{{{*/
 // Global Error Object							/*{{{*/
 /* If the implementation supports posix threads then the accessor function
 /* If the implementation supports posix threads then the accessor function
    is compiled to be thread safe otherwise a non-safe version is used. A
    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
    Per-Thread error object is maintained in much the same manner as libc
    manages errno */
    manages errno */
 #if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD)
 #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
 #else
- GlobalError *_GetErrorObj()
- {
-    static GlobalError *Obj = new GlobalError;
-    return Obj;
- }
+	GlobalError *_GetErrorObj() {
+		static GlobalError *Obj = new GlobalError;
+		return Obj;
+	}
 #endif
 #endif
 									/*}}}*/
 									/*}}}*/
-
 // GlobalError::GlobalError - Constructor				/*{{{*/
 // 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		/*{{{*/
 // 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			/*{{{*/
 // 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			/*{{{*/
 // 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			/*{{{*/
 // 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	/*{{{*/
 // 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 <apt-pkg/macros.h>
 
 
+#include <iostream>
+#include <list>
 #include <string>
 #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. 
 // The 'extra-ansi' syntax is used to help with collisions. 
 GlobalError *_GetErrorObj();
 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;
    std::vector<string> List;
+   Configuration::MatchAgainstConfig SilentIgnore("Dir::Ignore-Files-Silently");
    DIR *D = opendir(Dir.c_str());
    DIR *D = opendir(Dir.c_str());
    if (D == 0) 
    if (D == 0) 
    {
    {
@@ -307,6 +308,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
 	    {
 	    {
 	       if (Debug == true)
 	       if (Debug == true)
 		  std::clog << "Bad file: " << Ent->d_name << " → no extension" << std::endl;
 		  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;
 	       continue;
 	    }
 	    }
 	 }
 	 }
@@ -314,6 +316,8 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
 	 {
 	 {
 	    if (Debug == true)
 	    if (Debug == true)
 	       std::clog << "Bad file: " << Ent->d_name << " → bad extension »" << flExtension(Ent->d_name) << "«" << std::endl;
 	       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;
 	    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
 	// disable Moveable if we don't grow
 	if (Grow == 0)
 	if (Grow == 0)
-		Flags &= ~Moveable;
+		this->Flags &= ~Moveable;
 
 
 #ifndef __linux__
 #ifndef __linux__
 	// kfreebsd doesn't have mremap, so we use the fallback
 	// 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
 #endif
 
 
 #ifdef _POSIX_MAPPED_FILES
 #ifdef _POSIX_MAPPED_FILES
-	if ((Flags & Fallback) != Fallback) {
+	if ((this->Flags & Fallback) != Fallback) {
 		// Set the permissions.
 		// Set the permissions.
 		int Prot = PROT_READ;
 		int Prot = PROT_READ;
 		int Map = MAP_PRIVATE | MAP_ANONYMOUS;
 		int Map = MAP_PRIVATE | MAP_ANONYMOUS;
-		if ((Flags & ReadOnly) != ReadOnly)
+		if ((this->Flags & ReadOnly) != ReadOnly)
 			Prot |= PROT_WRITE;
 			Prot |= PROT_WRITE;
-		if ((Flags & Public) == Public)
+		if ((this->Flags & Public) == Public)
 			Map = MAP_SHARED | MAP_ANONYMOUS;
 			Map = MAP_SHARED | MAP_ANONYMOUS;
 
 
 		// use anonymous mmap() to get the memory
 		// use anonymous mmap() to get the memory
@@ -297,7 +297,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
    {
    {
       if(!Grow())
       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);
 			 "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
 	 return 0;
 	 return 0;
       }
       }
@@ -314,7 +314,7 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
    // Look for a matching pool entry
    // Look for a matching pool entry
    Pool *I;
    Pool *I;
    Pool *Empty = 0;
    Pool *Empty = 0;
-   for (I = Pools; I != Pools + PoolCount; I++)
+   for (I = Pools; I != Pools + PoolCount; ++I)
    {
    {
       if (I->ItemSize == 0)
       if (I->ItemSize == 0)
 	 Empty = I;
 	 Empty = I;
@@ -342,7 +342,11 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
    {
    {
       const unsigned long size = 20*1024;
       const unsigned long size = 20*1024;
       I->Count = size/ItemSize;
       I->Count = size/ItemSize;
+      Pool* oldPools = Pools;
       Result = RawAllocate(size,ItemSize);
       Result = RawAllocate(size,ItemSize);
+      if (Pools != oldPools)
+	 I += Pools - oldPools;
+
       // Does the allocation failed ?
       // Does the allocation failed ?
       if (Result == 0 && _error->PendingError())
       if (Result == 0 && _error->PendingError())
 	 return 0;
 	 return 0;
@@ -365,7 +369,7 @@ unsigned long DynamicMMap::WriteString(const char *String,
    if (Len == (unsigned long)-1)
    if (Len == (unsigned long)-1)
       Len = strlen(String);
       Len = strlen(String);
 
 
-   unsigned long Result = RawAllocate(Len+1,0);
+   unsigned long const Result = RawAllocate(Len+1,0);
 
 
    if (Result == 0 && _error->PendingError())
    if (Result == 0 && _error->PendingError())
       return 0;
       return 0;
@@ -395,16 +399,20 @@ bool DynamicMMap::Grow() {
 		return _error->Error(_("Unable to increase the size of the MMap as the "
 		return _error->Error(_("Unable to increase the size of the MMap as the "
 		                       "limit of %lu bytes is already reached."), Limit);
 		                       "limit of %lu bytes is already reached."), Limit);
 
 
-	unsigned long const newSize = WorkSpace + 1024*1024;
+	unsigned long const newSize = WorkSpace + GrowFactor;
 
 
 	if(Fd != 0) {
 	if(Fd != 0) {
 		Fd->Seek(newSize - 1);
 		Fd->Seek(newSize - 1);
 		char C = 0;
 		char C = 0;
 		Fd->Write(&C,sizeof(C));
 		Fd->Write(&C,sizeof(C));
 	}
 	}
+
+	unsigned long const poolOffset = Pools - ((Pool*) Base);
+
 	if ((Flags & Fallback) != Fallback) {
 	if ((Flags & Fallback) != Fallback) {
 #if defined(_POSIX_MAPPED_FILES) && defined(__linux__)
 #if defined(_POSIX_MAPPED_FILES) && defined(__linux__)
    #ifdef MREMAP_MAYMOVE
    #ifdef MREMAP_MAYMOVE
+
 		if ((Flags & Moveable) == Moveable)
 		if ((Flags & Moveable) == Moveable)
 			Base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE);
 			Base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE);
 		else
 		else
@@ -425,6 +433,7 @@ bool DynamicMMap::Grow() {
 			return false;
 			return false;
 	}
 	}
 
 
+	Pools =(Pool*) Base + poolOffset;
 	WorkSpace = newSize;
 	WorkSpace = newSize;
 	return true;
 	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
    // Store the IMS information
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
+   pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
    struct stat St;
    struct stat St;
    if (fstat(Pkg.Fd(),&St) != 0)
    if (fstat(Pkg.Fd(),&St) != 0)
       return _error->Errno("fstat","Failed to stat");
       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) {
 				Arch(Arch) {
    if (Arch == "native")
    if (Arch == "native")
       this->Arch = _config->Find("APT::Architecture");
       this->Arch = _config->Find("APT::Architecture");
+   Architectures = APT::Configuration::getArchitectures();
+   MultiArchEnabled = Architectures.size() > 1;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // ListParser::UniqFindTagWrite - Find the tag and write a unq string	/*{{{*/
 // ListParser::UniqFindTagWrite - Find the tag and write a unq string	/*{{{*/
@@ -104,7 +106,7 @@ string debListParser::Version()
 // ListParser::NewVersion - Fill in the version structure		/*{{{*/
 // ListParser::NewVersion - Fill in the version structure		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-bool debListParser::NewVersion(pkgCache::VerIterator Ver)
+bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
 {
 {
    // Parse the section
    // Parse the section
    Ver->Section = UniqFindTagWrite("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
 	 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
 	 it is downloaded only one time and installed only one time -- even if
 	 the architecture bound versions coming in and out on regular basis. */
 	 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)
       if (strcmp(Ver.Arch(true),"all") == 0)
 	 return true;
 	 return true;
-      else if (multiArch == true)
+      else if (MultiArchEnabled == true)
       {
       {
 	 // our pseudo packages have no size to not confuse the fetcher
 	 // our pseudo packages have no size to not confuse the fetcher
 	 Ver->Size = 0;
 	 Ver->Size = 0;
@@ -250,8 +251,8 @@ MD5SumValue debListParser::Description_md5()
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is called to update the package with any new information 
 /* This is called to update the package with any new information 
    that might be found in the section */
    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)
    if (Pkg->Section == 0)
       Pkg->Section = UniqFindTagWrite("Section");
       Pkg->Section = UniqFindTagWrite("Section");
@@ -331,8 +332,8 @@ unsigned short debListParser::VersionHash()
    Some of the above are obsolete (I think?) flag = hold-* and 
    Some of the above are obsolete (I think?) flag = hold-* and 
    status = post-inst-failed, removal-failed at least.
    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 *Start;
    const char *Stop;
    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
 /* This is the higher level depends parser. It takes a tag and generates
    a complete depends tree for the given version. */
    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 *Tag,unsigned int Type)
 {
 {
    const char *Start;
    const char *Start;
@@ -641,9 +642,6 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
    if (Section.Find(Tag,Start,Stop) == false)
    if (Section.Find(Tag,Start,Stop) == false)
       return true;
       return true;
 
 
-   static std::vector<std::string> const archs = APT::Configuration::getArchitectures();
-   static bool const multiArch = archs.size() <= 1;
-
    string Package;
    string Package;
    string const pkgArch = Ver.Arch(true);
    string const pkgArch = Ver.Arch(true);
    string Version;
    string Version;
@@ -655,13 +653,13 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
       if (Start == 0)
       if (Start == 0)
 	 return _error->Error("Problem parsing dependency %s",Tag);
 	 return _error->Error("Problem parsing dependency %s",Tag);
 
 
-      if (multiArch == true &&
+      if (MultiArchEnabled == true &&
 	  (Type == pkgCache::Dep::Conflicts ||
 	  (Type == pkgCache::Dep::Conflicts ||
 	   Type == pkgCache::Dep::DpkgBreaks ||
 	   Type == pkgCache::Dep::DpkgBreaks ||
 	   Type == pkgCache::Dep::Replaces))
 	   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)
 	    if (NewDepends(Ver,Package,*a,Version,Op,Type) == false)
 	       return false;
 	       return false;
       }
       }
@@ -676,7 +674,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
 // ListParser::ParseProvides - Parse the provides list			/*{{{*/
 // ListParser::ParseProvides - Parse the provides list			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
+bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 {
 {
    const char *Start;
    const char *Start;
    const char *Stop;
    const char *Stop;
@@ -713,14 +711,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
    if (Ver->MultiArch != pkgCache::Version::Foreign)
    if (Ver->MultiArch != pkgCache::Version::Foreign)
       return true;
       return true;
 
 
-   std::vector<string> const archs = APT::Configuration::getArchitectures();
-   if (archs.size() <= 1)
+   if (MultiArchEnabled == false)
       return true;
       return true;
 
 
    string const Package = Ver.ParentPkg().Name();
    string const Package = Ver.ParentPkg().Name();
    string const Version = Ver.VerStr();
    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)
       if (NewProvides(Ver, Package, *a, Version) == false)
 	 return false;
 	 return false;
@@ -760,7 +757,7 @@ bool debListParser::Step()
       if (Architecture.empty() == true)
       if (Architecture.empty() == true)
 	 return true;
 	 return true;
 
 
-      if (Arch.empty() == true)
+      if (Arch.empty() == true || MultiArchEnabled == false)
       {
       {
 	 if (APT::Configuration::checkArchitecture(Architecture) == true)
 	 if (APT::Configuration::checkArchitecture(Architecture) == true)
 	    return true;
 	    return true;
@@ -782,7 +779,7 @@ bool debListParser::Step()
 // ListParser::LoadReleaseInfo - Load the release information		/*{{{*/
 // ListParser::LoadReleaseInfo - Load the release information		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
+bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
 				    FileFd &File, string component)
 				    FileFd &File, string component)
 {
 {
    pkgTagFile Tags(&File, File.Size() + 256); // XXX
    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;
    pkgTagSection Section;
    unsigned long iOffset;
    unsigned long iOffset;
    string Arch;
    string Arch;
-   
+   std::vector<std::string> Architectures;
+   bool MultiArchEnabled;
+
    unsigned long UniqFindTagWrite(const char *Tag);
    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);
 		     unsigned int Type);
-   bool ParseProvides(pkgCache::VerIterator Ver);
+   bool ParseProvides(pkgCache::VerIterator &Ver);
    static bool GrabWord(string Word,WordList *List,unsigned char &Out);
    static bool GrabWord(string Word,WordList *List,unsigned char &Out);
    
    
    public:
    public:
@@ -49,19 +51,19 @@ class debListParser : public pkgCacheGenerator::ListParser
    virtual string Architecture();
    virtual string Architecture();
    virtual bool ArchitectureAll();
    virtual bool ArchitectureAll();
    virtual string Version();
    virtual string Version();
-   virtual bool NewVersion(pkgCache::VerIterator Ver);
+   virtual bool NewVersion(pkgCache::VerIterator &Ver);
    virtual string Description();
    virtual string Description();
    virtual string DescriptionLanguage();
    virtual string DescriptionLanguage();
    virtual MD5SumValue Description_md5();
    virtual MD5SumValue Description_md5();
    virtual unsigned short VersionHash();
    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 Offset() {return iOffset;};
    virtual unsigned long Size() {return Section.size();};
    virtual unsigned long Size() {return Section.size();};
 
 
    virtual bool Step();
    virtual bool Step();
    
    
-   bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File,
+   bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File,
 			string section);
 			string section);
    
    
    static const char *ParseDepends(const char *Start,const char *Stop,
    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);
    Update(Pkg);
    AddSizes(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)
    if (AutoInst == false)
       return;
       return;
 
 
@@ -1453,6 +1457,9 @@ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
 /* */
 /* */
 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 {
 {
+   if (unlikely(Pkg.end() == true))
+      return;
+
    ActionGroup group(*this);
    ActionGroup group(*this);
 
 
    RemoveSizes(Pkg);
    RemoveSizes(Pkg);
@@ -1466,12 +1473,17 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
    
    
    AddStates(Pkg);
    AddStates(Pkg);
    AddSizes(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		/*{{{*/
 // DepCache::SetCandidateVersion - Change the candidate version		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
+void pkgDepCache::SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo)
 {
 {
    ActionGroup group(*this);
    ActionGroup group(*this);
 
 
@@ -1489,6 +1501,28 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
    AddStates(Pkg);
    AddStates(Pkg);
    Update(Pkg);
    Update(Pkg);
    AddSizes(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)
 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
 /* The default just returns the highest available version that is not
    a source and automatic. */
    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 
    /* Not source/not automatic versions cannot be a candidate version 
       unless they are already installed */
       unless they are already installed */
@@ -1586,7 +1620,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
 // Policy::IsImportantDep - True if the dependency is important		/*{{{*/
 // Policy::IsImportantDep - True if the dependency is important		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
+bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep)
 {
 {
    if(Dep.IsCritical())
    if(Dep.IsCritical())
       return true;
       return true;
@@ -1605,54 +1639,6 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
    else if(Dep->Type == pkgCache::Dep::Suggests)
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);
      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;
    return false;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 10 - 20
apt-pkg/depcache.h

@@ -38,11 +38,10 @@
 #ifndef PKGLIB_DEPCACHE_H
 #ifndef PKGLIB_DEPCACHE_H
 #define PKGLIB_DEPCACHE_H
 #define PKGLIB_DEPCACHE_H
 
 
-
+#include <apt-pkg/configuration.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/progress.h>
 #include <apt-pkg/progress.h>
-
-#include <regex.h>
+#include <apt-pkg/error.h>
 
 
 #include <vector>
 #include <vector>
 #include <memory>
 #include <memory>
@@ -184,22 +183,13 @@ class pkgDepCache : protected pkgCache::Namespace
    /** \brief Returns \b true for packages matching a regular
    /** \brief Returns \b true for packages matching a regular
     *  expression in APT::NeverAutoRemove.
     *  expression in APT::NeverAutoRemove.
     */
     */
-   class DefaultRootSetFunc : public InRootSetFunc
+   class DefaultRootSetFunc : public InRootSetFunc, public Configuration::MatchAgainstConfig
    {
    {
-     std::vector<regex_t *> rootSetRegexp;
-     bool constructedSuccessfully;
-
    public:
    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
    struct StateCache
@@ -266,8 +256,8 @@ class pkgDepCache : protected pkgCache::Namespace
    {
    {
       public:
       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() {};
       virtual ~Policy() {};
    };
    };
@@ -344,7 +334,7 @@ class pkgDepCache : protected pkgCache::Namespace
    inline pkgVersioningSystem &VS() {return *Cache->VS;};
    inline pkgVersioningSystem &VS() {return *Cache->VS;};
    
    
    // Policy implementation
    // 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 bool IsImportantDep(DepIterator Dep) {return LocalPolicy->IsImportantDep(Dep);};
    inline Policy &GetPolicy() {return *LocalPolicy;};
    inline Policy &GetPolicy() {return *LocalPolicy;};
    
    
@@ -405,7 +395,7 @@ class pkgDepCache : protected pkgCache::Namespace
 		    bool ForceImportantDeps = false);
 		    bool ForceImportantDeps = false);
 
 
    void SetReInstall(PkgIterator const &Pkg,bool To);
    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. */
    /** Set the "is automatically installed" flag of Pkg. */
    void MarkAuto(const PkgIterator &Pkg, bool Auto);
    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::Terminal","term.log");
    Cnf.Set("Dir::Log::History","history.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
    // Translation
    Cnf.Set("APT::Acquire::Translation", "environment");
    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 \
 	 srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
 	 pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
 	 pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
 	 indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
 	 indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
-	 aptconfiguration.cc cacheset.cc
+	 aptconfiguration.cc
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
 	  orderlist.h sourcelist.h packagemanager.h tagfile.h \
 	  orderlist.h sourcelist.h packagemanager.h tagfile.h \
 	  init.h pkgcache.h version.h progress.h pkgrecords.h \
 	  init.h pkgcache.h version.h progress.h pkgrecords.h \
 	  acquire.h acquire-worker.h acquire-item.h acquire-method.h \
 	  acquire.h acquire-worker.h acquire-item.h acquire-method.h \
 	  clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
 	  clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
 	  pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
 	  pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
-          vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \
-	  cacheset.h
+	  vendorlist.h cdrom.h indexcopy.h aptconfiguration.h
 
 
 # Source code for the debian specific components
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..
 # In theory the deb headers do not need to be exported..

+ 2 - 1
apt-pkg/orderlist.cc

@@ -117,7 +117,8 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
       return false;
       return false;
 
 
    // Skip Packages that need configure only.
    // 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)
        Cache[Pkg].Keep() == true)
       return false;
       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…
       // configured we don't need to unpack it again…
       PkgIterator const P = Pkg.Group().FindPkg("all");
       PkgIterator const P = Pkg.Group().FindPkg("all");
       if (List->IsFlag(P,pkgOrderList::UnPacked) != true &&
       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)
 	 if (SmartUnPack(P) == false)
 	    return 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					/*{{{*/
 // Cache::ReMap - Reopen the cache file					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* If the file is already closed then this will open it open it. */
 /* 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.
    // Apply the typecasts.
    HeaderP = (Header *)Map.Data();
    HeaderP = (Header *)Map.Data();
@@ -135,6 +135,9 @@ bool pkgCache::ReMap()
    StringItemP = (StringItem *)Map.Data();
    StringItemP = (StringItem *)Map.Data();
    StrP = (char *)Map.Data();
    StrP = (char *)Map.Data();
 
 
+   if (Errorchecks == false)
+      return true;
+
    if (Map.Size() == 0 || HeaderP == 0)
    if (Map.Size() == 0 || HeaderP == 0)
       return _error->Error(_("Empty package cache"));
       return _error->Error(_("Empty package cache"));
    
    
@@ -307,7 +310,7 @@ const char *pkgCache::Priority(unsigned char Prio)
 // GrpIterator::FindPkg - Locate a package by arch			/*{{{*/
 // GrpIterator::FindPkg - Locate a package by arch			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
 /* 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))
 	if (unlikely(IsGood() == false || S->FirstPackage == 0))
 		return PkgIterator(*Owner, 0);
 		return PkgIterator(*Owner, 0);
 
 
@@ -346,7 +349,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
 // GrpIterator::FindPreferredPkg - Locate the "best" package		/*{{{*/
 // GrpIterator::FindPreferredPkg - Locate the "best" package		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
 /* 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");
 	pkgCache::PkgIterator Pkg = FindPkg("native");
 	if (Pkg.end() == false)
 	if (Pkg.end() == false)
 		return Pkg;
 		return Pkg;
@@ -367,7 +370,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() {
 /* Returns an End-Pointer on error, pointer to the package otherwise.
 /* 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
    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) */
    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 ||
 	if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
 	    LastPkg.end() == true))
 	    LastPkg.end() == true))
 		return PkgIterator(*Owner, 0);
 		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
 /* Currently critical deps are defined as depends, predepends and
    conflicts (including dpkg's Breaks fields). */
    conflicts (including dpkg's Breaks fields). */
-bool pkgCache::DepIterator::IsCritical()
+bool pkgCache::DepIterator::IsCritical() const
 {
 {
    if (S->Type == pkgCache::Dep::Conflicts ||
    if (S->Type == pkgCache::Dep::Conflicts ||
        S->Type == pkgCache::Dep::DpkgBreaks ||
        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 
    In Conjunction with the DepCache the value of Result may not be 
    super-good since the policy may have made it uninstallable. Using
    super-good since the policy may have made it uninstallable. Using
    AllTargets is better in this case. */
    AllTargets is better in this case. */
-bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
+bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const
 {
 {
    Result = TargetPkg();
    Result = TargetPkg();
    
    
@@ -577,7 +580,7 @@ bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
    provides. It includes every possible package-version that could satisfy
    provides. It includes every possible package-version that could satisfy
    the dependency. The last item in the list has a 0. The resulting pointer
    the dependency. The last item in the list has a 0. The resulting pointer
    must be delete [] 'd */
    must be delete [] 'd */
-pkgCache::Version **pkgCache::DepIterator::AllTargets()
+pkgCache::Version **pkgCache::DepIterator::AllTargets() const
 {
 {
    Version **Res = 0;
    Version **Res = 0;
    unsigned long Size =0;
    unsigned long Size =0;

+ 1 - 1
apt-pkg/pkgcache.h

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

+ 184 - 62
apt-pkg/pkgcachegen.cc

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

+ 34 - 12
apt-pkg/pkgcachegen.h

@@ -23,6 +23,8 @@
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>
 
 
+#include <set>
+
 class pkgSourceList;
 class pkgSourceList;
 class OpProgress;
 class OpProgress;
 class MMap;
 class MMap;
@@ -31,16 +33,34 @@ class pkgIndexFile;
 class pkgCacheGenerator							/*{{{*/
 class pkgCacheGenerator							/*{{{*/
 {
 {
    private:
    private:
-   
+
    pkgCache::StringItem *UniqHash[26];
    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:
    public:
    
    
    class ListParser;
    class ListParser;
    friend 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:
    protected:
-   
+
    DynamicMMap &Map;
    DynamicMMap &Map;
    pkgCache Cache;
    pkgCache Cache;
    OpProgress *Progress;
    OpProgress *Progress;
@@ -82,6 +102,8 @@ class pkgCacheGenerator							/*{{{*/
 			MMap **OutMap = 0,bool AllowMem = false);
 			MMap **OutMap = 0,bool AllowMem = false);
    static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap);
    static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap);
 
 
+   void ReMap(void const * const oldMap, void const * const newMap);
+
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
    ~pkgCacheGenerator();
    ~pkgCacheGenerator();
 };
 };
@@ -103,12 +125,12 @@ class pkgCacheGenerator::ListParser
 
 
    inline unsigned long WriteUniqString(string S) {return Owner->WriteUniqString(S);};
    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 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,
 		   const string &Version,unsigned int Op,
 		   unsigned int Type);
 		   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);
 		    const string &PkgArch, const string &Version);
    
    
    public:
    public:
@@ -118,13 +140,13 @@ class pkgCacheGenerator::ListParser
    virtual string Architecture() = 0;
    virtual string Architecture() = 0;
    virtual bool ArchitectureAll() = 0;
    virtual bool ArchitectureAll() = 0;
    virtual string Version() = 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 Description() = 0;
    virtual string DescriptionLanguage() = 0;
    virtual string DescriptionLanguage() = 0;
    virtual MD5SumValue Description_md5() = 0;
    virtual MD5SumValue Description_md5() = 0;
    virtual unsigned short VersionHash() = 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 Offset() = 0;
    virtual unsigned long Size() = 0;
    virtual unsigned long Size() = 0;
    
    
@@ -132,7 +154,7 @@ class pkgCacheGenerator::ListParser
    
    
    inline bool HasFileDeps() {return FoundFileDeps;};
    inline bool HasFileDeps() {return FoundFileDeps;};
    virtual bool CollectFileProvides(pkgCache &Cache,
    virtual bool CollectFileProvides(pkgCache &Cache,
-				    pkgCache::VerIterator Ver) {return true;};
+				    pkgCache::VerIterator &Ver) {return true;};
 
 
    ListParser() : FoundFileDeps(false) {};
    ListParser() : FoundFileDeps(false) {};
    virtual ~ListParser() {};
    virtual ~ListParser() {};

+ 1 - 1
apt-pkg/policy.h

@@ -76,7 +76,7 @@ class pkgPolicy : public pkgDepCache::Policy
 
 
    // Things for the cache interface.
    // Things for the cache interface.
    virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg);
    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();
    bool InitDefaults();
    
    
    pkgPolicy(pkgCache *Owner);
    pkgPolicy(pkgCache *Owner);

+ 11 - 10
cmdline/apt-cache.cc

@@ -29,7 +29,8 @@
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
-#include <apt-pkg/cacheset.h>
+
+#include "cacheset.h"
 
 
 #include <config.h>
 #include <config.h>
 #include <apti18n.h>
 #include <apti18n.h>
@@ -1867,21 +1868,21 @@ int main(int argc,const char *argv[])					/*{{{*/
    }
    }
    
    
    // Deal with stdout not being a tty
    // 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");
       _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)
    if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
       CmdL.DispatchArg(CmdsB);
       CmdL.DispatchArg(CmdsB);
 
 
    // Print any errors or warnings found during parsing
    // 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();
       _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();
       return ShowHelp();
 
 
    // Deal with stdout not being a tty
    // 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");
       _config->Set("quiet","1");
    
    
    // Match the operation
    // Match the operation
    CmdL.DispatchArg(Cmds);
    CmdL.DispatchArg(Cmds);
 
 
    // Print any errors or warnings found during parsing
    // 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();
       _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/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
 #include <apt-pkg/versionmatch.h>
-#include <apt-pkg/cacheset.h>
 
 
 #include <config.h>
 #include <config.h>
 #include <apti18n.h>
 #include <apti18n.h>
 
 
 #include "acqprogress.h"
 #include "acqprogress.h"
+#include "cacheset.h"
 
 
 #include <set>
 #include <set>
 #include <locale.h>
 #include <locale.h>
@@ -609,6 +609,253 @@ void Stats(ostream &out,pkgDepCache &Dep)
 	       Dep.BadCount());
 	       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				/*{{{*/
 // CacheFile::NameComp - QSort compare by name				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
@@ -1073,219 +1320,35 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    return 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
 /* This used to be inlined in DoInstall, but with the advent of regex package
    name matching it was split out.. */
    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,
 		  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)
    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)
    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;
    return true;
 }
 }
@@ -1624,61 +1687,6 @@ bool DoUpgrade(CommandLine &CmdL)
    return InstallPackages(Cache,true);
    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			/*{{{*/
 // DoInstall - Install packages from the command line			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Install named packages */
 /* Install named packages */
@@ -1694,140 +1702,69 @@ bool DoInstall(CommandLine &CmdL)
    if (Cache->BrokenCount() != 0)
    if (Cache->BrokenCount() != 0)
       BrokenFix = true;
       BrokenFix = true;
    
    
-   unsigned int AutoMarkChanged = 0;
-   unsigned int ExpectedInst = 0;
-   unsigned int Packages = 0;
    pkgProblemResolver Fix(Cache);
    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)
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
    else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
    {
    {
       _config->Set("APT::Get::Purge", true);
       _config->Set("APT::Get::Purge", true);
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    }
    }
    else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
    else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
    {
    {
       _config->Set("APT::Get::AutomaticRemove", "true");
       _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
       /* 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
 	 problems. This is if the user invoked install without -f and gave
 	 packages */
 	 packages */
@@ -1874,7 +1811,7 @@ bool DoInstall(CommandLine &CmdL)
 
 
    /* Print out a list of packages that are going to be installed extra
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
       to what the user asked */
-   if (Cache->InstCount() != ExpectedInst)
+   if (Cache->InstCount() != verset[MOD_INSTALL].size())
    {
    {
       string List;
       string List;
       string VersionsList;
       string VersionsList;
@@ -1993,14 +1930,15 @@ bool DoInstall(CommandLine &CmdL)
    // if nothing changed in the cache, but only the automark information
    // if nothing changed in the cache, but only the automark information
    // we write the StateFile here, otherwise it will be written in 
    // we write the StateFile here, otherwise it will be written in 
    // cache.commit()
    // cache.commit()
-   if (AutoMarkChanged > 0 &&
+   if (InstallAction.AutoMarkChanged > 0 &&
        Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
        Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
        Cache->BadCount() == 0 &&
        Cache->BadCount() == 0 &&
        _config->FindB("APT::Get::Simulate",false) == false)
        _config->FindB("APT::Get::Simulate",false) == false)
       Cache->writeStateFile(NULL);
       Cache->writeStateFile(NULL);
 
 
    // See if we need to prompt
    // 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,false);
 
 
    return InstallPackages(Cache,false);   
    return InstallPackages(Cache,false);   
@@ -2584,7 +2522,6 @@ bool DoBuildDep(CommandLine &CmdL)
       }
       }
       
       
       // Install the requested packages
       // Install the requested packages
-      unsigned int ExpectedInst = 0;
       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
       pkgProblemResolver Fix(Cache);
       pkgProblemResolver Fix(Cache);
       bool skipAlternatives = false; // skip remaining alternatives in an or group
       bool skipAlternatives = false; // skip remaining alternatives in an or group
@@ -2615,7 +2552,7 @@ bool DoBuildDep(CommandLine &CmdL)
              */
              */
             if (IV.end() == false && 
             if (IV.end() == false && 
                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
                 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
 	 else // BuildDep || BuildDepIndep
          {
          {
@@ -2731,7 +2668,7 @@ bool DoBuildDep(CommandLine &CmdL)
             if (_config->FindB("Debug::BuildDeps",false) == true)
             if (_config->FindB("Debug::BuildDeps",false) == true)
                cout << "  Trying to install " << (*D).Package << endl;
                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
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
                skipAlternatives = hasAlternatives;
@@ -3021,7 +2958,7 @@ int main(int argc,const char *argv[])					/*{{{*/
    }
    }
 
 
    // Deal with stdout not being a tty
    // 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");
       _config->Set("quiet","1");
 
 
    // Setup the output streams
    // Setup the output streams
@@ -3042,13 +2979,11 @@ int main(int argc,const char *argv[])					/*{{{*/
    CmdL.DispatchArg(Cmds);
    CmdL.DispatchArg(Cmds);
 
 
    // Print any errors or warnings found during parsing
    // 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();
       _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>
 #include <apt-pkg/pkgcache.h>
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 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 PackageSet : public std::set<pkgCache::PkgIterator> {		/*{{{*/
 /** \class APT::PackageSet
 /** \class APT::PackageSet
 
 
@@ -28,7 +70,7 @@ class PackageSet : public std::set<pkgCache::PkgIterator> {		/*{{{*/
     pkgCache. */
     pkgCache. */
 public:									/*{{{*/
 public:									/*{{{*/
 	/** \brief smell like a pkgCache::PkgIterator */
 	/** \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:
 	public:
 		const_iterator(std::set<pkgCache::PkgIterator>::const_iterator x) :
 		const_iterator(std::set<pkgCache::PkgIterator>::const_iterator x) :
 			 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
 	// 103. set::iterator is required to be modifiable, but this allows modification of keys
 	typedef APT::PackageSet::const_iterator iterator;
 	typedef APT::PackageSet::const_iterator iterator;
+									/*}}}*/
 
 
 	using std::set<pkgCache::PkgIterator>::insert;
 	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(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
 	/** \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.
 	    packages chosen cause of the given package.
 	    \param Cache the packages are in
 	    \param Cache the packages are in
 	    \param pattern regular expression for package names
 	    \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) {
 	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
 	/** \brief returns all packages specified by a string
 
 
 	    \param Cache the packages are in
 	    \param Cache the packages are in
 	    \param string String the package name(s) should be extracted from
 	    \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) {
 	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
 	/** \brief returns all packages specified on the commandline
@@ -97,11 +166,11 @@ public:									/*{{{*/
 	    No special package command is supported, just plain names.
 	    No special package command is supported, just plain names.
 	    \param Cache the packages are in
 	    \param Cache the packages are in
 	    \param cmdline Command line the package names should be extracted from
 	    \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) {
 	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 {
 	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) {};
 		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(
 	static std::map<unsigned short, PackageSet> GroupedFromCommandLine(
 		pkgCacheFile &Cache, const char **cmdline,
 		pkgCacheFile &Cache, const char **cmdline,
 		std::list<PackageSet::Modifier> const &mods,
 		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(
 	static std::map<unsigned short, PackageSet> GroupedFromCommandLine(
 		pkgCacheFile &Cache, const char **cmdline,
 		pkgCacheFile &Cache, const char **cmdline,
 		std::list<PackageSet::Modifier> const &mods,
 		std::list<PackageSet::Modifier> const &mods,
 		unsigned short const &fallback) {
 		unsigned short const &fallback) {
-		std::ostream out (std::ofstream("/dev/null").rdbuf());
+		CacheSetHelper helper;
 		return APT::PackageSet::GroupedFromCommandLine(Cache, cmdline,
 		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> {		/*{{{*/
 class VersionSet : public std::set<pkgCache::VerIterator> {		/*{{{*/
@@ -134,7 +223,7 @@ class VersionSet : public std::set<pkgCache::VerIterator> {		/*{{{*/
     pkgCache. */
     pkgCache. */
 public:									/*{{{*/
 public:									/*{{{*/
 	/** \brief smell like a pkgCache::VerIterator */
 	/** \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:
 	public:
 		const_iterator(std::set<pkgCache::VerIterator>::const_iterator x) :
 		const_iterator(std::set<pkgCache::VerIterator>::const_iterator x) :
 			 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 bool Pseudo() const { return (**this).Pseudo(); };
 		inline pkgCache::VerFileIterator NewestFile() const { return (**this).NewestFile(); };
 		inline pkgCache::VerFileIterator NewestFile() const { return (**this).NewestFile(); };
 	};
 	};
+									/*}}}*/
 	// 103. set::iterator is required to be modifiable, but this allows modification of keys
 	// 103. set::iterator is required to be modifiable, but this allows modification of keys
 	typedef APT::VersionSet::const_iterator iterator;
 	typedef APT::VersionSet::const_iterator iterator;
 
 
 	using std::set<pkgCache::VerIterator>::insert;
 	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(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 */
 	/** \brief specifies which version(s) will be returned if non is given */
 	enum Version {
 	enum Version {
@@ -198,41 +289,86 @@ public:									/*{{{*/
 	    non specifically requested  and executes regex's if needed on names.
 	    non specifically requested  and executes regex's if needed on names.
 	    \param Cache the packages and versions are in
 	    \param Cache the packages and versions are in
 	    \param cmdline Command line the versions should be extracted from
 	    \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,
 	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,
 	static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
 			APT::VersionSet::Version const &fallback) {
 			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) {
 	static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
 		return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST);
 		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:								/*{{{*/
 protected:								/*{{{*/
 
 
 	/** \brief returns the candidate version of the package
 	/** \brief returns the candidate version of the package
 
 
 	    \param Cache to be used to query for information
 	    \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,
 	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
 	/** \brief returns the installed version of the package
 
 
 	    \param Cache to be used to query for information
 	    \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,
 	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
 PROGRAM=apt-cache
 SLIBS = -lapt-pkg $(INTLLIBS)
 SLIBS = -lapt-pkg $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-cache.cc
+SOURCE = apt-cache.cc cacheset.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)
 
 
 # The apt-get program
 # The apt-get program
 PROGRAM=apt-get
 PROGRAM=apt-get
 SLIBS = -lapt-pkg -lutil $(INTLLIBS)
 SLIBS = -lapt-pkg -lutil $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-get.cc acqprogress.cc
+SOURCE = apt-get.cc acqprogress.cc cacheset.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)
 
 
 # The apt-config program
 # 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:
   * methods/ftp.h:
     - Handle different logins on the same server (Closes: #586904).
     - Handle different logins on the same server (Closes: #586904).
   * apt-pkg/deb/deblistparser.cc:
   * apt-pkg/deb/deblistparser.cc:
@@ -13,7 +55,7 @@ apt (0.7.26~exp8) experimental; urgency=low
   * debian/control:
   * debian/control:
     - Set Standards-Version to 3.9.0
     - 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
 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>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Luca Bruno <lethalman88@gmail.com>, Julian Andres Klode <jak@debian.org>
  Luca Bruno <lethalman88@gmail.com>, Julian Andres Klode <jak@debian.org>
 Standards-Version: 3.9.0
 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
 Build-Conflicts: autoconf2.13, automake1.4
 
 
 Package: apt
 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
      will be looked up in
      <filename>/tmp/staging/var/lib/dpkg/status</filename>.
      <filename>/tmp/staging/var/lib/dpkg/status</filename>.
    </para>
    </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>
  
  
  <refsect1><title>APT in DSelect</title>
  <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)
 include $(PROGRAM_H)
 
 
 # Program for testing CommandLine reconstruction
 # Program for testing CommandLine reconstruction
-PROGRAM = commandlineasstring${BASENAME}
+PROGRAM = CommandlineAsString${BASENAME}
 SLIBS = -lapt-pkg
 SLIBS = -lapt-pkg
 SOURCE = commandlineasstring_test.cc
 SOURCE = commandlineasstring_test.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)
 
 
 # Program for testing debians version comparing
 # Program for testing debians version comparing
-PROGRAM = compareversion${BASENAME}
+PROGRAM = CompareVersion${BASENAME}
 SLIBS = -lapt-pkg
 SLIBS = -lapt-pkg
 SOURCE = compareversion_test.cc
 SOURCE = compareversion_test.cc
 include $(PROGRAM_H)
 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), "
 		"apt (>= 0.7.25), "
 		"not-for-me [ !dsk ], "
 		"not-for-me [ !dsk ], "
 		"only-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), "
 		"overlord-dev:any (= 7.15.3~) | overlord-dev:native (>> 7.15.5), "
 	;
 	;
 
 
@@ -100,6 +106,68 @@ test:
 		Start++;
 		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);
 	Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch);
 	if (StripMultiArch == true)
 	if (StripMultiArch == true)
 		equals("overlord-dev", Package);
 		equals("overlord-dev", Package);