[gnome-software] rpm-ostree: Correctly resolve installed appdata files to package names



commit cea79cd9419e6dc53d701c220de804a6691c86bf
Author: Kalev Lember <klember redhat com>
Date:   Wed Jan 23 14:16:55 2019 +0100

    rpm-ostree: Correctly resolve installed appdata files to package names
    
    This makes use of the custom "appstream::source-file" metadata key that
    was added in commit c7bdc2f to map locally installed appdata files to
    packages.
    
    rpm-ostree doesn't expose enough API to query locally installed files,
    but we can just as well directly ask librpm.

 .gitlab-ci.yml                            |  1 +
 contrib/gnome-software.spec.in            |  1 +
 meson.build                               |  1 +
 plugins/rpm-ostree/gs-plugin-rpm-ostree.c | 97 +++++++++++++++++++++++++++----
 plugins/rpm-ostree/meson.build            |  2 +-
 5 files changed, 90 insertions(+), 12 deletions(-)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 90093205..fa9c73f5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,6 +9,7 @@ before_script:
   - dnf install -y 
https://people.freedesktop.org/~hughsient/temp/libappstream-glib-0.7.14-0.641.20181015git.fc29.x86_64.rpm 
https://people.freedesktop.org/~hughsient/temp/libappstream-glib-devel-0.7.14-0.641.20181015git.fc29.x86_64.rpm
   - dnf --enablerepo updates-testing -y builddep gnome-software
   # Some deps may not be sync'd
+  - dnf -y install rpm-devel
   - dnf -y install rpm-ostree-devel
   - dnf -y install libstemmer-devel
   - dnf -y install gnome-online-accounts-devel
diff --git a/contrib/gnome-software.spec.in b/contrib/gnome-software.spec.in
index e5974895..07be3cfe 100644
--- a/contrib/gnome-software.spec.in
+++ b/contrib/gnome-software.spec.in
@@ -41,6 +41,7 @@ BuildRequires: PackageKit-glib-devel >= %{packagekit_version}
 BuildRequires: polkit-devel
 BuildRequires: flatpak-devel >= %{flatpak_version}
 BuildRequires: ostree-devel
+BuildRequires: rpm-devel
 BuildRequires: rpm-ostree-devel
 BuildRequires: libgudev1-devel
 BuildRequires: valgrind-devel
diff --git a/meson.build b/meson.build
index b3bf29c4..cd971a62 100644
--- a/meson.build
+++ b/meson.build
@@ -159,6 +159,7 @@ endif
 
 if get_option('rpm_ostree')
   ostree = dependency('ostree-1')
+  rpm = dependency('rpm')
   rpm_ostree = dependency('rpm-ostree-1', version : '>= 2018.4')
 endif
 
diff --git a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
index 3ed325a7..80abca30 100644
--- a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
+++ b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2017-2018 Kalev Lember <klember redhat com>
+ * Copyright (C) 2017-2019 Kalev Lember <klember redhat com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -21,11 +21,15 @@
 
 #include <config.h>
 
+#include <gnome-software.h>
+
+#include <fcntl.h>
 #include <gio/gio.h>
 #include <glib/gstdio.h>
-
-#include <gnome-software.h>
 #include <ostree.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmts.h>
 #include <rpmostree.h>
 
 #include "gs-rpmostree-generated.h"
@@ -35,6 +39,9 @@
  */
 #define GS_RPMOSTREE_CLIENT_ID PACKAGE_NAME
 
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(rpmts, rpmtsFree, NULL);
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(rpmdbMatchIterator, rpmdbFreeIterator, NULL);
+
 struct GsPluginData {
        GsRPMOSTreeOS           *os_proxy;
        GsRPMOSTreeSysroot      *sysroot_proxy;
@@ -54,6 +61,9 @@ gs_plugin_initialize (GsPlugin *plugin)
                return;
        }
 
+       /* open transaction */
+       rpmReadConfigFiles(NULL, NULL);
+
        /* rpm-ostree is already a daemon with a DBus API; hence it makes
         * more sense to use a custom plugin instead of using PackageKit.
         */
@@ -772,6 +782,60 @@ resolve_packages_app (GsPlugin *plugin,
        }
 }
 
+static gboolean
+resolve_appstream_source_file_to_package_name (GsPlugin *plugin,
+                                               GsApp *app,
+                                               GsPluginRefineFlags flags,
+                                               GCancellable *cancellable,
+                                               GError **error)
+{
+       Header h;
+       const gchar *fn;
+       gint rc;
+       g_auto(rpmdbMatchIterator) mi = NULL;
+       g_auto(rpmts) ts = NULL;
+
+       /* open db readonly */
+       ts = rpmtsCreate();
+       rpmtsSetRootDir (ts, NULL);
+       rc = rpmtsOpenDB (ts, O_RDONLY);
+       if (rc != 0) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_NOT_SUPPORTED,
+                            "Failed to open rpmdb: %i", rc);
+               return FALSE;
+       }
+
+       /* look for a specific file */
+       fn = gs_app_get_metadata_item (app, "appstream::source-file");
+       if (fn == NULL)
+               return TRUE;
+
+       mi = rpmtsInitIterator (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 for %s with %s", gs_app_get_id (app), fn);
+       while ((h = rpmdbNextIterator (mi)) != NULL) {
+               const gchar *name;
+
+               /* 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);
+                       gs_app_set_management_plugin (app, gs_plugin_get_name (plugin));
+                       gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_PACKAGE);
+               }
+       }
+
+       return TRUE;
+}
+
 gboolean
 gs_plugin_refine (GsPlugin *plugin,
                   GsAppList *list,
@@ -804,19 +868,30 @@ gs_plugin_refine (GsPlugin *plugin,
 
        for (guint i = 0; i < gs_app_list_length (list); i++) {
                GsApp *app = gs_app_list_index (list, i);
-               GPtrArray *sources;
+
                if (gs_app_has_quirk (app, GS_APP_QUIRK_IS_WILDCARD))
                        continue;
-               if (gs_app_get_kind (app) == AS_APP_KIND_WEB_APP)
-                       continue;
-               if (g_strcmp0 (gs_app_get_management_plugin (app), "rpm-ostree") != 0)
+               /* set management plugin for apps where appstream just added the source package name in 
refine() */
+               if (gs_app_get_management_plugin (app) == NULL &&
+                   gs_app_get_bundle_kind (app) == AS_BUNDLE_KIND_PACKAGE &&
+                   gs_app_get_scope (app) == AS_APP_SCOPE_SYSTEM &&
+                   gs_app_get_source_default (app) != NULL) {
+                       gs_app_set_management_plugin (app, gs_plugin_get_name (plugin));
+               }
+               /* resolve the source package name based on installed appdata/desktop file name */
+               if (gs_app_get_management_plugin (app) == NULL &&
+                   gs_app_get_bundle_kind (app) == AS_BUNDLE_KIND_UNKNOWN &&
+                   gs_app_get_scope (app) == AS_APP_SCOPE_SYSTEM &&
+                   gs_app_get_source_default (app) == NULL) {
+                       if (!resolve_appstream_source_file_to_package_name (plugin, app, flags, cancellable, 
error))
+                               return FALSE;
+               }
+               if (g_strcmp0 (gs_app_get_management_plugin (app), gs_plugin_get_name (plugin)) != 0)
                        continue;
-               sources = gs_app_get_sources (app);
-               if (sources->len == 0)
+               if (gs_app_get_source_default (app) == NULL)
                        continue;
 
-               if (gs_app_get_state (app) == AS_APP_STATE_UNKNOWN)
-                       resolve_packages_app (plugin, pkglist, layered_packages, app);
+               resolve_packages_app (plugin, pkglist, layered_packages, app);
        }
 
        return TRUE;
diff --git a/plugins/rpm-ostree/meson.build b/plugins/rpm-ostree/meson.build
index 8cf509db..7c2b5eeb 100644
--- a/plugins/rpm-ostree/meson.build
+++ b/plugins/rpm-ostree/meson.build
@@ -18,7 +18,7 @@ shared_module(
   install : true,
   install_dir: plugin_dir,
   c_args : cargs,
-  dependencies : [ plugin_libs, ostree, rpm_ostree ],
+  dependencies : [ plugin_libs, ostree, rpm, rpm_ostree ],
   link_with : [
     libgnomesoftware
   ]


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]