[packagekit] [PATCH] aptcc: Support for library provides

Matthias Klumpp matthias at nlinux.org
Mon Jul 18 12:38:04 PDT 2011


Hi!
The patch below enables searching for library names on aptcc. This means
you will be able
to run:
 $ pkcon what-provides libpackagekit.so.14
and get "libpackagekit-glib2-14" as result on Debian machines.
This already works well on Fedora with RPM.
Daniel, could you please take a look at the patch below and say if I can
commit it? It still has some very rough edges and I hope the regex handling
is okay (:P) - if someone knows how to do it better, please speak up.
Thanks!
Cheers,
   Matthias

diff --git a/backends/aptcc/apt.cpp b/backends/aptcc/apt.cpp
index 694b098..98506af 100644
--- a/backends/aptcc/apt.cpp
+++ b/backends/aptcc/apt.cpp
@@ -47,6 +47,7 @@
 #include <fstream>
 #include <dirent.h>
 #include <assert.h>
+#include <regex.h>
 
 aptcc::aptcc(PkBackend *backend, bool &cancel)
 	:
@@ -421,7 +422,8 @@ void
aptcc::emitUpdates(vector<pair<pkgCache::PkgIterator, pkgCache::VerIterator
 	}
 }
 
-void aptcc::povidesCodec(vector<pair<pkgCache::PkgIterator,
pkgCache::VerIterator> > &output,
+// search packages which provide a codec (specified in "values")
+void aptcc::providesCodec(vector<pair<pkgCache::PkgIterator,
pkgCache::VerIterator> > &output,
                          gchar **values)
 {
     GstMatcher *matcher = new GstMatcher(values);
@@ -463,6 +465,78 @@ void
aptcc::povidesCodec(vector<pair<pkgCache::PkgIterator, pkgCache::VerIterato
     delete matcher;
 }
 
+// search packages which provide the libraries specified in "values"
+void aptcc::providesLibrary(vector<pair<pkgCache::PkgIterator,
pkgCache::VerIterator> > &output,
+                         gchar **values)
+{
+	bool ret = false;
+	// Quick-check for library names
+	for (uint i = 0; i < g_strv_length(values); i++)
+		if (g_str_has_prefix (values[i], "lib")) {
+			ret = true;
+			break;
+		}
+	if (!ret)
+		return;
+
+	const char *libreg_str = "^\\(lib.*\\)\\.so\\.[0-9]*";
+	g_debug ("RegStr: %s", libreg_str);
+	regex_t libreg;
+	if(regcomp(&libreg, libreg_str, 0) != 0) {
+		g_debug("Regex compilation error: ", libreg);
+		return;
+	}
+
+	gchar *value;
+	for (uint i = 0; i < g_strv_length(values); i++) {
+		value = values[i];
+		regmatch_t matches[2];
+		if (regexec(&libreg, value, 2, matches, 0) != REG_NOMATCH) {
+			string libPkgName = string(value, matches[1].rm_so, matches[1].rm_eo -
matches[1].rm_so);
+
+			string strvalue = string(value);
+			ssize_t pos = strvalue.find (".so.");
+			if ((pos != string::npos) && (pos > 0)) {
+				// If last char is a number, add a "-" (to be policy-compliant)
+				if (g_ascii_isdigit (libPkgName.at (libPkgName.length () - 1)))
+					libPkgName.append ("-");
+
+				libPkgName.append (strvalue.substr (pos + 4));
+			}
+
+			g_debug ("PkgString: %s", libPkgName.c_str ());
+
+			for (pkgCache::PkgIterator pkg = packageCache->PkgBegin(); !pkg.end();
++pkg) {
+				// Ignore packages that exist only due to dependencies.
+				if (pkg.VersionList().end() && pkg.ProvidesList().end()) {
+				continue;
+				}
+
+				// TODO: Ignore virtual packages
+				pkgCache::VerIterator ver = find_ver (pkg);
+				if (ver.end() == true) {
+					ver = find_candidate_ver(pkg);
+					if (ver.end() == true) {
+						continue;
+					}
+				}
+
+				// Make everything lower-case
+				std::transform(libPkgName.begin(), libPkgName.end(),
libPkgName.begin(), ::tolower);
+
+				if (g_strcmp0 (pkg.Name (), libPkgName.c_str ()) == 0) {
+					output.push_back(pair<pkgCache::PkgIterator,
pkgCache::VerIterator>(pkg, ver));
+				}
+			}
+
+		} else {
+			g_debug("libmatcher: Did not match: %s", value);
+		}
+	}
+
+}
+
 // used to emit packages it collects all the needed info
 void aptcc::emit_details(const pkgCache::PkgIterator &pkg, const
pkgCache::VerIterator &version)
 {
diff --git a/backends/aptcc/apt.h b/backends/aptcc/apt.h
index 02d7f91..3751ae2 100644
--- a/backends/aptcc/apt.h
+++ b/backends/aptcc/apt.h
@@ -123,9 +123,15 @@ public:
 	bool installPackages(pkgCacheFile &Cache);
 
 	/**
-	 *  check if the package provides the codec
+	 *  check which package provides the codec
 	 */
-	void povidesCodec(vector<pair<pkgCache::PkgIterator,
pkgCache::VerIterator> > &output,
+	void providesCodec(vector<pair<pkgCache::PkgIterator,
pkgCache::VerIterator> > &output,
+			  gchar **values);
+
+	/**
+	 *  check which package provides a shared library
+	 */
+	void providesLibrary(vector<pair<pkgCache::PkgIterator,
pkgCache::VerIterator> > &output,
 			  gchar **values);
 
 	pkgRecords    *packageRecords;
diff --git a/backends/aptcc/gstMatcher.cpp b/backends/aptcc/gstMatcher.cpp
index 9f60581..7e5e1d6 100644
--- a/backends/aptcc/gstMatcher.cpp
+++ b/backends/aptcc/gstMatcher.cpp
@@ -43,7 +43,7 @@ GstMatcher::GstMatcher(gchar **values)
     for (uint i = 0; i < g_strv_length(values); i++) {
         value = values[i];
         regmatch_t matches[5];
-        if (regexec(&pkre, value, 5, matches, 0) == 0) {
+        if (regexec(&pkre, value, 5, matches, 0) != REG_NOMATCH) {
             Match values;
             string version, type, data, opt;
 
@@ -100,7 +100,7 @@ GstMatcher::GstMatcher(gchar **values)
 
             m_matches.push_back(values);
         } else {
-            g_debug("Did not match: %s", value);
+            g_debug("gstmatcher: Did not match: %s", value);
         }
     }
     regfree(&pkre);
diff --git a/backends/aptcc/pk-backend-aptcc.cpp
b/backends/aptcc/pk-backend-aptcc.cpp
index 07e3cd1..dc35c6a 100644
--- a/backends/aptcc/pk-backend-aptcc.cpp
+++ b/backends/aptcc/pk-backend-aptcc.cpp
@@ -524,7 +524,9 @@ backend_what_provides_thread (PkBackend *backend)
 
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
 
-	if (provides == PK_PROVIDES_ENUM_MIMETYPE ||
+	// We can handle libraries, mimetypes and codecs
+	if (provides == PK_PROVIDES_ENUM_LIBRARY ||
+	    provides == PK_PROVIDES_ENUM_MIMETYPE ||
 	    provides == PK_PROVIDES_ENUM_CODEC ||
 	    provides == PK_PROVIDES_ENUM_ANY) {
 		aptcc *m_apt = new aptcc(backend, _cancel);
@@ -537,30 +539,32 @@ backend_what_provides_thread (PkBackend *backend)
 			return false;
 		}
 
-
 		pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
 		vector<string> packages;
 		vector<pair<pkgCache::PkgIterator, pkgCache::VerIterator> > output;
-		if (provides == PK_PROVIDES_ENUM_MIMETYPE) {
+
+		if (provides == PK_PROVIDES_ENUM_LIBRARY) {
+			m_apt->providesLibrary (output, values);
+		} else if (provides == PK_PROVIDES_ENUM_MIMETYPE) {
 			packages = searchMimeType (backend, values, error, _cancel);
 		} else if (provides == PK_PROVIDES_ENUM_CODEC) {
-			m_apt->povidesCodec(output, values);
+			m_apt->providesCodec (output, values);
 		} else {
-			// any...
+			// PK_PROVIDES_ENUM_ANY, just search for everything a package can
provide
+			m_apt->providesLibrary (output, values);
+			m_apt->providesCodec (output, values);
 			packages = searchMimeType (backend, values, error, _cancel);
-			m_apt->povidesCodec(output, values);
 		}
 
-		for(vector<string>::iterator i = packages.begin();
-		    i != packages.end(); ++i)
-		{
+		for (vector<string>::iterator i = packages.begin();
+		    i != packages.end(); ++i) {
 			if (_cancel) {
 			    break;
 			}
 			pkgCache::PkgIterator pkg = m_apt->packageCache->FindPkg(i->c_str());
-            if (pkg.end() == true) {
-                continue;
-            }
+			if (pkg.end() == true) {
+				continue;
+			}
 			pkgCache::VerIterator ver = m_apt->find_ver(pkg);
 			if (ver.end() == true) {
 				continue;
@@ -586,6 +590,7 @@ backend_what_provides_thread (PkBackend *backend)
 		}
 
 		delete m_apt;
+
 	} else {
 		provides_text = pk_provides_enum_to_string (provides);
 		pk_backend_error_code (backend,




More information about the PackageKit mailing list