Add a method to get a VersionSet from the Commandline and refactor
authorDavid Kalnischkies <kalnischkies@gmail.com>
Sat, 5 Jun 2010 07:20:29 +0000 (09:20 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Sat, 5 Jun 2010 07:20:29 +0000 (09:20 +0200)
the existing methods a bit to reuse them easier intern

apt-pkg/cacheset.cc
apt-pkg/cacheset.h

index b49b365..7372c90 100644 (file)
@@ -13,6 +13,7 @@
 #include <apt-pkg/error.h>
 #include <apt-pkg/cacheset.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/versionmatch.h>
 
 #include <apti18n.h>
 
@@ -22,7 +23,7 @@
                                                                        /*}}}*/
 namespace APT {
 // FromRegEx - Return all packages in the cache matching a pattern     /*{{{*/
-PackageSet PackageSet::FromRegEx(pkgCache &Cache, std::string pattern, std::ostream &out) {
+PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out) {
        PackageSet pkgset;
        std::string arch = "native";
        static const char * const isregex = ".?+*|[^$";
@@ -48,7 +49,7 @@ PackageSet PackageSet::FromRegEx(pkgCache &Cache, std::string pattern, std::ostr
                return pkgset;
        }
 
-       for (pkgCache::GrpIterator Grp = Cache.GrpBegin(); Grp.end() == false; ++Grp)
+       for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp)
        {
                if (regexec(&Pattern, Grp.Name(), 0, 0, 0) != 0)
                        continue;
@@ -76,28 +77,129 @@ PackageSet PackageSet::FromRegEx(pkgCache &Cache, std::string pattern, std::ostr
 }
                                                                        /*}}}*/
 // FromCommandLine - Return all packages specified on commandline      /*{{{*/
-PackageSet PackageSet::FromCommandLine(pkgCache &Cache, const char **cmdline, std::ostream &out) {
+PackageSet PackageSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out) {
        PackageSet pkgset;
        for (const char **I = cmdline + 1; *I != 0; I++) {
-               pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-               if (Pkg.end() == true) {
-                       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 = Cache.FindPkg(*I, *a);
-                       }
-                       if (Pkg.end() == true) {
-                               PackageSet regex = FromRegEx(Cache, *I, out);
-                               if (regex.empty() == true)
-                                       _error->Warning(_("Unable to locate package %s"),*I);
-                               else
-                                       pkgset.insert(regex.begin(), regex.end());
-                               continue;
+               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, const char * const str, std::ostream &out) {
+       pkgCache::GrpIterator Grp = Cache.GetPkgCache()->FindGrp(str);
+       if (Grp.end() == false) {
+               pkgCache::PkgIterator Pkg = Grp.FindPreferredPkg();
+               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);
+       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 + 1; *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) {
+                               pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release :
+                                                       pkgVersionMatch::Version));
+                               pkgCache::VerIterator 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 (strcmp(ver.c_str(), V.VerStr()) != 0)
+                                       ioprintf(out, _("Selected version %s (%s) for %s\n"),
+                                                V.VerStr(), V.RelStr().c_str(), P.FullName(true).c_str());
+                               verset.insert(V);
+                       } else {
+                               pkgCache::VerIterator V;
+                               switch(fallback) {
+                               case VersionSet::ALL:
+                                       for (V = P.VersionList(); V.end() != true; ++V)
+                                               verset.insert(V);
+                                       break;
+                               case VersionSet::CANDANDINST:
+                                       verset.insert(getInstalledVer(Cache, P));
+                                       verset.insert(getCandidateVer(Cache, P));
+                                       break;
+                               case VersionSet::CANDIDATE:
+                                       verset.insert(getCandidateVer(Cache, P));
+                                       break;
+                               case VersionSet::INSTALLED:
+                                       verset.insert(getInstalledVer(Cache, P));
+                                       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
+                                               _error->Error(_("Can't select installed nor candidate version from package %s as it has neither of them"), P.FullName(true).c_str());
+                                       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
+                                               _error->Error(_("Can't select installed nor candidate version from package %s as it has neither of them"), P.FullName(true).c_str());
+                                       break;
+                               case VersionSet::NEWEST:
+                                       if (P->VersionList != 0)
+                                               verset.insert(P.VersionList());
+                                       else
+                                               _error->Error(_("Can't select newest version from package %s as it is purely virtual"), P.FullName(true).c_str());
+                                       break;
+                               }
                        }
                }
-               pkgset.insert(Pkg);
        }
-       return pkgset;
+       return verset;
+}
+                                                                       /*}}}*/
+// 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].InstVerIter(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 f0131bf..708531b 100644 (file)
@@ -14,6 +14,7 @@
 #include <set>
 #include <string>
 
+#include <apt-pkg/cachefile.h>
 #include <apt-pkg/pkgcache.h>
                                                                        /*}}}*/
 namespace APT {
@@ -68,12 +69,23 @@ 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(pkgCache &Cache, std::string pattern, std::ostream &out);
-       static APT::PackageSet FromRegEx(pkgCache &Cache, std::string const &pattern) {
+       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out);
+       static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string const &pattern) {
                std::ostream out (std::ofstream("/dev/null").rdbuf());
                return APT::PackageSet::FromRegEx(Cache, pattern, out);
        }
 
+       /** \brief returns all packages specified by a string
+
+           \param Cache the packages are in
+           \param string String the package name(s) should be extracted from
+           \param out stream to print various notices to */
+       static APT::PackageSet FromString(pkgCacheFile &Cache, const char * const string, std::ostream &out);
+       static APT::PackageSet FromString(pkgCacheFile &Cache, const char * const string) {
+               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               return APT::PackageSet::FromString(Cache, string, out);
+       }
+
        /** \brief returns all packages specified on the commandline
 
            Get all package names from the commandline and executes regex's if needed.
@@ -81,8 +93,8 @@ 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(pkgCache &Cache, const char **cmdline, std::ostream &out);
-       static APT::PackageSet FromCommandLine(pkgCache &Cache, const char **cmdline) {
+       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out);
+       static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
                std::ostream out (std::ofstream("/dev/null").rdbuf());
                return APT::PackageSet::FromCommandLine(Cache, cmdline, out);
        }
@@ -133,6 +145,60 @@ public:                                                                    /*{{{*/
        // 103. set::iterator is required to be modifiable, but this allows modification of keys
        typedef typename APT::VersionSet::const_iterator iterator;
 
+       /** \brief specifies which version(s) will be returned if non is given */
+       enum Version {
+               /** All versions */
+               ALL,
+               /** Candidate and installed version */
+               CANDANDINST,
+               /** Candidate version */
+               CANDIDATE,
+               /** Installed version */
+               INSTALLED,
+               /** Candidate or if non installed version */
+               CANDINST,
+               /** Installed or if non candidate version */
+               INSTCAND,
+               /** Newest version */
+               NEWEST
+       };
+
+       /** \brief returns all versions specified on the commandline
+
+           Get all versions from the commandline, uses given default version if
+           non specifically requested  and executes regex's if needed on names.
+           \param Cache the packages and versions are in
+           \param cmdline Command line the versions should be extracted from
+           \param out stream to print various notices to */
+       static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+                       APT::VersionSet::Version const &fallback, std::ostream &out);
+       static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
+                       APT::VersionSet::Version const &fallback) {
+               std::ostream out (std::ofstream("/dev/null").rdbuf());
+               return APT::VersionSet::FromCommandLine(Cache, cmdline, fallback, out);
+       }
+       static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) {
+               return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST);
+       }
+                                                                       /*}}}*/
+protected:                                                             /*{{{*/
+
+       /** \brief returns the candidate version of the package
+
+           \param Cache to be used to query for information
+           \param Pkg we want the candidate version from this package
+           \param AllowError add an error to the stack if not */
+       static pkgCache::VerIterator getCandidateVer(pkgCacheFile &Cache,
+               pkgCache::PkgIterator const &Pkg, bool const &AllowError = false);
+
+       /** \brief returns the installed version of the package
+
+           \param Cache to be used to query for information
+           \param Pkg we want the installed version from this package
+           \param AllowError add an error to the stack if not */
+       static pkgCache::VerIterator getInstalledVer(pkgCacheFile &Cache,
+               pkgCache::PkgIterator const &Pkg, bool const &AllowError = false);
+
                                                                        /*}}}*/
 };                                                                     /*}}}*/
 }