merge with debian-experimental-ma
authorDavid Kalnischkies <kalnischkies@gmail.com>
Mon, 5 Jul 2010 10:06:45 +0000 (12:06 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Mon, 5 Jul 2010 10:06:45 +0000 (12:06 +0200)
34 files changed:
apt-pkg/algorithms.h
apt-pkg/aptconfiguration.cc
apt-pkg/cachefile.cc
apt-pkg/cachefile.h
apt-pkg/cacheiterators.h
apt-pkg/cacheset.cc [deleted file]
apt-pkg/contrib/configuration.cc
apt-pkg/contrib/configuration.h
apt-pkg/contrib/error.cc
apt-pkg/contrib/error.h
apt-pkg/contrib/fileutl.cc
apt-pkg/contrib/mmap.cc
apt-pkg/deb/deblistparser.cc
apt-pkg/deb/deblistparser.h
apt-pkg/depcache.cc
apt-pkg/depcache.h
apt-pkg/init.cc
apt-pkg/makefile
apt-pkg/orderlist.cc
apt-pkg/packagemanager.cc
apt-pkg/pkgcache.cc
apt-pkg/pkgcachegen.cc
apt-pkg/policy.h
cmdline/apt-cache.cc
cmdline/apt-cdrom.cc
cmdline/apt-get.cc
cmdline/cacheset.cc [new file with mode: 0644]
cmdline/cacheset.h [moved from apt-pkg/cacheset.h with 54% similarity]
cmdline/makefile
debian/changelog
debian/control
doc/apt.conf.5.xml
test/libapt/globalerror_test.cc [new file with mode: 0644]
test/libapt/makefile

index cee30b6..cf4a98c 100644 (file)
@@ -48,7 +48,7 @@ class pkgSimulate : public pkgPackageManager                          /*{{{*/
       pkgDepCache *Cache;
       public:
       
-      virtual VerIterator GetCandidateVer(PkgIterator Pkg)
+      virtual VerIterator GetCandidateVer(PkgIterator const &Pkg)
       {
         return (*Cache)[Pkg].CandidateVerIter(*Cache);
       }
index 0c050d9..44f1f31 100644 (file)
@@ -10,6 +10,7 @@
 // Include Files                                                       /*{{{*/
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/strutl.h>
@@ -196,6 +197,9 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
        // it was undocumented and so it should be not very widthly used
        string const oldAcquire = _config->Find("APT::Acquire::Translation","");
        if (oldAcquire.empty() == false && oldAcquire != "environment") {
+               // TRANSLATORS: the two %s are APT configuration options
+               _error->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
+                               "APT::Acquire::Translation", "Acquire::Languages");
                if (oldAcquire != "none")
                        codes.push_back(oldAcquire);
                codes.push_back("en");
index 0159838..964c5bd 100644 (file)
@@ -28,7 +28,7 @@
 // ---------------------------------------------------------------------
 /* */
 pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL),
-                               Policy(NULL), SrcList(NULL)
+                               SrcList(NULL), Policy(NULL)
 {
 }
                                                                        /*}}}*/
index 63bc3de..09d3ec2 100644 (file)
 
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/acquire.h>
+#include <apt-pkg/policy.h>
 #include <apt-pkg/sourcelist.h>
 
-class pkgPolicy;
-class pkgSourceList;
 class pkgCacheFile
 {
    protected:
@@ -65,6 +64,11 @@ class pkgCacheFile
    inline pkgPolicy* GetPolicy() { BuildPolicy(); return Policy; };
    inline pkgSourceList* GetSourceList() { BuildSourceList(); return SrcList; };
 
+   inline bool IsPkgCacheBuilt() const { return (Cache != NULL); };
+   inline bool IsDepCacheBuilt() const { return (DCache != NULL); };
+   inline bool IsPolicyBuilt() const { return (Policy != NULL); };
+   inline bool IsSrcListBuilt() const { return (SrcList != NULL); };
+
    pkgCacheFile();
    virtual ~pkgCacheFile();
 };
index f0b40db..dfe5707 100644 (file)
@@ -30,6 +30,8 @@
 #ifndef PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 #include<iterator>
+
+#include<string.h>
 // abstract Iterator template                                          /*{{{*/
 /* This template provides the very basic iterator methods we
    need to have for doing some walk-over-the-cache magic */
@@ -103,13 +105,13 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
 
        inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
        inline PkgIterator PackageList() const;
-       PkgIterator FindPkg(string Arch = "any");
+       PkgIterator FindPkg(string Arch = "any") const;
        /** \brief find the package with the "best" architecture
 
            The best architecture is either the "native" or the first
            in the list of Architectures which is not an end-Pointer */
-       PkgIterator FindPreferredPkg();
-       PkgIterator NextPkg(PkgIterator const &Pkg);
+       PkgIterator FindPreferredPkg() const;
+       PkgIterator NextPkg(PkgIterator const &Pkg) const;
 
        // Constructors
        inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator<Group, GrpIterator>(Owner, Trg), HashIndex(0) {
@@ -183,6 +185,13 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 
        // Comparison
        int CompareVer(const VerIterator &B) const;
+       /** \brief compares two version and returns if they are similar
+
+           This method should be used to identify if two pseudo versions are
+           refering to the same "real" version */
+       inline bool SimilarVer(const VerIterator &B) const {
+               return (B.end() == false && S->Hash == B->Hash && strcmp(VerStr(), B.VerStr()) == 0);
+       };
 
        // Accessors
        inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;};
@@ -263,17 +272,17 @@ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> {
 
        // Accessors
        inline const char *TargetVer() const {return S->Version == 0?0:Owner->StrP + S->Version;};
-       inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + S->Package);};
-       inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;};
-       inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + S->ParentVer);};
-       inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);};
-       inline bool Reverse() {return Type == DepRev;};
-       bool IsCritical();
+       inline PkgIterator TargetPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->Package);};
+       inline PkgIterator SmartTargetPkg() const {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;};
+       inline VerIterator ParentVer() const {return VerIterator(*Owner,Owner->VerP + S->ParentVer);};
+       inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);};
+       inline bool Reverse() const {return Type == DepRev;};
+       bool IsCritical() const;
        void GlobOr(DepIterator &Start,DepIterator &End);
-       Version **AllTargets();
-       bool SmartTargetPkg(PkgIterator &Result);
-       inline const char *CompType() {return Owner->CompType(S->CompareOp);};
-       inline const char *DepType() {return Owner->DepType(S->Type);};
+       Version **AllTargets() const;
+       bool SmartTargetPkg(PkgIterator &Result) const;
+       inline const char *CompType() const {return Owner->CompType(S->CompareOp);};
+       inline const char *DepType() const {return Owner->DepType(S->Type);};
 
        inline DepIterator(pkgCache &Owner, Dependency *Trg, Version* = 0) :
                Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepVer) {
@@ -306,9 +315,9 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
        // Accessors
        inline const char *Name() const {return Owner->StrP + Owner->PkgP[S->ParentPkg].Name;};
        inline const char *ProvideVersion() const {return S->ProvideVersion == 0?0:Owner->StrP + S->ProvideVersion;};
-       inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);};
-       inline VerIterator OwnerVer() {return VerIterator(*Owner,Owner->VerP + S->Version);};
-       inline PkgIterator OwnerPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);};
+       inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);};
+       inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);};
+       inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);};
 
        inline PrvIterator() : Iterator<Provides, PrvIterator>(), Type(PrvVer) {};
 
diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc
deleted file mode 100644 (file)
index 43ade4b..0000000
+++ /dev/null
@@ -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();
-}
-                                                                       /*}}}*/
-}
index 9129d92..81cc87d 100644 (file)
@@ -843,3 +843,46 @@ bool ReadConfigDir(Configuration &Conf,const string &Dir,
    return true;
 }
                                                                        /*}}}*/
+// MatchAgainstConfig Constructor                                      /*{{{*/
+Configuration::MatchAgainstConfig::MatchAgainstConfig(char const * Config)
+{
+   std::vector<std::string> const strings = _config->FindVector(Config);
+   for (std::vector<std::string>::const_iterator s = strings.begin();
+       s != strings.end(); ++s)
+   {
+      regex_t *p = new regex_t;
+      if (regcomp(p, s->c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0)
+        patterns.push_back(p);
+      else
+      {
+        regfree(p);
+        delete p;
+        _error->Warning("Regex compilation error for '%s' in configuration option '%s'",
+                               s->c_str(), Config);
+      }
+    }
+
+}
+                                                                       /*}}}*/
+// MatchAgainstConfig Destructor                                       /*{{{*/
+Configuration::MatchAgainstConfig::~MatchAgainstConfig()
+{
+   for(std::vector<regex_t *>::const_iterator p = patterns.begin();
+       p != patterns.end(); ++p)
+   {
+      regfree(*p);
+      delete *p;
+   }
+}
+                                                                       /*}}}*/
+// MatchAgainstConfig::Match - returns true if a pattern matches       /*{{{*/
+bool Configuration::MatchAgainstConfig::Match(char const * str) const
+{
+   for(std::vector<regex_t *>::const_iterator p = patterns.begin();
+       p != patterns.end(); ++p)
+      if (regexec(*p, str, 0, 0, 0) == 0)
+        return true;
+
+   return false;
+}
+                                                                       /*}}}*/
index 2494c1d..cbe18e4 100644 (file)
@@ -28,7 +28,7 @@
 #ifndef PKGLIB_CONFIGURATION_H
 #define PKGLIB_CONFIGURATION_H
 
-
+#include <regex.h>
 
 #include <string>
 #include <vector>
@@ -104,6 +104,23 @@ class Configuration
    Configuration(const Item *Root);
    Configuration();
    ~Configuration();
+
+   /** \brief match a string against a configurable list of patterns */
+   class MatchAgainstConfig
+   {
+     std::vector<regex_t *> patterns;
+
+   public:
+     MatchAgainstConfig(char const * Config);
+     virtual ~MatchAgainstConfig();
+
+     /** \brief Returns \b true for a string matching one of the patterns */
+     bool Match(char const * str) const;
+     bool Match(std::string const &str) const { return Match(str.c_str()); };
+
+     /** \brief returns if the matcher setup was successful */
+     bool wasConstructedSuccessfully() const { return patterns.empty() == false; }
+   };
 };
 
 extern Configuration *_config;
dissimilarity index 71%
index 927b7e0..8cee21c 100644 (file)
-// -*- mode: cpp; mode: fold -*-
-// Description                                                         /*{{{*/
-// $Id: error.cc,v 1.11 2002/03/26 07:38:58 jgg Exp $
-/* ######################################################################
-   
-   Global Erorr Class - Global error mechanism
-
-   We use a simple STL vector to store each error record. A PendingFlag
-   is kept which indicates when the vector contains a Sever error.
-   
-   This source is placed in the Public Domain, do with it what you will
-   It was originally written by Jason Gunthorpe.
-   
-   ##################################################################### */
-                                                                       /*}}}*/
-// Include Files                                                       /*{{{*/
-#include <apt-pkg/error.h>
-
-#include <iostream>
-#include <errno.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-
-#include <string>
-#include <cstring>
-
-#include "config.h"
-                                                                       /*}}}*/
-
-using namespace std;
-
-// Global Error Object                                                 /*{{{*/
-/* If the implementation supports posix threads then the accessor function
-   is compiled to be thread safe otherwise a non-safe version is used. A
-   Per-Thread error object is maintained in much the same manner as libc
-   manages errno */
-#if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD)
- #include <pthread.h>
-
- static pthread_key_t ErrorKey;
- static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
- static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
-
- GlobalError *_GetErrorObj()
- {
-    static pthread_once_t Once = PTHREAD_ONCE_INIT;
-    pthread_once(&Once,KeyAlloc);
-    
-    void *Res = pthread_getspecific(ErrorKey);
-    if (Res == 0)
-       pthread_setspecific(ErrorKey,Res = new GlobalError);
-    return (GlobalError *)Res;
- }
-#else
- GlobalError *_GetErrorObj()
- {
-    static GlobalError *Obj = new GlobalError;
-    return Obj;
- }
-#endif
-                                                                       /*}}}*/
-
-// GlobalError::GlobalError - Constructor                              /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-GlobalError::GlobalError() : List(0), PendingFlag(false)
-{
-}
-                                                                       /*}}}*/
-// 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;
-}
-                                                                       /*}}}*/
-// 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;
-}
-                                                                       /*}}}*/
-// GlobalError::Warning - Add a warning to the list                    /*{{{*/
-// ---------------------------------------------------------------------
-/* This doesn't set the pending error flag */
-bool GlobalError::Warning(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 = false;
-   Insert(Itm);
-   
-   return false;
-}
-                                                                       /*}}}*/
-// GlobalError::PopMessage - Pulls a single message out                        /*{{{*/
-// ---------------------------------------------------------------------
-/* This should be used in a loop checking empty() each cycle. It returns
-   true if the message is an error. */
-bool GlobalError::PopMessage(string &Text)
-{
-   if (List == 0)
-      return false;
-      
-   bool Ret = List->Error;
-   Text = List->Text;
-   Item *Old = List;
-   List = List->Next;
-   delete Old;
-   
-   // This really should check the list to see if only warnings are left..
-   if (List == 0)
-      PendingFlag = false;
-   
-   return Ret;
-}
-                                                                       /*}}}*/
-// 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;
-};
-                                                                       /*}}}*/
-// 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;
-}
-                                                                       /*}}}*/
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+/* ######################################################################
+
+   Global Error Class - Global error mechanism
+
+   We use a simple STL vector to store each error record. A PendingFlag
+   is kept which indicates when the vector contains a Sever error.
+
+   This source is placed in the Public Domain, do with it what you will
+   It was originally written by Jason Gunthorpe.
+
+   ##################################################################### */
+                                                                       /*}}}*/
+// Include Files                                                       /*{{{*/
+#include <apt-pkg/error.h>
+
+#include <iostream>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <string>
+#include <cstring>
+
+#include "config.h"
+                                                                       /*}}}*/
+
+// Global Error Object                                                 /*{{{*/
+/* If the implementation supports posix threads then the accessor function
+   is compiled to be thread safe otherwise a non-safe version is used. A
+   Per-Thread error object is maintained in much the same manner as libc
+   manages errno */
+#if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD)
+       #include <pthread.h>
+
+       static pthread_key_t ErrorKey;
+       static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
+       static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
+
+       GlobalError *_GetErrorObj() {
+               static pthread_once_t Once = PTHREAD_ONCE_INIT;
+               pthread_once(&Once,KeyAlloc);
+
+               void *Res = pthread_getspecific(ErrorKey);
+               if (Res == 0)
+                       pthread_setspecific(ErrorKey,Res = new GlobalError);
+               return (GlobalError *)Res;
+       }
+#else
+       GlobalError *_GetErrorObj() {
+               static GlobalError *Obj = new GlobalError;
+               return Obj;
+       }
+#endif
+                                                                       /*}}}*/
+// GlobalError::GlobalError - Constructor                              /*{{{*/
+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                /*{{{*/
+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                       /*{{{*/
+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                    /*{{{*/
+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);
+       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;
+
+       if (type == FATAL || type == DEBUG)
+               std::clog << m << std::endl;
+
+       return false;
+}
+                                                                       /*}}}*/
+// GlobalError::PopMessage - Pulls a single message out                        /*{{{*/
+bool GlobalError::PopMessage(std::string &Text) {
+       if (Messages.empty() == true)
+               return false;
+
+       Item const msg = Messages.front();
+       Messages.pop_front();
+
+       bool const Ret = (msg.Type == ERROR || msg.Type == FATAL);
+       Text = msg.Text;
+       if (PendingFlag == false || Ret == false)
+               return Ret;
+
+       // check if another error message is pending
+       for (std::list<Item>::const_iterator m = Messages.begin();
+            m != Messages.end(); m++)
+               if (m->Type == ERROR || m->Type == FATAL)
+                       return Ret;
+
+       PendingFlag = false;
+       return Ret;
+}
+                                                                       /*}}}*/
+// GlobalError::DumpErrors - Dump all of the errors/warns to cerr      /*{{{*/
+void GlobalError::DumpErrors(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::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();
+}
+                                                                       /*}}}*/
index 8d5ec05..7373516 100644 (file)
 
 #include <apt-pkg/macros.h>
 
+#include <iostream>
+#include <list>
 #include <string>
 
-class GlobalError
+#include <stdarg.h>
+
+class GlobalError                                                      /*{{{*/
 {
-   struct Item
-   {
-      std::string Text;
-      bool Error;
-      Item *Next;
-   };
-   
-   Item *List;
-   bool PendingFlag;
-   void Insert(Item *I);
-   
-   public:
+public:                                                                        /*{{{*/
+       /** \brief a message can have one of following severity */
+       enum MsgType {
+               /** \brief Message will be printed instantly as it is likely that
+                       this error will lead to a complete crash */
+               FATAL = 40,
+               /** \brief An error does hinder the correct execution and should be corrected */
+               ERROR = 30,
+               /** \brief indicates problem that can lead to errors later on */
+               WARNING = 20,
+               /** \brief deprecation warnings, old fallback behavior, â€¦ */
+               NOTICE = 10,
+               /** \brief for developers only in areas it is hard to print something directly */
+               DEBUG = 0
+       };
 
-   // Call to generate an error from a library call.
-   bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold;
-   bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold;
+       /** \brief add a fatal error message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool FatalE(const char *Function,const char *Description,...) __like_printf(3) __cold;
 
-   /* A warning should be considered less severe than an error, and may be
-      ignored by the client. */
-   bool Error(const char *Description,...) __like_printf(2) __cold;
-   bool Warning(const char *Description,...) __like_printf(2) __cold;
+       /** \brief add an Error message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold;
 
-   // Simple accessors
-   inline bool PendingError() {return PendingFlag;};
-   inline bool empty() {return List == 0;};
-   bool PopMessage(std::string &Text);
-   void Discard();
+       /** \brief add a warning message with errno to the list
+        *
+        *  A warning should be considered less severe than an error and
+        *  may be ignored by the client.
+        *
+        *  \param Function Name of the function generates the warning.
+        *  \param Description Format string for the warning message.
+        *
+        *  \return \b false
+        */
+       bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold;
 
-   // Usefull routine to dump to cerr
-   void DumpErrors();
-   
-   GlobalError();
+       /** \brief add a notice message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool NoticeE(const char *Function,const char *Description,...) __like_printf(3) __cold;
+
+       /** \brief add a debug message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool DebugE(const char *Function,const char *Description,...) __like_printf(3) __cold;
+
+       /** \brief add an fatal error message to the list
+        *
+        *  Most of the stuff we consider as "error" is also "fatal" for
+        *  the user as the application will not have the expected result,
+        *  but a fatal message here means that it gets printed directly
+        *  to stderr in addiction to adding it to the list as the error
+        *  leads sometimes to crashes and a maybe duplicated message
+        *  is better than "Segfault" as the only displayed text
+        *
+        *  \param Description Format string for the fatal error message.
+        *
+        *  \return \b false
+        */
+       bool Fatal(const char *Description,...) __like_printf(2) __cold;
+
+       /** \brief add an Error message to the list
+        *
+        *  \param Description Format string for the error message.
+        *
+        *  \return \b false
+        */
+       bool Error(const char *Description,...) __like_printf(2) __cold;
+
+       /** \brief add a warning message to the list
+        *
+        *  A warning should be considered less severe than an error and
+        *  may be ignored by the client.
+        *
+        *  \param Description Format string for the message
+        *
+        *  \return \b false
+        */
+       bool Warning(const char *Description,...) __like_printf(2) __cold;
+
+       /** \brief add a notice message to the list
+        *
+        *  A notice should be considered less severe than an error or a
+        *  warning and can be ignored by the client without further problems
+        *  for some times, but he should consider fixing the problem.
+        *  This error type can be used for e.g. deprecation warnings of options.
+        *
+        *  \param Description Format string for the message
+        *
+        *  \return \b false
+        */
+       bool Notice(const char *Description,...) __like_printf(2) __cold;
+
+       /** \brief add a debug message to the list
+        *
+        *  \param Description Format string for the message
+        *
+        *  \return \b false
+        */
+       bool Debug(const char *Description,...) __like_printf(2) __cold;
+
+       /** \brief is an error in the list?
+        *
+        *  \return \b true if an error is included in the list, \b false otherwise
+        */
+       inline bool PendingError() const {return PendingFlag;};
+
+       /** \brief is the list empty?
+        *
+        *  The default checks if the list is empty or contains only notices,
+        *  if you want to check if also no notices happend set the parameter
+        *  flag to \b false.
+        *
+        *  \param WithoutNotice does notices count, default is \b true, so no
+        *
+        *  \return \b true if an the list is empty, \b false otherwise
+        */
+       bool empty(MsgType const &trashhold = WARNING) const;
+
+       /** \brief returns and removes the first (or last) message in the list
+        *
+        *  \param[out] Text message of the first/last item
+        *
+        *  \return \b true if the message was an error, \b false otherwise
+        */
+       bool PopMessage(std::string &Text);
+
+       /** \brief clears the list of messages */
+       void Discard();
+
+       /** \brief outputs the list of messages to the given stream
+        *
+        *  Note that all messages are discarded, also the notices
+        *  displayed or not.
+        *
+        *  \param[out] out output stream to write the messages in
+        *  \param WithoutNotice output notices or not
+        */
+       void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING,
+                       bool const &mergeStack = true);
+
+       /** \brief dumps the list of messages to std::cerr
+        *
+        *  Note that all messages are discarded, also the notices
+        *  displayed or not.
+        *
+        *  \param WithoutNotice print notices or not
+        */
+       void inline DumpErrors(MsgType const &trashhold = WARNING) {
+               DumpErrors(std::cerr, trashhold);
+       }
+
+       /** \brief put the current Messages into the stack
+        *
+        *  All "old" messages will be pushed into a stack to
+        *  them later back, but for now the Message query will be
+        *  empty and performs as no messages were present before.
+        *
+        * The stack can be as deep as you want - all stack operations
+        * will only operate on the last element in the stack.
+        */
+       void PushToStack();
+
+       /** \brief throw away all current messages */
+       void RevertToStack();
+
+       /** \brief merge current and stack together */
+       void MergeWithStack();
+
+       /** \brief return the deep of the stack */
+       size_t StackCount() const {
+               return Stacks.size();
+       }
+
+       GlobalError();
+                                                                       /*}}}*/
+private:                                                               /*{{{*/
+       struct Item {
+               std::string Text;
+               MsgType Type;
+
+               Item(char const *Text, MsgType const &Type) :
+                       Text(Text), Type(Type) {};
+
+               friend std::ostream& operator<< (std::ostream &out, Item i) {
+                       switch(i.Type) {
+                       case FATAL:
+                       case ERROR: out << "E"; break;
+                       case WARNING: out << "W"; break;
+                       case NOTICE: out << "N"; break;
+                       case DEBUG: out << "D"; break;
+                       }
+                       return out << ": " << i.Text;
+               }
+       };
+
+       std::list<Item> Messages;
+       bool PendingFlag;
+
+       struct MsgStack {
+               std::list<Item> const Messages;
+               bool const PendingFlag;
+
+               MsgStack(std::list<Item> const &Messages, bool const &Pending) :
+                        Messages(Messages), PendingFlag(Pending) {};
+       };
+
+       std::list<MsgStack> Stacks;
+
+       bool InsertErrno(MsgType type, const char* Function,
+                        const char* Description, va_list const &args);
+       bool Insert(MsgType type, const char* Description,
+                        va_list const &args);
+                                                                       /*}}}*/
 };
+                                                                       /*}}}*/
 
 // The 'extra-ansi' syntax is used to help with collisions. 
 GlobalError *_GetErrorObj();
index 0b62d1b..62d42e4 100644 (file)
@@ -282,6 +282,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
    }
 
    std::vector<string> List;
+   Configuration::MatchAgainstConfig SilentIgnore("Dir::Ignore-Files-Silently");
    DIR *D = opendir(Dir.c_str());
    if (D == 0) 
    {
@@ -307,6 +308,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
            {
               if (Debug == true)
                  std::clog << "Bad file: " << Ent->d_name << " â†’ no extension" << std::endl;
+              _error->Notice("Ignoring file '%s' in directory '%s' as it has no filename extension", Ent->d_name, Dir.c_str());
               continue;
            }
         }
@@ -314,6 +316,8 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
         {
            if (Debug == true)
               std::clog << "Bad file: " << Ent->d_name << " â†’ bad extension Â»" << flExtension(Ent->d_name) << "«" << std::endl;
+           if (SilentIgnore.Match(Ent->d_name) == false)
+              _error->Notice("Ignoring file '%s' in directory '%s' as it has an invalid filename extension", Ent->d_name, Dir.c_str());
            continue;
         }
       }
index d233e51..d710662 100644 (file)
@@ -297,7 +297,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
    {
       if(!Grow())
       {
-        _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
+        _error->Fatal(_("Dynamic MMap ran out of room. Please increase the size "
                         "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
         return 0;
       }
index 6ede14c..24df57a 100644 (file)
@@ -39,6 +39,8 @@ debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
                                Arch(Arch) {
    if (Arch == "native")
       this->Arch = _config->Find("APT::Architecture");
+   Architectures = APT::Configuration::getArchitectures();
+   MultiArchEnabled = Architectures.size() > 1;
 }
                                                                        /*}}}*/
 // ListParser::UniqFindTagWrite - Find the tag and write a unq string  /*{{{*/
@@ -156,10 +158,9 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
         to a NOP in the download/install step - this package will ensure that
         it is downloaded only one time and installed only one time -- even if
         the architecture bound versions coming in and out on regular basis. */
-      bool const static multiArch = APT::Configuration::getArchitectures().size() > 1;
       if (strcmp(Ver.Arch(true),"all") == 0)
         return true;
-      else if (multiArch == true)
+      else if (MultiArchEnabled == true)
       {
         // our pseudo packages have no size to not confuse the fetcher
         Ver->Size = 0;
@@ -641,9 +642,6 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
    if (Section.Find(Tag,Start,Stop) == false)
       return true;
 
-   static std::vector<std::string> const archs = APT::Configuration::getArchitectures();
-   static bool const multiArch = archs.size() <= 1;
-
    string Package;
    string const pkgArch = Ver.Arch(true);
    string Version;
@@ -655,13 +653,13 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
       if (Start == 0)
         return _error->Error("Problem parsing dependency %s",Tag);
 
-      if (multiArch == true &&
+      if (MultiArchEnabled == true &&
          (Type == pkgCache::Dep::Conflicts ||
           Type == pkgCache::Dep::DpkgBreaks ||
           Type == pkgCache::Dep::Replaces))
       {
-        for (std::vector<std::string>::const_iterator a = archs.begin();
-             a != archs.end(); ++a)
+        for (std::vector<std::string>::const_iterator a = Architectures.begin();
+             a != Architectures.end(); ++a)
            if (NewDepends(Ver,Package,*a,Version,Op,Type) == false)
               return false;
       }
@@ -713,14 +711,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
    if (Ver->MultiArch != pkgCache::Version::Foreign)
       return true;
 
-   std::vector<string> const archs = APT::Configuration::getArchitectures();
-   if (archs.size() <= 1)
+   if (MultiArchEnabled == false)
       return true;
 
    string const Package = Ver.ParentPkg().Name();
    string const Version = Ver.VerStr();
-   for (std::vector<string>::const_iterator a = archs.begin();
-       a != archs.end(); ++a)
+   for (std::vector<string>::const_iterator a = Architectures.begin();
+       a != Architectures.end(); ++a)
    {
       if (NewProvides(Ver, Package, *a, Version) == false)
         return false;
@@ -760,7 +757,7 @@ bool debListParser::Step()
       if (Architecture.empty() == true)
         return true;
 
-      if (Arch.empty() == true)
+      if (Arch.empty() == true || MultiArchEnabled == false)
       {
         if (APT::Configuration::checkArchitecture(Architecture) == true)
            return true;
index 8da0515..6c81d9f 100644 (file)
@@ -32,7 +32,9 @@ class debListParser : public pkgCacheGenerator::ListParser
    pkgTagSection Section;
    unsigned long iOffset;
    string Arch;
-   
+   std::vector<std::string> Architectures;
+   bool MultiArchEnabled;
+
    unsigned long UniqFindTagWrite(const char *Tag);
    bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver);
    bool ParseDepends(pkgCache::VerIterator Ver,const char *Tag,
index 3ae5f59..05127fe 100644 (file)
@@ -1255,6 +1255,10 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    Update(Pkg);
    AddSizes(Pkg);
 
+   // always trigger the install of the all package for a pseudo package
+   if (P.CandidateVerIter(*Cache).Pseudo() == true)
+      MarkInstall(Pkg.Group().FindPkg("all"), AutoInst, Depth, FromUser, ForceImportantDeps);
+
    if (AutoInst == false)
       return;
 
@@ -1453,6 +1457,9 @@ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
 /* */
 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 {
+   if (unlikely(Pkg.end() == true))
+      return;
+
    ActionGroup group(*this);
 
    RemoveSizes(Pkg);
@@ -1466,12 +1473,17 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
    
    AddStates(Pkg);
    AddSizes(Pkg);
+
+   if (unlikely(Pkg.CurrentVer().end() == true) || Pkg.CurrentVer().Pseudo() == false)
+      return;
+
+   SetReInstall(Pkg.Group().FindPkg("all"), To);
 }
                                                                        /*}}}*/
 // DepCache::SetCandidateVersion - Change the candidate version                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
+void pkgDepCache::SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo)
 {
    ActionGroup group(*this);
 
@@ -1489,6 +1501,28 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
    AddStates(Pkg);
    Update(Pkg);
    AddSizes(Pkg);
+
+   if (TargetVer.Pseudo() == false || Pseudo == false)
+      return;
+
+   // the version was pseudo: set all other pseudos also
+   pkgCache::GrpIterator Grp = Pkg.Group();
+   for (Pkg = Grp.FindPkg("any"); Pkg.end() == false; ++Pkg)
+   {
+      StateCache &P = PkgState[Pkg->ID];
+      if (TargetVer.SimilarVer(P.CandidateVerIter(*this)) == true ||
+         (P.CandidateVerIter(*this).Pseudo() == false &&
+          strcmp(Pkg.Arch(), "all") != 0))
+        continue;
+
+      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
+      {
+        if (TargetVer.SimilarVer(Ver) == false)
+           continue;
+        SetCandidateVersion(Ver, false);
+        break;
+      }
+   }
 }
 
 void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
@@ -1551,7 +1585,7 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
 // ---------------------------------------------------------------------
 /* The default just returns the highest available version that is not
    a source and automatic. */
-pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
+pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pkg)
 {
    /* Not source/not automatic versions cannot be a candidate version 
       unless they are already installed */
@@ -1586,7 +1620,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
 // Policy::IsImportantDep - True if the dependency is important                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
+bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep)
 {
    if(Dep.IsCritical())
       return true;
@@ -1605,54 +1639,6 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);
 
-   return false;
-}
-                                                                       /*}}}*/
-pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()                  /*{{{*/
-  : constructedSuccessfully(false)
-{
-  Configuration::Item const *Opts;
-  Opts = _config->Tree("APT::NeverAutoRemove");
-  if (Opts != 0 && Opts->Child != 0)
-    {
-      Opts = Opts->Child;
-      for (; Opts != 0; Opts = Opts->Next)
-       {
-         if (Opts->Value.empty() == true)
-           continue;
-
-         regex_t *p = new regex_t;
-         if(regcomp(p,Opts->Value.c_str(),
-                    REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
-           {
-             regfree(p);
-             delete p;
-             _error->Error("Regex compilation error for APT::NeverAutoRemove");
-             return;
-           }
-
-         rootSetRegexp.push_back(p);
-       }
-    }
-
-  constructedSuccessfully = true;
-}
-                                                                       /*}}}*/
-pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()                 /*{{{*/
-{
-  for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
-    {
-      regfree(rootSetRegexp[i]);
-      delete rootSetRegexp[i];
-    }
-}
-                                                                       /*}}}*/
-bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) /*{{{*/
-{
-   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
-      if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
-        return true;
-
    return false;
 }
                                                                        /*}}}*/
index c6f245a..45276dc 100644 (file)
 #ifndef PKGLIB_DEPCACHE_H
 #define PKGLIB_DEPCACHE_H
 
-
+#include <apt-pkg/configuration.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/progress.h>
-
-#include <regex.h>
+#include <apt-pkg/error.h>
 
 #include <vector>
 #include <memory>
@@ -184,22 +183,13 @@ class pkgDepCache : protected pkgCache::Namespace
    /** \brief Returns \b true for packages matching a regular
     *  expression in APT::NeverAutoRemove.
     */
-   class DefaultRootSetFunc : public InRootSetFunc
+   class DefaultRootSetFunc : public InRootSetFunc, public Configuration::MatchAgainstConfig
    {
-     std::vector<regex_t *> rootSetRegexp;
-     bool constructedSuccessfully;
-
    public:
-     DefaultRootSetFunc();
-     ~DefaultRootSetFunc();
-
-     /** \return \b true if the class initialized successfully, \b
-      *  false otherwise.  Used to avoid throwing an exception, since
-      *  APT classes generally don't.
-      */
-     bool wasConstructedSuccessfully() const { return constructedSuccessfully; }
+     DefaultRootSetFunc() : Configuration::MatchAgainstConfig("APT::NeverRemove") {};
+     virtual ~DefaultRootSetFunc() {};
 
-     bool InRootSet(const pkgCache::PkgIterator &pkg);
+     bool InRootSet(const pkgCache::PkgIterator &pkg) { return pkg.end() == true && Match(pkg.Name()); };
    };
 
    struct StateCache
@@ -266,8 +256,8 @@ class pkgDepCache : protected pkgCache::Namespace
    {
       public:
       
-      virtual VerIterator GetCandidateVer(PkgIterator Pkg);
-      virtual bool IsImportantDep(DepIterator Dep);
+      virtual VerIterator GetCandidateVer(PkgIterator const &Pkg);
+      virtual bool IsImportantDep(DepIterator const &Dep);
       
       virtual ~Policy() {};
    };
@@ -344,7 +334,7 @@ class pkgDepCache : protected pkgCache::Namespace
    inline pkgVersioningSystem &VS() {return *Cache->VS;};
    
    // Policy implementation
-   inline VerIterator GetCandidateVer(PkgIterator Pkg) {return LocalPolicy->GetCandidateVer(Pkg);};
+   inline VerIterator GetCandidateVer(PkgIterator const &Pkg) {return LocalPolicy->GetCandidateVer(Pkg);};
    inline bool IsImportantDep(DepIterator Dep) {return LocalPolicy->IsImportantDep(Dep);};
    inline Policy &GetPolicy() {return *LocalPolicy;};
    
@@ -405,7 +395,7 @@ class pkgDepCache : protected pkgCache::Namespace
                    bool ForceImportantDeps = false);
 
    void SetReInstall(PkgIterator const &Pkg,bool To);
-   void SetCandidateVersion(VerIterator TargetVer);
+   void SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo = true);
 
    /** Set the "is automatically installed" flag of Pkg. */
    void MarkAuto(const PkgIterator &Pkg, bool Auto);
index 21472eb..7a332c8 100644 (file)
@@ -78,6 +78,11 @@ bool pkgInitConfig(Configuration &Cnf)
    Cnf.Set("Dir::Log::Terminal","term.log");
    Cnf.Set("Dir::Log::History","history.log");
 
+   Cnf.Set("Dir::Ignore-Files-Silently::", "~$");
+   Cnf.Set("Dir::Ignore-Files-Silently::", "\\.disabled$");
+   Cnf.Set("Dir::Ignore-Files-Silently::", "\\.bak$");
+   Cnf.Set("Dir::Ignore-Files-Silently::", "\\.dpkg-[a-z]+$");
+
    // Translation
    Cnf.Set("APT::Acquire::Translation", "environment");
 
index 1a70786..a5be462 100644 (file)
@@ -35,15 +35,14 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
         srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
         pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
         indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
-        aptconfiguration.cc cacheset.cc
+        aptconfiguration.cc
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
          orderlist.h sourcelist.h packagemanager.h tagfile.h \
          init.h pkgcache.h version.h progress.h pkgrecords.h \
          acquire.h acquire-worker.h acquire-item.h acquire-method.h \
          clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
          pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
-          vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \
-         cacheset.h
+         vendorlist.h cdrom.h indexcopy.h aptconfiguration.h
 
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..
index 7c95029..55f9cb9 100644 (file)
@@ -117,7 +117,8 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
       return false;
 
    // Skip Packages that need configure only.
-   if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && 
+   if ((Pkg.State() == pkgCache::PkgIterator::NeedsConfigure ||
+        Pkg.State() == pkgCache::PkgIterator::NeedsNothing) &&
        Cache[Pkg].Keep() == true)
       return false;
 
index eef79cc..49776aa 100644 (file)
@@ -602,7 +602,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
       // configured we don't need to unpack it again…
       PkgIterator const P = Pkg.Group().FindPkg("all");
       if (List->IsFlag(P,pkgOrderList::UnPacked) != true &&
-         List->IsFlag(P,pkgOrderList::Configured) != true) {
+         List->IsFlag(P,pkgOrderList::Configured) != true &&
+         P.State() != pkgCache::PkgIterator::NeedsNothing) {
         if (SmartUnPack(P) == false)
            return false;
       }
index 30bb414..68aa83d 100644 (file)
@@ -307,7 +307,7 @@ const char *pkgCache::Priority(unsigned char Prio)
 // GrpIterator::FindPkg - Locate a package by arch                     /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
        if (unlikely(IsGood() == false || S->FirstPackage == 0))
                return PkgIterator(*Owner, 0);
 
@@ -346,7 +346,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
 // GrpIterator::FindPreferredPkg - Locate the "best" package           /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() {
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() const {
        pkgCache::PkgIterator Pkg = FindPkg("native");
        if (Pkg.end() == false)
                return Pkg;
@@ -367,7 +367,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() {
 /* Returns an End-Pointer on error, pointer to the package otherwise.
    We can't simply ++ to the next as the next package of the last will
    be from a different group (with the same hash value) */
-pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) {
+pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const {
        if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
            LastPkg.end() == true))
                return PkgIterator(*Owner, 0);
@@ -504,7 +504,7 @@ std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const
 // ---------------------------------------------------------------------
 /* Currently critical deps are defined as depends, predepends and
    conflicts (including dpkg's Breaks fields). */
-bool pkgCache::DepIterator::IsCritical()
+bool pkgCache::DepIterator::IsCritical() const
 {
    if (S->Type == pkgCache::Dep::Conflicts ||
        S->Type == pkgCache::Dep::DpkgBreaks ||
@@ -528,7 +528,7 @@ bool pkgCache::DepIterator::IsCritical()
    In Conjunction with the DepCache the value of Result may not be 
    super-good since the policy may have made it uninstallable. Using
    AllTargets is better in this case. */
-bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
+bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const
 {
    Result = TargetPkg();
    
@@ -577,7 +577,7 @@ bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
    provides. It includes every possible package-version that could satisfy
    the dependency. The last item in the list has a 0. The resulting pointer
    must be delete [] 'd */
-pkgCache::Version **pkgCache::DepIterator::AllTargets()
+pkgCache::Version **pkgCache::DepIterator::AllTargets() const
 {
    Version **Res = 0;
    unsigned long Size =0;
index 5649cd6..05c0149 100644 (file)
@@ -572,10 +572,7 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
                                OldDepLast);
                     // Breaks: ${self}:other (!= ${binary:Version})
                     NewDepends(D, V, V.VerStr(),
-                               pkgCache::Dep::Less, pkgCache::Dep::DpkgBreaks,
-                               OldDepLast);
-                    NewDepends(D, V, V.VerStr(),
-                               pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks,
+                               pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
                                OldDepLast);
                     if (V->MultiArch == pkgCache::Version::All)
                     {
index 28cb3cc..f8b2678 100644 (file)
@@ -76,7 +76,7 @@ class pkgPolicy : public pkgDepCache::Policy
 
    // Things for the cache interface.
    virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg);
-   virtual bool IsImportantDep(pkgCache::DepIterator Dep) {return pkgDepCache::Policy::IsImportantDep(Dep);};
+   virtual bool IsImportantDep(pkgCache::DepIterator const &Dep) {return pkgDepCache::Policy::IsImportantDep(Dep);};
    bool InitDefaults();
    
    pkgPolicy(pkgCache *Owner);
index 7cb95b3..c790559 100644 (file)
@@ -29,7 +29,8 @@
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/sptr.h>
-#include <apt-pkg/cacheset.h>
+
+#include "cacheset.h"
 
 #include <config.h>
 #include <apti18n.h>
@@ -1867,21 +1868,21 @@ int main(int argc,const char *argv[])                                   /*{{{*/
    }
    
    // Deal with stdout not being a tty
-   if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
 
-//       if (_config->FindB("APT::Cache::Generate",true) == false)
+   if (_config->Exists("APT::Cache::Generate") == true)
+      _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
+
    if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
       CmdL.DispatchArg(CmdsB);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-          
-   return 0;
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
                                                                        /*}}}*/
index 8b9eaca..d1268ed 100644 (file)
@@ -266,20 +266,18 @@ int main(int argc,const char *argv[])                                     /*{{{*/
       return ShowHelp();
 
    // Deal with stdout not being a tty
-   if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
    
    // Match the operation
    CmdL.DispatchArg(Cmds);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-   
-   return 0;
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
                                                                        /*}}}*/
index 0ada46c..7cf760c 100644 (file)
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
-#include <apt-pkg/cacheset.h>
 
 #include <config.h>
 #include <apti18n.h>
 
 #include "acqprogress.h"
+#include "cacheset.h"
 
 #include <set>
 #include <locale.h>
@@ -609,6 +609,253 @@ void Stats(ostream &out,pkgDepCache &Dep)
               Dep.BadCount());
 }
                                                                        /*}}}*/
+// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
+class CacheSetHelperAPTGet : public APT::CacheSetHelper {
+       /** \brief stream message should be printed to */
+       std::ostream &out;
+       /** \brief were things like Task or RegEx used to select packages? */
+       bool explicitlyNamed;
+
+       APT::PackageSet virtualPkgs;
+
+public:
+       CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
+               explicitlyNamed = true;
+       }
+
+       virtual void showTaskSelection(APT::PackageSet const &pkgset, string const &pattern) {
+               for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+                       ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
+                                Pkg.FullName(true).c_str(), pattern.c_str());
+               explicitlyNamed = false;
+       }
+       virtual void showRegExSelection(APT::PackageSet const &pkgset, string const &pattern) {
+               for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+                       ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
+                                Pkg.FullName(true).c_str(), pattern.c_str());
+               explicitlyNamed = false;
+       }
+       virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+                                string const &ver, bool const &verIsRel) {
+               if (ver != Ver.VerStr())
+                       ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+                                Ver.VerStr(), Ver.RelStr().c_str(), Pkg.FullName(true).c_str());
+       }
+
+       bool showVirtualPackageErrors(pkgCacheFile &Cache) {
+               if (virtualPkgs.empty() == true)
+                       return true;
+               for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin();
+                    Pkg != virtualPkgs.end(); ++Pkg) {
+                       if (Pkg->ProvidesList != 0) {
+                               ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
+                                        Pkg.FullName(true).c_str());
+
+                               pkgCache::PrvIterator I = Pkg.ProvidesList();
+                               unsigned short provider = 0;
+                               for (; I.end() == false; ++I) {
+                                       pkgCache::PkgIterator Pkg = I.OwnerPkg();
+
+                                       if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) {
+                                               out << "  " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
+                                               if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
+                                                       out << _(" [Installed]");
+                                               out << endl;
+                                               ++provider;
+                                       }
+                               }
+                               // if we found no candidate which provide this package, show non-candidates
+                               if (provider == 0)
+                                       for (I = Pkg.ProvidesList(); I.end() == false; I++)
+                                               out << "  " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
+                                                   << _(" [Not candidate version]") << endl;
+                               else
+                                       out << _("You should explicitly select one to install.") << endl;
+                       } else {
+                               ioprintf(out,
+                                       _("Package %s is not available, but is referred to by another package.\n"
+                                         "This may mean that the package is missing, has been obsoleted, or\n"
+                                         "is only available from another source\n"),Pkg.FullName(true).c_str());
+
+                               string List;
+                               string VersionsList;
+                               SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount];
+                               memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen));
+                               for (pkgCache::DepIterator Dep = Pkg.RevDependsList();
+                                    Dep.end() == false; Dep++) {
+                                       if (Dep->Type != pkgCache::Dep::Replaces)
+                                               continue;
+                                       if (Seen[Dep.ParentPkg()->ID] == true)
+                                               continue;
+                                       Seen[Dep.ParentPkg()->ID] = true;
+                                       List += Dep.ParentPkg().FullName(true) + " ";
+                                       //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
+                               }
+                               ShowList(out,_("However the following packages replace it:"),List,VersionsList);
+                       }
+                       out << std::endl;
+               }
+               return false;
+       }
+
+       virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+               APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE);
+               if (verset.empty() == false)
+                       return *(verset.begin());
+               if (ShowError == true) {
+                       _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str());
+                       virtualPkgs.insert(Pkg);
+               }
+               return pkgCache::VerIterator(Cache, 0);
+       }
+
+       virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+               APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
+               if (verset.empty() == false)
+                       return *(verset.begin());
+               if (ShowError == true)
+                       ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+               return pkgCache::VerIterator(Cache, 0);
+       }
+
+       APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
+                                               APT::VersionSet::Version const &select) {
+               /* This is a pure virtual package and there is a single available
+                  candidate providing it. */
+               if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
+                       return APT::VersionSet();
+
+               pkgCache::PkgIterator Prov;
+               bool found_one = false;
+               for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
+                       pkgCache::VerIterator const PVer = P.OwnerVer();
+                       pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
+
+                       /* Ignore versions that are not a candidate. */
+                       if (Cache[PPkg].CandidateVer != PVer)
+                               continue;
+
+                       if (found_one == false) {
+                               Prov = PPkg;
+                               found_one = true;
+                       } else if (PPkg != Prov) {
+                               found_one = false; // we found at least two
+                               break;
+                       }
+               }
+
+               if (found_one == true) {
+                       ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
+                                Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
+                       return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
+               }
+               return APT::VersionSet();
+       }
+
+       inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
+
+};
+                                                                       /*}}}*/
+// TryToInstall - Mark a package for installation                      /*{{{*/
+struct TryToInstall {
+   pkgCacheFile* Cache;
+   pkgProblemResolver* Fix;
+   bool FixBroken;
+   unsigned long AutoMarkChanged;
+   APT::PackageSet doAutoInstallLater;
+
+   TryToInstall(pkgCacheFile &Cache, pkgProblemResolver &PM, bool const &FixBroken) : Cache(&Cache), Fix(&PM),
+                       FixBroken(FixBroken), AutoMarkChanged(0) {};
+
+   void operator() (pkgCache::VerIterator const &Ver) {
+      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+      Cache->GetDepCache()->SetCandidateVersion(Ver);
+      pkgDepCache::StateCache &State = (*Cache)[Pkg];
+
+      // Handle the no-upgrade case
+      if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
+        ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
+                 Pkg.FullName(true).c_str());
+      // Ignore request for install if package would be new
+      else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
+        ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
+                 Pkg.FullName(true).c_str());
+      else {
+        Fix->Clear(Pkg);
+        Fix->Protect(Pkg);
+        Cache->GetDepCache()->MarkInstall(Pkg,false);
+
+        if (State.Install() == false) {
+           if (_config->FindB("APT::Get::ReInstall",false) == true) {
+              if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
+                 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
+                          Pkg.FullName(true).c_str());
+              else
+                 Cache->GetDepCache()->SetReInstall(Pkg, true);
+           } else
+              ioprintf(c1out,_("%s is already the newest version.\n"),
+                       Pkg.FullName(true).c_str());
+        }
+
+        // Install it with autoinstalling enabled (if we not respect the minial
+        // required deps or the policy)
+        if (FixBroken == false)
+           doAutoInstallLater.insert(Pkg);
+      }
+
+      // see if we need to fix the auto-mark flag
+      // e.g. apt-get install foo
+      // where foo is marked automatic
+      if (State.Install() == false &&
+         (State.Flags & pkgCache::Flag::Auto) &&
+         _config->FindB("APT::Get::ReInstall",false) == false &&
+         _config->FindB("APT::Get::Only-Upgrade",false) == false &&
+         _config->FindB("APT::Get::Download-Only",false) == false)
+      {
+        ioprintf(c1out,_("%s set to manually installed.\n"),
+                 Pkg.FullName(true).c_str());
+        Cache->GetDepCache()->MarkAuto(Pkg,false);
+        AutoMarkChanged++;
+      }
+   }
+
+   void doAutoInstall() {
+      for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
+          P != doAutoInstallLater.end(); ++P) {
+        pkgDepCache::StateCache &State = (*Cache)[P];
+        if (State.InstBroken() == false && State.InstPolicyBroken() == false)
+           continue;
+        Cache->GetDepCache()->MarkInstall(P, true);
+      }
+      doAutoInstallLater.clear();
+   }
+};
+                                                                       /*}}}*/
+// TryToRemove - Mark a package for removal                            /*{{{*/
+struct TryToRemove {
+   pkgCacheFile* Cache;
+   pkgProblemResolver* Fix;
+   bool FixBroken;
+   unsigned long AutoMarkChanged;
+
+   TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM) {};
+
+   void operator() (pkgCache::VerIterator const &Ver)
+   {
+      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+      Fix->Clear(Pkg);
+      Fix->Protect(Pkg);
+      Fix->Remove(Pkg);
+
+      if (Pkg->CurrentVer == 0)
+        ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+      else
+        Cache->GetDepCache()->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
+   }
+};
+                                                                       /*}}}*/
 // CacheFile::NameComp - QSort compare by name                         /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1073,219 +1320,35 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    return true;
 }
                                                                        /*}}}*/
-// TryToInstall - Try to install a single package                      /*{{{*/
+// TryToInstallBuildDep - Try to install a single package              /*{{{*/
 // ---------------------------------------------------------------------
 /* This used to be inlined in DoInstall, but with the advent of regex package
    name matching it was split out.. */
-bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
+bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache,
                  pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
-                 unsigned int &ExpectedInst,bool AllowFail = true)
+                 bool AllowFail = true)
 {
-   /* This is a pure virtual package and there is a single available
-      candidate providing it. */
    if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
    {
-      pkgCache::PkgIterator Prov;
-      bool found_one = false;
-
-      for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; P++)
-      {
-        pkgCache::VerIterator const PVer = P.OwnerVer();
-        pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
-
-        /* Ignore versions that are not a candidate. */
-        if (Cache[PPkg].CandidateVer != PVer)
-            continue;
-
-        if (found_one == false)
-        {
-           Prov = PPkg;
-           found_one = true;
-        }
-        else if (PPkg != Prov)
-        {
-           found_one = false; // we found at least two
-           break;
-        }
-      }
-
-      if (found_one == true)
-      {
-        ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
-                 Prov.FullName(true).c_str(),Pkg.FullName(true).c_str());
-        Pkg = Prov;
-      }
+      CacheSetHelperAPTGet helper(c1out);
+      helper.showErrors(AllowFail == false);
+      pkgCache::VerIterator Ver = helper.canNotFindNewestVer(Cache, Pkg);
+      if (Ver.end() == false)
+        Pkg = Ver.ParentPkg();
+      else if (helper.showVirtualPackageErrors(Cache) == false)
+        return AllowFail;
    }
 
-   // Handle the no-upgrade case
-   if (_config->FindB("APT::Get::upgrade",true) == false &&
-       Pkg->CurrentVer != 0)
-   {
-      if (AllowFail == true)
-        ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
-                 Pkg.FullName(true).c_str());
-      return true;
-   }
-
-   // Ignore request for install if package would be new
-   if (_config->FindB("APT::Get::Only-Upgrade", false) == true &&
-       Pkg->CurrentVer == 0)
-   {
-      if (AllowFail == true)
-        ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
-                 Pkg.Name());
-      return true;
-   }
-
-   // Check if there is something at all to install
-   pkgDepCache::StateCache &State = Cache[Pkg];
-   if (Remove == true && Pkg->CurrentVer == 0)
-   {
-      Fix.Clear(Pkg);
-      Fix.Protect(Pkg);
-      Fix.Remove(Pkg);
-      
-      /* We want to continue searching for regex hits, so we return false here
-         otherwise this is not really an error. */
-      if (AllowFail == false)
-        return false;
-      
-      ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
-      return true;
-   }
-   
-   if (State.CandidateVer == 0 && Remove == false)
-   {
-      if (AllowFail == false)
-        return false;
-      
-      if (Pkg->ProvidesList != 0)
-      {
-        ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
-                 Pkg.FullName(true).c_str());
-        
-        pkgCache::PrvIterator I = Pkg.ProvidesList();
-        unsigned short provider = 0;
-        for (; I.end() == false; I++)
-        {
-           pkgCache::PkgIterator Pkg = I.OwnerPkg();
-           
-           if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
-           {
-              c1out << "  " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
-              if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
-                 c1out << _(" [Installed]");
-              c1out << endl;
-              ++provider;
-           }
-        }
-        // if we found no candidate which provide this package, show non-candidates
-        if (provider == 0)
-           for (I = Pkg.ProvidesList(); I.end() == false; I++)
-              c1out << "  " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
-               << _(" [Not candidate version]") << endl;
-        else
-           c1out << _("You should explicitly select one to install.") << endl;
-      }
-      else
-      {
-        ioprintf(c1out,
-        _("Package %s is not available, but is referred to by another package.\n"
-          "This may mean that the package is missing, has been obsoleted, or\n"
-           "is only available from another source\n"),Pkg.FullName(true).c_str());
-        
-        string List;
-        string VersionsList;
-        SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
-        memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
-        pkgCache::DepIterator Dep = Pkg.RevDependsList();
-        for (; Dep.end() == false; Dep++)
-        {
-           if (Dep->Type != pkgCache::Dep::Replaces)
-              continue;
-           if (Seen[Dep.ParentPkg()->ID] == true)
-              continue;
-           Seen[Dep.ParentPkg()->ID] = true;
-           List += Dep.ParentPkg().FullName(true) + " ";
-        //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
-        }          
-        ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
-      }
-      
-      _error->Error(_("Package %s has no installation candidate"),Pkg.FullName(true).c_str());
-      return false;
-   }
-
-   Fix.Clear(Pkg);
-   Fix.Protect(Pkg);   
    if (Remove == true)
    {
-      Fix.Remove(Pkg);
-      Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
-      return true;
-   }
-   
-   // Install it
-   Cache.MarkInstall(Pkg,false);
-   if (State.Install() == false)
-   {
-      if (_config->FindB("APT::Get::ReInstall",false) == true)
-      {
-        if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
-           ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
-                    Pkg.FullName(true).c_str());
-        else
-           Cache.SetReInstall(Pkg,true);
-      }      
-      else
-      {
-        if (AllowFail == true)
-           ioprintf(c1out,_("%s is already the newest version.\n"),
-                    Pkg.FullName(true).c_str());
-      }      
-   }   
-   else
-      ExpectedInst++;
-   
-   // Install it with autoinstalling enabled (if we not respect the minial
-   // required deps or the policy)
-   if ((State.InstBroken() == true || State.InstPolicyBroken() == true) && BrokenFix == false)
-      Cache.MarkInstall(Pkg,true);
-
-   return true;
-}
-                                                                       /*}}}*/
-// TryToChangeVer - Try to change a candidate version                  /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
-                   const char *VerTag,bool IsRel)
-{
-   pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : 
-                                pkgVersionMatch::Version));
-   
-   pkgCache::VerIterator Ver = Match.Find(Pkg);
-                        
-   if (Ver.end() == true)
-   {
-      if (IsRel == true)
-        return _error->Error(_("Release '%s' for '%s' was not found"),
-                             VerTag,Pkg.FullName(true).c_str());
-      return _error->Error(_("Version '%s' for '%s' was not found"),
-                          VerTag,Pkg.FullName(true).c_str());
-   }
-   
-   if (strcmp(VerTag,Ver.VerStr()) != 0)
-   {
-      ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
-              Ver.VerStr(),Ver.RelStr().c_str(),Pkg.FullName(true).c_str());
-   }
-   
-   Cache.SetCandidateVersion(Ver);
-
-   // Set the all package to the same candidate
-   if (Ver.Pseudo() == true)
-      Cache.SetCandidateVersion(Match.Find(Pkg.Group().FindPkg("all")));
+      TryToRemove RemoveAction(Cache, Fix);
+      RemoveAction(Pkg.VersionList());
+   } else if (Cache[Pkg].CandidateVer != 0) {
+      TryToInstall InstallAction(Cache, Fix, BrokenFix);
+      InstallAction(Cache[Pkg].CandidateVerIter(Cache));
+      InstallAction.doAutoInstall();
+   } else
+      return AllowFail;
 
    return true;
 }
@@ -1624,61 +1687,6 @@ bool DoUpgrade(CommandLine &CmdL)
    return InstallPackages(Cache,true);
 }
                                                                        /*}}}*/
-// DoInstallTask - Install task from the command line                  /*{{{*/
-// ---------------------------------------------------------------------
-/* Install named task */
-bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix, 
-                   bool BrokenFix,
-                   unsigned int& ExpectedInst, 
-                   const char *taskname,
-                   bool Remove)
-{
-   const char *start, *end;
-   pkgCache::PkgIterator Pkg;
-   char buf[64*1024];
-   regex_t Pattern;
-
-   // get the records
-   pkgRecords Recs(Cache);
-
-   // build regexp for the task
-   char S[300];
-   snprintf(S, sizeof(S), "^Task:.*[, ]%s([, ]|$)", taskname);
-   if(regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE) != 0)
-      return _error->Error("Failed to compile task regexp");
-   
-   bool found = false;
-   bool res = true;
-
-   // two runs, first ignore dependencies, second install any missing
-   for(int IgnoreBroken=1; IgnoreBroken >= 0; IgnoreBroken--)
-   {
-      for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-        pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache);
-        if(ver.end())
-           continue;
-        pkgRecords::Parser &parser = Recs.Lookup(ver.FileList());
-        parser.GetRec(start,end);
-        strncpy(buf, start, end-start);
-        buf[end-start] = 0x0;
-        if (regexec(&Pattern,buf,0,0,0) != 0)
-           continue;
-        res &= TryToInstall(Pkg,Cache,Fix,Remove,IgnoreBroken,ExpectedInst);
-        found = true;
-      }
-   }
-   
-   // now let the problem resolver deal with any issues
-   Fix.Resolve(true);
-
-   if(!found)
-      _error->Error(_("Couldn't find task %s"),taskname);
-
-   regfree(&Pattern);
-   return res;
-}
-                                                                       /*}}}*/
 // DoInstall - Install packages from the command line                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Install named packages */
@@ -1694,140 +1702,69 @@ bool DoInstall(CommandLine &CmdL)
    if (Cache->BrokenCount() != 0)
       BrokenFix = true;
    
-   unsigned int AutoMarkChanged = 0;
-   unsigned int ExpectedInst = 0;
-   unsigned int Packages = 0;
    pkgProblemResolver Fix(Cache);
-   
-   bool DefRemove = false;
+
+   static const unsigned short MOD_REMOVE = 1;
+   static const unsigned short MOD_INSTALL = 2;
+
+   unsigned short fallback = MOD_INSTALL;
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
    {
       _config->Set("APT::Get::Purge", true);
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    }
    else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
    {
       _config->Set("APT::Get::AutomaticRemove", "true");
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    }
-   // new scope for the ActionGroup
-   {
-      pkgDepCache::ActionGroup group(Cache);
-      for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-      {
-        // Duplicate the string
-        unsigned int Length = strlen(*I);
-        char S[300];
-        if (Length >= sizeof(S))
-           continue;
-        strcpy(S,*I);
-      
-        // See if we are removing and special indicators..
-        bool Remove = DefRemove;
-        char *VerTag = 0;
-        bool VerIsRel = false;
 
-         // this is a task!
-         if (Length >= 1 && S[Length - 1] == '^')
-         {
-            S[--Length] = 0;
-            // tasks must always be confirmed
-            ExpectedInst += 1000;
-            // see if we can install it
-            TryInstallTask(Cache, Fix, BrokenFix, ExpectedInst, S, Remove);
-            continue;
-         }
+   std::list<APT::VersionSet::Modifier> mods;
+   mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
+               APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
+   mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
+               APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
+   CacheSetHelperAPTGet helper(c0out);
+   std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
+               CmdL.FileList + 1, mods, fallback, helper);
 
-        while (Cache->FindPkg(S).end() == true)
-        {
-           // Handle an optional end tag indicating what to do
-           if (Length >= 1 && S[Length - 1] == '-')
-           {
-              Remove = true;
-              S[--Length] = 0;
-              continue;
-           }
-        
-           if (Length >= 1 && S[Length - 1] == '+')
-           {
-              Remove = false;
-              S[--Length] = 0;
-              continue;
-           }
-        
-           char *Slash = strchr(S,'=');
-           if (Slash != 0)
-           {
-              VerIsRel = false;
-              *Slash = 0;
-              VerTag = Slash + 1;
-           }
-        
-           Slash = strchr(S,'/');
-           if (Slash != 0)
-           {
-              VerIsRel = true;
-              *Slash = 0;
-              VerTag = Slash + 1;
-           }
-        
-           break;
-        }
-      
-        // Locate the package
-        pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
-        Packages++;
-        if (Pkg.end() == true)
-        {
-           APT::PackageSet pkgset = APT::PackageSet::FromRegEx(Cache, S, c1out);
-           if (pkgset.empty() == true)
-              return _error->Error(_("Couldn't find package %s"),S);
+   if (_error->PendingError() == true)
+   {
+      helper.showVirtualPackageErrors(Cache);
+      return false;
+   }
 
-           // Regexs must always be confirmed
-           ExpectedInst += 1000;
+   unsigned short order[] = { 0, 0, 0 };
+   if (fallback == MOD_INSTALL) {
+      order[0] = MOD_INSTALL;
+      order[1] = MOD_REMOVE;
+   } else {
+      order[0] = MOD_REMOVE;
+      order[1] = MOD_INSTALL;
+   }
 
-           bool Hit = false;
-           for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
-           {
-              if (VerTag != 0)
-                 if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
-                    return false;
+  TryToInstall InstallAction(Cache, Fix, BrokenFix);
+  TryToRemove RemoveAction(Cache, Fix);
 
-              Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
-                                  ExpectedInst,false);
-           }
+   // new scope for the ActionGroup
+   {
+      pkgDepCache::ActionGroup group(Cache);
 
-           if (Hit == false)
-              return _error->Error(_("Couldn't find package %s"),S);
+      for (unsigned short i = 0; order[i] != 0; ++i)
+      {
+        if (order[i] == MOD_INSTALL) {
+           InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
+           InstallAction.doAutoInstall();
         }
-        else
-        {
-           if (VerTag != 0)
-              if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
-                 return false;
-           if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
-              return false;
-
-           // see if we need to fix the auto-mark flag 
-           // e.g. apt-get install foo 
-           // where foo is marked automatic
-           if(!Remove && 
-              Cache[Pkg].Install() == false && 
-              (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
-              _config->FindB("APT::Get::ReInstall",false) == false &&
-              _config->FindB("APT::Get::Only-Upgrade",false) == false &&
-              _config->FindB("APT::Get::Download-Only",false) == false)
-           {
-              ioprintf(c1out,_("%s set to manually installed.\n"),
-                       Pkg.FullName(true).c_str());
-              Cache->MarkAuto(Pkg,false);
-              AutoMarkChanged++;
-           }
-        }      
+        else if (order[i] == MOD_REMOVE)
+           RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
       }
 
+      if (_error->PendingError() == true)
+        return false;
+
       /* If we are in the Broken fixing mode we do not attempt to fix the
         problems. This is if the user invoked install without -f and gave
         packages */
@@ -1874,7 +1811,7 @@ bool DoInstall(CommandLine &CmdL)
 
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
-   if (Cache->InstCount() != ExpectedInst)
+   if (Cache->InstCount() != verset[MOD_INSTALL].size())
    {
       string List;
       string VersionsList;
@@ -1993,14 +1930,15 @@ bool DoInstall(CommandLine &CmdL)
    // if nothing changed in the cache, but only the automark information
    // we write the StateFile here, otherwise it will be written in 
    // cache.commit()
-   if (AutoMarkChanged > 0 &&
+   if (InstallAction.AutoMarkChanged > 0 &&
        Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
        Cache->BadCount() == 0 &&
        _config->FindB("APT::Get::Simulate",false) == false)
       Cache->writeStateFile(NULL);
 
    // See if we need to prompt
-   if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
+   // FIXME: check if really the packages in the set are going to be installed
+   if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
 
    return InstallPackages(Cache,false);   
@@ -2584,7 +2522,6 @@ bool DoBuildDep(CommandLine &CmdL)
       }
       
       // Install the requested packages
-      unsigned int ExpectedInst = 0;
       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
       pkgProblemResolver Fix(Cache);
       bool skipAlternatives = false; // skip remaining alternatives in an or group
@@ -2615,7 +2552,7 @@ bool DoBuildDep(CommandLine &CmdL)
              */
             if (IV.end() == false && 
                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
-               TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
+               TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
          }
         else // BuildDep || BuildDepIndep
          {
@@ -2731,7 +2668,7 @@ bool DoBuildDep(CommandLine &CmdL)
             if (_config->FindB("Debug::BuildDeps",false) == true)
                cout << "  Trying to install " << (*D).Package << endl;
 
-            if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
+            if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false) == true)
             {
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
@@ -3021,7 +2958,7 @@ int main(int argc,const char *argv[])                                     /*{{{*/
    }
 
    // Deal with stdout not being a tty
-   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
 
    // Setup the output streams
@@ -3042,13 +2979,11 @@ int main(int argc,const char *argv[])                                   /*{{{*/
    CmdL.DispatchArg(Cmds);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-   
-   return 0;   
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
                                                                        /*}}}*/
diff --git a/cmdline/cacheset.cc b/cmdline/cacheset.cc
new file mode 100644 (file)
index 0000000..78c9d3f
--- /dev/null
@@ -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);
+}
+                                                                       /*}}}*/
+}
similarity index 54%
rename from apt-pkg/cacheset.h
rename to cmdline/cacheset.h
index 668d803..c8c3dd0 100644 (file)
 #include <apt-pkg/pkgcache.h>
                                                                        /*}}}*/
 namespace APT {
+class PackageSet;
+class VersionSet;
+class CacheSetHelper {                                                 /*{{{*/
+/** \class APT::CacheSetHelper
+    Simple base class with a lot of virtual methods which can be overridden
+    to alter the behavior or the output of the CacheSets.
+
+    This helper is passed around by the static methods in the CacheSets and
+    used every time they hit an error condition or something could be
+    printed out.
+*/
+public:                                                                        /*{{{*/
+       CacheSetHelper(bool const &ShowError = true) : ShowError(ShowError) {};
+       virtual ~CacheSetHelper() {};
+
+       virtual void showTaskSelection(PackageSet const &pkgset, string const &pattern) {};
+       virtual void showRegExSelection(PackageSet const &pkgset, string const &pattern) {};
+       virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+                                string const &ver, bool const &verIsRel) {};
+
+       virtual pkgCache::PkgIterator canNotFindPkgName(pkgCacheFile &Cache, std::string const &str);
+       virtual PackageSet canNotFindTask(pkgCacheFile &Cache, std::string pattern);
+       virtual PackageSet canNotFindRegEx(pkgCacheFile &Cache, std::string pattern);
+       virtual PackageSet canNotFindPackage(pkgCacheFile &Cache, std::string const &str);
+       virtual VersionSet canNotFindAllVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg);
+       virtual VersionSet canNotFindInstCandVer(pkgCacheFile &Cache,
+                               pkgCache::PkgIterator const &Pkg);
+       virtual VersionSet canNotFindCandInstVer(pkgCacheFile &Cache,
+                               pkgCache::PkgIterator const &Pkg);
+       virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache,
+                               pkgCache::PkgIterator const &Pkg);
+       virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache,
+                               pkgCache::PkgIterator const &Pkg);
+       virtual pkgCache::VerIterator canNotFindInstalledVer(pkgCacheFile &Cache,
+                               pkgCache::PkgIterator const &Pkg);
+
+       bool showErrors() const { return ShowError; };
+       bool showErrors(bool const &newValue) { if (ShowError == newValue) return ShowError; else return ((ShowError = newValue) == false); };
+                                                                       /*}}}*/
+protected:
+       bool ShowError;
+};                                                                     /*}}}*/
 class PackageSet : public std::set<pkgCache::PkgIterator> {            /*{{{*/
 /** \class APT::PackageSet
 
@@ -28,7 +70,7 @@ class PackageSet : public std::set<pkgCache::PkgIterator> {           /*{{{*/
     pkgCache. */
 public:                                                                        /*{{{*/
        /** \brief smell like a pkgCache::PkgIterator */
-       class const_iterator : public std::set<pkgCache::PkgIterator>::const_iterator {
+       class const_iterator : public std::set<pkgCache::PkgIterator>::const_iterator {/*{{{*/
        public:
                const_iterator(std::set<pkgCache::PkgIterator>::const_iterator x) :
                         std::set<pkgCache::PkgIterator>::const_iterator(x) {}
@@ -62,9 +104,25 @@ public:                                                                     /*{{{*/
        };
        // 103. set::iterator is required to be modifiable, but this allows modification of keys
        typedef APT::PackageSet::const_iterator iterator;
+                                                                       /*}}}*/
 
        using std::set<pkgCache::PkgIterator>::insert;
        inline void insert(pkgCache::PkgIterator const &P) { if (P.end() == false) std::set<pkgCache::PkgIterator>::insert(P); };
+       inline void insert(PackageSet const &pkgset) { insert(pkgset.begin(), pkgset.end()); };
+
+       /** \brief returns all packages in the cache who belong to the given task
+
+           A simple helper responsible for search for all members of a task
+           in the cache. Optional it prints a a notice about the
+           packages chosen cause of the given task.
+           \param Cache the packages are in
+           \param pattern name of the task
+           \param helper responsible for error and message handling */
+       static APT::PackageSet FromTask(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
+       static APT::PackageSet FromTask(pkgCacheFile &Cache, std::string const &pattern) {
+               CacheSetHelper helper;
+               return APT::PackageSet::FromTask(Cache, pattern, helper);
+       }
 
        /** \brief returns all packages in the cache whose name matchs a given pattern
 
@@ -73,22 +131,33 @@ public:                                                                    /*{{{*/
            packages chosen cause of the given package.
            \param Cache the packages are in
            \param pattern regular expression for package names
-           \param out stream to print the notice to */
-       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out);
+           \param helper responsible for error and message handling */
+       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
        static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string const &pattern) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
-               return APT::PackageSet::FromRegEx(Cache, pattern, out);
+               CacheSetHelper helper;
+               return APT::PackageSet::FromRegEx(Cache, pattern, helper);
        }
 
        /** \brief returns all packages specified by a string
 
            \param Cache the packages are in
            \param string String the package name(s) should be extracted from
-           \param out stream to print various notices to */
-       static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, std::ostream &out);
+           \param helper responsible for error and message handling */
+       static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, CacheSetHelper &helper);
        static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
-               return APT::PackageSet::FromString(Cache, string, out);
+               CacheSetHelper helper;
+               return APT::PackageSet::FromString(Cache, string, helper);
+       }
+
+       /** \brief returns a package specified by a string
+
+           \param Cache the package is in
+           \param string String the package name should be extracted from
+           \param helper responsible for error and message handling */
+       static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &string, CacheSetHelper &helper);
+       static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &string) {
+               CacheSetHelper helper;
+               return APT::PackageSet::FromName(Cache, string, helper);
        }
 
        /** \brief returns all packages specified on the commandline
@@ -97,11 +166,11 @@ public:                                                                    /*{{{*/
            No special package command is supported, just plain names.
            \param Cache the packages are in
            \param cmdline Command line the package names should be extracted from
-           \param out stream to print various notices to */
-       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out);
+           \param helper responsible for error and message handling */
+       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper);
        static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
-               return APT::PackageSet::FromCommandLine(Cache, cmdline, out);
+               CacheSetHelper helper;
+               return APT::PackageSet::FromCommandLine(Cache, cmdline, helper);
        }
 
        struct Modifier {
@@ -112,18 +181,38 @@ public:                                                                   /*{{{*/
                Modifier (unsigned short const &id, const char * const alias, Position const &pos) : ID(id), Alias(alias), Pos(pos) {};
        };
 
+       /** \brief group packages by a action modifiers
+
+           At some point it is needed to get from the same commandline
+           different package sets grouped by a modifier. Take
+               apt-get install apt awesome-
+           as an example.
+           \param Cache the packages are in
+           \param cmdline Command line the package names should be extracted from
+           \param mods list of modifiers the method should accept
+           \param fallback the default modifier group for a package
+           \param helper responsible for error and message handling */
        static std::map<unsigned short, PackageSet> GroupedFromCommandLine(
                pkgCacheFile &Cache, const char **cmdline,
                std::list<PackageSet::Modifier> const &mods,
-               unsigned short const &fallback, std::ostream &out);
+               unsigned short const &fallback, CacheSetHelper &helper);
        static std::map<unsigned short, PackageSet> GroupedFromCommandLine(
                pkgCacheFile &Cache, const char **cmdline,
                std::list<PackageSet::Modifier> const &mods,
                unsigned short const &fallback) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               CacheSetHelper helper;
                return APT::PackageSet::GroupedFromCommandLine(Cache, cmdline,
-                               mods, fallback, out);
+                               mods, fallback, helper);
        }
+
+       enum Constructor { UNKNOWN, REGEX, TASK };
+       Constructor getConstructor() const { return ConstructedBy; };
+
+       PackageSet() : ConstructedBy(UNKNOWN) {};
+       PackageSet(Constructor const &by) : ConstructedBy(by) {};
+                                                                       /*}}}*/
+private:                                                               /*{{{*/
+       Constructor ConstructedBy;
                                                                        /*}}}*/
 };                                                                     /*}}}*/
 class VersionSet : public std::set<pkgCache::VerIterator> {            /*{{{*/
@@ -134,7 +223,7 @@ class VersionSet : public std::set<pkgCache::VerIterator> {         /*{{{*/
     pkgCache. */
 public:                                                                        /*{{{*/
        /** \brief smell like a pkgCache::VerIterator */
-       class const_iterator : public std::set<pkgCache::VerIterator>::const_iterator {
+       class const_iterator : public std::set<pkgCache::VerIterator>::const_iterator {/*{{{*/
        public:
                const_iterator(std::set<pkgCache::VerIterator>::const_iterator x) :
                         std::set<pkgCache::VerIterator>::const_iterator(x) {}
@@ -168,11 +257,13 @@ public:                                                                   /*{{{*/
                inline bool Pseudo() const { return (**this).Pseudo(); };
                inline pkgCache::VerFileIterator NewestFile() const { return (**this).NewestFile(); };
        };
+                                                                       /*}}}*/
        // 103. set::iterator is required to be modifiable, but this allows modification of keys
        typedef APT::VersionSet::const_iterator iterator;
 
        using std::set<pkgCache::VerIterator>::insert;
        inline void insert(pkgCache::VerIterator const &V) { if (V.end() == false) std::set<pkgCache::VerIterator>::insert(V); };
+       inline void insert(VersionSet const &verset) { insert(verset.begin(), verset.end()); };
 
        /** \brief specifies which version(s) will be returned if non is given */
        enum Version {
@@ -198,41 +289,86 @@ public:                                                                   /*{{{*/
            non specifically requested  and executes regex's if needed on names.
            \param Cache the packages and versions are in
            \param cmdline Command line the versions should be extracted from
-           \param out stream to print various notices to */
+           \param helper responsible for error and message handling */
        static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
-                       APT::VersionSet::Version const &fallback, std::ostream &out);
+                       APT::VersionSet::Version const &fallback, CacheSetHelper &helper);
        static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
                        APT::VersionSet::Version const &fallback) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
-               return APT::VersionSet::FromCommandLine(Cache, cmdline, fallback, out);
+               CacheSetHelper helper;
+               return APT::VersionSet::FromCommandLine(Cache, cmdline, fallback, helper);
        }
        static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
                return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST);
        }
+
+       static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg,
+                       APT::VersionSet::Version const &fallback, CacheSetHelper &helper,
+                       bool const &onlyFromName = false);
+       static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg,
+                       APT::VersionSet::Version const &fallback) {
+               CacheSetHelper helper;
+               return APT::VersionSet::FromString(Cache, pkg, fallback, helper);
+       }
+       static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg) {
+               return APT::VersionSet::FromString(Cache, pkg, CANDINST);
+       }
+
+       /** \brief returns all versions specified for the package
+
+           \param Cache the package and versions are in
+           \param P the package in question
+           \param fallback the version(s) you want to get
+           \param helper the helper used for display and error handling */
+       static APT::VersionSet FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
+               VersionSet::Version const &fallback, CacheSetHelper &helper);
+       static APT::VersionSet FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
+                       APT::VersionSet::Version const &fallback) {
+               CacheSetHelper helper;
+               return APT::VersionSet::FromPackage(Cache, P, fallback, helper);
+       }
+       static APT::VersionSet FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P) {
+               return APT::VersionSet::FromPackage(Cache, P, CANDINST);
+       }
+
+       struct Modifier {
+               enum Position { NONE, PREFIX, POSTFIX };
+               unsigned short ID;
+               const char * const Alias;
+               Position Pos;
+               VersionSet::Version SelectVersion;
+               Modifier (unsigned short const &id, const char * const alias, Position const &pos,
+                         VersionSet::Version const &select) : ID(id), Alias(alias), Pos(pos),
+                        SelectVersion(select) {};
+       };
+
+       static std::map<unsigned short, VersionSet> GroupedFromCommandLine(
+               pkgCacheFile &Cache, const char **cmdline,
+               std::list<VersionSet::Modifier> const &mods,
+               unsigned short const &fallback, CacheSetHelper &helper);
+       static std::map<unsigned short, VersionSet> GroupedFromCommandLine(
+               pkgCacheFile &Cache, const char **cmdline,
+               std::list<VersionSet::Modifier> const &mods,
+               unsigned short const &fallback) {
+               CacheSetHelper helper;
+               return APT::VersionSet::GroupedFromCommandLine(Cache, cmdline,
+                               mods, fallback, helper);
+       }
                                                                        /*}}}*/
 protected:                                                             /*{{{*/
 
        /** \brief returns the candidate version of the package
 
            \param Cache to be used to query for information
-           \param Pkg we want the candidate version from this package
-           \param AllowError add an error to the stack if not */
+           \param Pkg we want the candidate version from this package */
        static pkgCache::VerIterator getCandidateVer(pkgCacheFile &Cache,
-               pkgCache::PkgIterator const &Pkg, bool const &AllowError = false);
+               pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper);
 
        /** \brief returns the installed version of the package
 
            \param Cache to be used to query for information
-           \param Pkg we want the installed version from this package
-           \param AllowError add an error to the stack if not */
+           \param Pkg we want the installed version from this package */
        static pkgCache::VerIterator getInstalledVer(pkgCacheFile &Cache,
-               pkgCache::PkgIterator const &Pkg, bool const &AllowError = false);
-
-
-       static bool AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset,
-               pkgCache::PkgIterator const &P, VersionSet::Version const &fallback,
-               bool const &AllowError = false);
-
+               pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper);
                                                                        /*}}}*/
 };                                                                     /*}}}*/
 }
index 917ccc9..4ffe49e 100644 (file)
@@ -9,14 +9,14 @@ include ../buildlib/defaults.mak
 PROGRAM=apt-cache
 SLIBS = -lapt-pkg $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-cache.cc
+SOURCE = apt-cache.cc cacheset.cc
 include $(PROGRAM_H)
 
 # The apt-get program
 PROGRAM=apt-get
 SLIBS = -lapt-pkg -lutil $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-get.cc acqprogress.cc
+SOURCE = apt-get.cc acqprogress.cc cacheset.cc
 include $(PROGRAM_H)
 
 # The apt-config program
index 1bf6815..878d523 100644 (file)
@@ -1,5 +1,44 @@
-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)
+
+  [ Julian Andres Klode ]
   * methods/ftp.h:
     - Handle different logins on the same server (Closes: #586904).
   * apt-pkg/deb/deblistparser.cc:
@@ -13,7 +52,7 @@ apt (0.7.26~exp8) experimental; urgency=low
   * debian/control:
     - Set Standards-Version to 3.9.0
 
- -- Julian Andres Klode <jak@debian.org>  Thu, 24 Jun 2010 10:56:39 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Mon, 05 Jul 2010 12:05:30 +0200
 
 apt (0.7.26~exp7) experimental; urgency=low
 
index 8bc4356..d482f2d 100644 (file)
@@ -6,7 +6,7 @@ Uploaders: Michael Vogt <mvo@debian.org>, Otavio Salvador <otavio@debian.org>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Luca Bruno <lethalman88@gmail.com>, Julian Andres Klode <jak@debian.org>
 Standards-Version: 3.9.0
-Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev, autoconf, automake, doxygen, intltool
+Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev, autoconf, automake, doxygen
 Build-Conflicts: autoconf2.13, automake1.4
 
 Package: apt
index 0cf4bb6..39e2c8e 100644 (file)
@@ -507,6 +507,15 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      will be looked up in
      <filename>/tmp/staging/var/lib/dpkg/status</filename>.
    </para>
+
+   <para>
+      The <literal>Ignore-Files-Silently</literal> list can be used to specify
+      which files APT should silently ignore while parsing the files in the
+      fragment directories. Per default a file which end with <literal>.disabled</literal>,
+      <literal>~</literal>, <literal>.bak</literal> or <literal>.dpkg-[a-z]+</literal>
+      is silently ignored. As seen in the last default value these patterns can use regular
+      expression syntax.
+   </para>
  </refsect1>
  
  <refsect1><title>APT in DSelect</title>
diff --git a/test/libapt/globalerror_test.cc b/test/libapt/globalerror_test.cc
new file mode 100644 (file)
index 0000000..b275225
--- /dev/null
@@ -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;
+}
index ee3401b..5005826 100644 (file)
@@ -30,13 +30,19 @@ SOURCE = getlistoffilesindir_test.cc
 include $(PROGRAM_H)
 
 # Program for testing CommandLine reconstruction
-PROGRAM = commandlineasstring${BASENAME}
+PROGRAM = CommandlineAsString${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = commandlineasstring_test.cc
 include $(PROGRAM_H)
 
 # Program for testing debians version comparing
-PROGRAM = compareversion${BASENAME}
+PROGRAM = CompareVersion${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = compareversion_test.cc
 include $(PROGRAM_H)
+
+# test the GlobalError stack class
+PROGRAM = GlobalError${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = globalerror_test.cc
+include $(PROGRAM_H)