[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