Prechádzať zdrojové kódy

Add a method to get a VersionSet from the Commandline and refactor
the existing methods a bit to reuse them easier intern

David Kalnischkies 16 rokov pred
rodič
commit
856d3b06a6
2 zmenil súbory, kde vykonal 191 pridanie a 23 odobranie
  1. 121 19
      apt-pkg/cacheset.cc
  2. 70 4
      apt-pkg/cacheset.h

+ 121 - 19
apt-pkg/cacheset.cc

@@ -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();
 }
 									/*}}}*/
 }

+ 70 - 4
apt-pkg/cacheset.h

@@ -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);
+
 									/*}}}*/
 };									/*}}}*/
 }