[gnome-software] Add a plugin that uses librpm to get the package versions on an OSTree system
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Add a plugin that uses librpm to get the package versions on an OSTree system
- Date: Fri, 25 Mar 2016 17:05:12 +0000 (UTC)
commit 5c20c0508109a39d4c5d9db1783dcee6826a1799
Author: Richard Hughes <richard hughsie com>
Date: Fri Mar 25 16:47:17 2016 +0000
Add a plugin that uses librpm to get the package versions on an OSTree system
On OSTree we have no PackageKit available, so we have to skip a layer.
configure.ac | 23 ++++
contrib/gnome-software.spec.in | 1 +
src/plugins/Makefile.am | 12 ++
src/plugins/gs-appstream.c | 3 +
src/plugins/gs-plugin-packagekit-refine.c | 12 ++
src/plugins/gs-plugin-rpm.c | 196 +++++++++++++++++++++++++++++
6 files changed, 247 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 28f4e5f..24ad5b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -223,6 +223,28 @@ AS_IF([test "x$have_limba" = "xyes"], [
])
AM_CONDITIONAL(HAVE_LIMBA, test x$enable_limba = xyes)
+# RPM
+AC_ARG_ENABLE(rpm,
+ [AS_HELP_STRING([--enable-rpm],
+ [enable RPM support [default=auto]])],,
+ enable_rpm=maybe)
+AS_IF([test "x$enable_rpm" != "xno"], [
+ PKG_CHECK_MODULES(RPM,
+ rpm,
+ [have_rpm=yes],
+ [have_rpm=no])
+], [
+ have_rpm=no
+])
+AS_IF([test "x$have_rpm" = "xyes"], [
+ AC_DEFINE(HAVE_RPM, 1, [Build RPM support])
+], [
+ AS_IF([test "x$enable_rpm" = "xyes"], [
+ AC_MSG_ERROR([RPM support requested but 'rpm' was not found])
+ ])
+])
+AM_CONDITIONAL(HAVE_RPM, test x$have_rpm = xyes)
+
# Steam
AC_ARG_ENABLE(steam,
[AS_HELP_STRING([--enable-steam],
@@ -308,6 +330,7 @@ echo "
Limba support: ${have_limba}
XDG-APP support: ${have_xdg_app}
OSTree support: ${have_ostree}
+ RPM support: ${have_rpm}
Steam support: ${enable_steam}
GNOME Shell ext. support: ${enable_shell_extensions}
ODRS support: ${enable_odrs}
diff --git a/contrib/gnome-software.spec.in b/contrib/gnome-software.spec.in
index 8b7e866..03e98b1 100644
--- a/contrib/gnome-software.spec.in
+++ b/contrib/gnome-software.spec.in
@@ -32,6 +32,7 @@ BuildRequires: gsettings-desktop-schemas-devel
BuildRequires: libappstream-glib-devel
BuildRequires: fwupd-devel
BuildRequires: json-glib-devel
+BuildRequires: rpm-devel
# this is not a library version
%define gs_plugin_version 9
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index d0ddf85..85a7f0d 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
$(LIMBA_CFLAGS) \
$(OSTREE_CFLAGS) \
$(XDG_APP_CFLAGS) \
+ $(RPM_CFLAGS) \
-DBINDIR=\"$(bindir)\" \
-DDATADIR=\"$(datadir)\" \
-DGS_MODULESETDIR=\"$(datadir)/gnome-software/modulesets.d\" \
@@ -84,6 +85,10 @@ if HAVE_ODRS
plugin_LTLIBRARIES += libgs_plugin_odrs.la
endif
+if HAVE_RPM
+plugin_LTLIBRARIES += libgs_plugin_rpm.la
+endif
+
libgs_plugin_dummy_la_SOURCES = gs-plugin-dummy.c
libgs_plugin_dummy_la_LIBADD = $(GS_PLUGIN_LIBS)
libgs_plugin_dummy_la_LDFLAGS = -module -avoid-version
@@ -162,6 +167,13 @@ libgs_plugin_odrs_la_LDFLAGS = -module -avoid-version
libgs_plugin_odrs_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
endif
+if HAVE_RPM
+libgs_plugin_rpm_la_SOURCES = gs-plugin-rpm.c
+libgs_plugin_rpm_la_LIBADD = $(GS_PLUGIN_LIBS) $(RPM_LIBS)
+libgs_plugin_rpm_la_LDFLAGS = -module -avoid-version
+libgs_plugin_rpm_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
+endif
+
if HAVE_STEAM
libgs_plugin_steam_la_SOURCES = gs-plugin-steam.c
libgs_plugin_steam_la_LIBADD = $(GS_PLUGIN_LIBS)
diff --git a/src/plugins/gs-appstream.c b/src/plugins/gs-appstream.c
index d5ca7f0..a8f2f40 100644
--- a/src/plugins/gs-appstream.c
+++ b/src/plugins/gs-appstream.c
@@ -409,6 +409,9 @@ gs_appstream_refine_app (GsPlugin *plugin,
if (as_app_get_id (item) != NULL && gs_app_get_id (app) == NULL)
gs_app_set_id (app, as_app_get_id (item));
+ /* set source */
+ gs_app_set_metadata (app, "appstream::source-file", as_app_get_source_file (item));
+
/* set name */
tmp = as_app_get_name (item, NULL);
if (tmp != NULL) {
diff --git a/src/plugins/gs-plugin-packagekit-refine.c b/src/plugins/gs-plugin-packagekit-refine.c
index 714c340..5f71b9f 100644
--- a/src/plugins/gs-plugin-packagekit-refine.c
+++ b/src/plugins/gs-plugin-packagekit-refine.c
@@ -56,6 +56,18 @@ gs_plugin_get_name (void)
}
/**
+ * gs_plugin_get_conflicts:
+ */
+const gchar **
+gs_plugin_get_conflicts (GsPlugin *plugin)
+{
+ static const gchar *deps[] = {
+ "rpm",
+ NULL };
+ return deps;
+}
+
+/**
* gs_plugin_initialize:
*/
static void
diff --git a/src/plugins/gs-plugin-rpm.c b/src/plugins/gs-plugin-rpm.c
new file mode 100644
index 0000000..602bdc2
--- /dev/null
+++ b/src/plugins/gs-plugin-rpm.c
@@ -0,0 +1,196 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmts.h>
+
+#include <gs-plugin.h>
+
+struct GsPluginPrivate {
+ rpmts ts;
+ gboolean loaded;
+};
+
+/**
+ * gs_plugin_get_name:
+ */
+const gchar *
+gs_plugin_get_name (void)
+{
+ return "rpm";
+}
+
+/**
+ * gs_plugin_get_deps:
+ */
+const gchar **
+gs_plugin_get_deps (GsPlugin *plugin)
+{
+ static const gchar *deps[] = {
+ "appstream", /* need application IDs */
+ NULL };
+ return deps;
+}
+
+/**
+ * gs_plugin_initialize:
+ */
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+ plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+
+ /* only works with an rpmdb */
+ if (!g_file_test ("/var/lib/rpm/Packages", G_FILE_TEST_EXISTS)) {
+ gs_plugin_set_enabled (plugin, FALSE);
+ return;
+ }
+
+ /* open transaction */
+ rpmReadConfigFiles(NULL, NULL);
+ plugin->priv->ts = rpmtsCreate();
+}
+
+/**
+ * gs_plugin_destroy:
+ */
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+ if (plugin->priv->ts != NULL) {
+ rpmtsCloseDB (plugin->priv->ts);
+ rpmtsFree (plugin->priv->ts);
+ }
+}
+
+/**
+ * gs_plugin_startup:
+ */
+static gboolean
+gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+ gint rc;
+
+ /* already started */
+ if (plugin->priv->loaded)
+ return TRUE;
+
+ /* open db readonly */
+ rpmtsSetRootDir (plugin->priv->ts, NULL);
+ rc = rpmtsOpenDB (plugin->priv->ts, O_RDONLY);
+ if (rc != 0) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_FAILED,
+ "Failed to open rpmdb: %i", rc);
+ return FALSE;
+ }
+ plugin->priv->loaded = TRUE;
+ return TRUE;
+}
+
+/**
+ * gs_plugin_refine_app:
+ */
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+ GsApp *app,
+ GsPluginRefineFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ Header h;
+ const gchar *fn;
+ rpmdbMatchIterator mi;
+
+ /* required */
+ if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION) == 0 &&
+ (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION) == 0)
+ return TRUE;
+
+ /* ensure database open */
+ if (!gs_plugin_startup (plugin, cancellable, error))
+ return FALSE;
+
+ /* no need to run the plugin */
+ if (gs_app_get_source_default (app) != NULL &&
+ gs_app_get_source_id_default (app) != NULL)
+ return TRUE;
+
+ /* look for a specific file */
+ fn = gs_app_get_metadata_item (app, "appstream::source-file");
+ if (fn == NULL)
+ return TRUE;
+ if (!g_str_has_prefix (fn, "/usr"))
+ return TRUE;
+ mi = rpmtsInitIterator(plugin->priv->ts, RPMDBI_INSTFILENAMES, fn, 0);
+ if (mi == NULL) {
+ g_debug ("rpm: no search results for %s", fn);
+ return TRUE;
+ }
+
+ /* process any results */
+ g_debug ("rpm: querying with %s", fn);
+ while ((h = rpmdbNextIterator(mi)) != NULL) {
+ guint64 epoch;
+ const gchar *name;
+ const gchar *version;
+ const gchar *arch;
+ const gchar *release;
+ g_autofree gchar *tmp = NULL;
+
+ /* add default source */
+ name = headerGetString (h, RPMTAG_NAME);
+ if (gs_app_get_source_default (app) == NULL) {
+ g_debug ("rpm: setting source to %s", name);
+ gs_app_add_source (app, name);
+ }
+
+ /* add version */
+ version = headerGetString (h, RPMTAG_VERSION);
+ if (gs_app_get_version (app) == NULL) {
+ g_debug ("rpm: setting version to %s", version);
+ gs_app_set_version (app, version);
+ }
+
+ /* add source-id */
+ if (gs_app_get_source_id_default (app) == NULL) {
+ release = headerGetString (h, RPMTAG_RELEASE);
+ arch = headerGetString (h, RPMTAG_ARCH);
+ epoch = headerGetNumber (h, RPMTAG_EPOCH);
+ if (epoch > 0) {
+ tmp = g_strdup_printf ("%s;%" G_GUINT64_FORMAT ":%s-%s;%s;installed",
+ name, epoch, version, release, arch);
+ } else {
+ tmp = g_strdup_printf ("%s;%s-%s;%s;installed",
+ name, version, release, arch);
+ }
+ g_debug ("rpm: setting source-id to %s", tmp);
+ gs_app_add_source_id (app, tmp);
+ }
+ }
+ rpmdbFreeIterator (mi);
+ return TRUE;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]