Use an abstract helper for error handling and output
authorDavid Kalnischkies <kalnischkies@gmail.com>
Tue, 22 Jun 2010 16:01:11 +0000 (18:01 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Tue, 22 Jun 2010 16:01:11 +0000 (18:01 +0200)
instead of doing this directly in the CacheSets.
With this method an application like apt-get can change
the behavior of the CacheSets to his liking.
It can for example easily keep track of how packages
were added to the set: by names or with regex's…

cmdline/apt-get.cc
cmdline/cacheset.cc
cmdline/cacheset.h

index c081ca1..6a7d7a4 100644 (file)
@@ -1079,7 +1079,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    name matching it was split out.. */
 bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &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. */
@@ -1244,9 +1244,7 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
                     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)
@@ -1589,6 +1587,41 @@ bool DoUpgrade(CommandLine &CmdL)
    return InstallPackages(Cache,true);
 }
                                                                        /*}}}*/
+// 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;
+
+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());
+       }
+
+       inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
+
+};
+                                                                       /*}}}*/
 // DoInstall - Install packages from the command line                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Install named packages */
@@ -1605,7 +1638,6 @@ bool DoInstall(CommandLine &CmdL)
       BrokenFix = true;
    
    unsigned int AutoMarkChanged = 0;
-   unsigned int ExpectedInst = 0;
    pkgProblemResolver Fix(Cache);
 
    unsigned short fallback = 0;
@@ -1621,28 +1653,29 @@ bool DoInstall(CommandLine &CmdL)
       _config->Set("APT::Get::AutomaticRemove", "true");
       fallback = 1;
    }
-   // new scope for the ActionGroup
-   {
-      // TODO: Howto get an ExpectedInst count ?
-      pkgDepCache::ActionGroup group(Cache);
-      std::list<APT::VersionSet::Modifier> mods;
-      mods.push_back(APT::VersionSet::Modifier(0, "+",
+
+   std::list<APT::VersionSet::Modifier> mods;
+   mods.push_back(APT::VersionSet::Modifier(0, "+",
                APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDINST));
-      mods.push_back(APT::VersionSet::Modifier(1, "-",
+   mods.push_back(APT::VersionSet::Modifier(1, "-",
                APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::INSTCAND));
-      std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
-               CmdL.FileList + 1, mods, fallback, c0out);
+   CacheSetHelperAPTGet helper(c0out);
+   std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
+               CmdL.FileList + 1, mods, fallback, helper);
 
-      if (_error->PendingError() == true)
-        return false;
+   if (_error->PendingError() == true)
+      return false;
 
+   // new scope for the ActionGroup
+   {
+      pkgDepCache::ActionGroup group(Cache);
       for (APT::VersionSet::const_iterator Ver = verset[0].begin();
           Ver != verset[0].end(); ++Ver)
       {
         pkgCache::PkgIterator Pkg = Ver.ParentPkg();
         Cache->SetCandidateVersion(Ver);
 
-        if (TryToInstall(Pkg, Cache, Fix, false, BrokenFix, ExpectedInst) == false)
+        if (TryToInstall(Pkg, Cache, Fix, false, BrokenFix) == false)
            return false;
 
         // see if we need to fix the auto-mark flag
@@ -1666,7 +1699,7 @@ bool DoInstall(CommandLine &CmdL)
       {
         pkgCache::PkgIterator Pkg = Ver.ParentPkg();
 
-        if (TryToInstall(Pkg, Cache, Fix, true, BrokenFix, ExpectedInst) == false)
+        if (TryToInstall(Pkg, Cache, Fix, true, BrokenFix) == false)
            return false;
       }
 
@@ -1719,7 +1752,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[0].size())
    {
       string List;
       string VersionsList;
@@ -1845,7 +1878,8 @@ bool DoInstall(CommandLine &CmdL)
       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[0].size() && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
 
    return InstallPackages(Cache,false);   
@@ -2429,7 +2463,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
@@ -2460,7 +2493,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);
+               TryToInstall(Pkg,Cache,Fix,true,false);
          }
         else // BuildDep || BuildDepIndep
          {
@@ -2576,7 +2609,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 (TryToInstall(Pkg,Cache,Fix,false,false) == true)
             {
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
index 55ab267..88a98fd 100644 (file)
@@ -24,7 +24,7 @@
                                                                        /*}}}*/
 namespace APT {
 // FromTask - Return all packages in the cache from a specific task    /*{{{*/
-PackageSet PackageSet::FromTask(pkgCacheFile &Cache, std::string pattern, std::ostream &out) {
+PackageSet PackageSet::FromTask(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
        PackageSet pkgset;
        if (Cache.BuildCaches() == false || Cache.BuildDepCache() == false)
                return pkgset;
@@ -67,19 +67,22 @@ PackageSet PackageSet::FromTask(pkgCacheFile &Cache, std::string pattern, std::o
                char buf[length];
                strncpy(buf, start, length);
                buf[length-1] = '\0';
-               if (regexec(&Pattern, buf, 0, 0, 0) == 0)
-                       pkgset.insert(Pkg);
+               if (regexec(&Pattern, buf, 0, 0, 0) != 0)
+                       continue;
+
+               pkgset.insert(Pkg);
        }
+       regfree(&Pattern);
 
        if (pkgset.empty() == true)
-               _error->Error(_("Couldn't find task %s"), pattern.c_str());
+               return helper.canNotFindTask(Cache, pattern);
 
-       regfree(&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, std::ostream &out) {
+PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
        PackageSet pkgset;
        static const char * const isregex = ".?+*|[^$";
 
@@ -121,14 +124,14 @@ PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, std::
                                continue;
                }
 
-               ioprintf(out, _("Note, selecting %s for regex '%s'\n"),
-                        Pkg.FullName(true).c_str(), pattern.c_str());
-
                pkgset.insert(Pkg);
        }
-
        regfree(&Pattern);
 
+       if (pkgset.empty() == true)
+               return helper.canNotFindRegEx(Cache, pattern);
+
+       helper.showRegExSelection(pkgset, pattern);
        return pkgset;
 }
                                                                        /*}}}*/
@@ -136,7 +139,7 @@ PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, std::
 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) {
+               unsigned short const &fallback, CacheSetHelper &helper) {
        std::map<unsigned short, PackageSet> pkgsets;
        for (const char **I = cmdline; *I != 0; ++I) {
                unsigned short modID = fallback;
@@ -159,24 +162,23 @@ std::map<unsigned short, PackageSet> PackageSet::GroupedFromCommandLine(
                        }
                        break;
                }
-               PackageSet pset = PackageSet::FromString(Cache, str, out);
-               pkgsets[modID].insert(pset.begin(), pset.end());
+               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, std::ostream &out) {
+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, out);
+               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, std::ostream &out) {
+PackageSet PackageSet::FromString(pkgCacheFile &Cache, std::string const &str, CacheSetHelper &helper) {
        std::string pkg = str;
        size_t archfound = pkg.find_last_of(':');
        std::string arch;
@@ -198,23 +200,22 @@ PackageSet PackageSet::FromString(pkgCacheFile &Cache, std::string const &str, s
                pkgset.insert(Pkg);
                return pkgset;
        }
-       PackageSet pset = FromTask(Cache, str, out);
+       PackageSet pset = FromTask(Cache, str, helper);
        if (pset.empty() == false)
                return pset;
 
-       pset = FromRegEx(Cache, str, out);
+       pset = FromRegEx(Cache, str, helper);
        if (pset.empty() == false)
                return pset;
 
-       _error->Warning(_("Unable to locate package %s"), str.c_str());
-       return pset;
+       return helper.canNotFindPackage(Cache, str);
 }
                                                                        /*}}}*/
 // 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, std::ostream &out) {
+               unsigned short const &fallback, CacheSetHelper &helper) {
        std::map<unsigned short, VersionSet> versets;
        for (const char **I = cmdline; *I != 0; ++I) {
                unsigned short modID = fallback;
@@ -241,18 +242,17 @@ std::map<unsigned short, VersionSet> VersionSet::GroupedFromCommandLine(
                        }
                        break;
                }
-               VersionSet vset = VersionSet::FromString(Cache, str, select , out);
-               versets[modID].insert(vset.begin(), vset.end());
+               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, std::ostream &out) {
+               APT::VersionSet::Version const &fallback, CacheSetHelper &helper) {
        VersionSet verset;
        for (const char **I = cmdline; *I != 0; ++I) {
-               VersionSet vset = VersionSet::FromString(Cache, *I, fallback, out);
+               VersionSet vset = VersionSet::FromString(Cache, *I, fallback, helper);
                verset.insert(vset.begin(), vset.end());
        }
        return verset;
@@ -260,7 +260,7 @@ APT::VersionSet VersionSet::FromCommandLine(pkgCacheFile &Cache, const char **cm
                                                                        /*}}}*/
 // FromString - Returns all versions spedcified by a string            /*{{{*/
 APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg,
-               APT::VersionSet::Version const &fallback, std::ostream &out) {
+               APT::VersionSet::Version const &fallback, CacheSetHelper &helper) {
        std::string ver;
        bool verIsRel = false;
        size_t const vertag = pkg.find_last_of("/=");
@@ -269,19 +269,19 @@ APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg,
                verIsRel = (pkg[vertag] == '/');
                pkg.erase(vertag);
        }
-       PackageSet pkgset = PackageSet::FromString(Cache, pkg.c_str(), out);
+       PackageSet pkgset = PackageSet::FromString(Cache, pkg.c_str(), helper);
        VersionSet verset;
        for (PackageSet::const_iterator P = pkgset.begin();
             P != pkgset.end(); ++P) {
                if (vertag == string::npos) {
-                       AddSelectedVersion(Cache, verset, P, fallback);
+                       AddSelectedVersion(Cache, verset, P, fallback, helper);
                        continue;
                }
                pkgCache::VerIterator V;
                if (ver == "installed")
-                       V = getInstalledVer(Cache, P);
+                       V = getInstalledVer(Cache, P, helper);
                else if (ver == "candidate")
-                       V = getCandidateVer(Cache, P);
+                       V = getCandidateVer(Cache, P, helper);
                else {
                        pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release :
                                        pkgVersionMatch::Version));
@@ -298,76 +298,70 @@ APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg,
                }
                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());
+               helper.showSelectedVersion(P, V, ver, verIsRel);
                verset.insert(V);
        }
        return verset;
 }
                                                                        /*}}}*/
 // AddSelectedVersion - add version from package based on fallback     /*{{{*/
-bool VersionSet::AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset,
+void VersionSet::AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset,
                pkgCache::PkgIterator const &P, VersionSet::Version const &fallback,
-               bool const &AllowError) {
+               CacheSetHelper &helper) {
        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 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;
+                       verset.insert(helper.canNotFindAllVer(Cache, P));
                break;
        case VersionSet::CANDANDINST:
-               verset.insert(getInstalledVer(Cache, P, AllowError));
-               verset.insert(getCandidateVer(Cache, P, AllowError));
+               verset.insert(getInstalledVer(Cache, P, helper));
+               verset.insert(getCandidateVer(Cache, P, helper));
                break;
        case VersionSet::CANDIDATE:
-               verset.insert(getCandidateVer(Cache, P, AllowError));
+               verset.insert(getCandidateVer(Cache, P, helper));
                break;
        case VersionSet::INSTALLED:
-               verset.insert(getInstalledVer(Cache, P, AllowError));
+               verset.insert(getInstalledVer(Cache, P, helper));
                break;
        case VersionSet::CANDINST:
-               V = getCandidateVer(Cache, P, true);
+               showErrors = helper.showErrors(false);
+               V = getCandidateVer(Cache, P, helper);
                if (V.end() == true)
-                       V = getInstalledVer(Cache, P, true);
+                       V = getInstalledVer(Cache, P, helper);
+               helper.showErrors(showErrors);
                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;
+                       verset.insert(helper.canNotFindInstCandVer(Cache, P));
                break;
        case VersionSet::INSTCAND:
-               V = getInstalledVer(Cache, P, true);
+               showErrors = helper.showErrors(false);
+               V = getInstalledVer(Cache, P, helper);
                if (V.end() == true)
-                       V = getCandidateVer(Cache, P, true);
+                       V = getCandidateVer(Cache, P, helper);
+               helper.showErrors(showErrors);
                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;
+                       verset.insert(helper.canNotFindInstCandVer(Cache, P));
                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;
+                       verset.insert(helper.canNotFindNewestVer(Cache, P));
                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) {
+               pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) {
        pkgCache::VerIterator Cand;
        if (Cache.IsDepCacheBuilt() == true)
                Cand = Cache[Pkg].CandidateVerIter(Cache);
@@ -376,17 +370,78 @@ pkgCache::VerIterator VersionSet::getCandidateVer(pkgCacheFile &Cache,
                        return pkgCache::VerIterator(*Cache);
                Cand = Cache.GetPolicy()->GetCandidateVer(Pkg);
        }
-       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());
+       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, 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());
+               pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) {
+       if (Pkg->CurrentVer == 0)
+               return helper.canNotFindInstalledVer(Cache, Pkg);
        return Pkg.CurrentVer();
 }
                                                                        /*}}}*/
+// 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) {
+       if (ShowError == true)
+               _error->Error(_("Unable to locate package %s"), str.c_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();
+}
+                                                                       /*}}}*/
+// 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);
+}
+                                                                       /*}}}*/
+// 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);
+}
+                                                                       /*}}}*/
+// 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);
+}
+                                                                       /*}}}*/
 }
index 64a72e7..9c94910 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 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 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
 
@@ -66,6 +105,7 @@ public:                                                                      /*{{{*/
 
        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
 
@@ -75,10 +115,10 @@ public:                                                                    /*{{{*/
            \param Cache the packages are in
            \param pattern name of the task
            \param out stream to print the notice to */
-       static APT::PackageSet FromTask(pkgCacheFile &Cache, std::string pattern, std::ostream &out);
+       static APT::PackageSet FromTask(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper);
        static APT::PackageSet FromTask(pkgCacheFile &Cache, std::string const &pattern) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
-               return APT::PackageSet::FromTask(Cache, pattern, out);
+               CacheSetHelper helper;
+               return APT::PackageSet::FromTask(Cache, pattern, helper);
        }
 
        /** \brief returns all packages in the cache whose name matchs a given pattern
@@ -89,10 +129,10 @@ public:                                                                    /*{{{*/
            \param Cache the packages are in
            \param pattern regular expression for package names
            \param out stream to print the notice to */
-       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out);
+       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string 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
@@ -100,10 +140,10 @@ public:                                                                   /*{{{*/
            \param Cache the packages are in
            \param string String the package name(s) should be extracted from
            \param out stream to print various notices to */
-       static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, std::ostream &out);
+       static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, 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 all packages specified on the commandline
@@ -113,10 +153,10 @@ public:                                                                   /*{{{*/
            \param Cache the packages are in
            \param cmdline Command line the package names should be extracted from
            \param out stream to print various notices to */
-       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out);
+       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, 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 {
@@ -130,14 +170,14 @@ public:                                                                   /*{{{*/
        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);
        }
                                                                        /*}}}*/
 };                                                                     /*}}}*/
@@ -189,6 +229,7 @@ public:                                                                     /*{{{*/
 
        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 {
@@ -216,22 +257,22 @@ public:                                                                   /*{{{*/
            \param cmdline Command line the versions should be extracted from
            \param out stream to print various notices to */
        static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
-                       APT::VersionSet::Version const &fallback, std::ostream &out);
+                       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, std::ostream &out);
+                       APT::VersionSet::Version const &fallback, CacheSetHelper &helper);
        static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg,
                        APT::VersionSet::Version const &fallback) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
-               return APT::VersionSet::FromString(Cache, pkg, fallback, out);
+               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);
@@ -251,14 +292,14 @@ public:                                                                   /*{{{*/
        static std::map<unsigned short, VersionSet> GroupedFromCommandLine(
                pkgCacheFile &Cache, const char **cmdline,
                std::list<VersionSet::Modifier> const &mods,
-               unsigned short const &fallback, std::ostream &out);
+               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) {
-               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               CacheSetHelper helper;
                return APT::VersionSet::GroupedFromCommandLine(Cache, cmdline,
-                               mods, fallback, out);
+                               mods, fallback, helper);
        }
                                                                        /*}}}*/
 protected:                                                             /*{{{*/
@@ -266,23 +307,20 @@ 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);
-
+               pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper);
 
-       static bool AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset,
+       static void AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset,
                pkgCache::PkgIterator const &P, VersionSet::Version const &fallback,
-               bool const &AllowError = false);
+               CacheSetHelper &helper);
 
                                                                        /*}}}*/
 };                                                                     /*}}}*/