[gnome-software: 2/8] packagekit: Merge packagekit-history plugin into packagekit




commit d33c2f1f4f78fd645cdcf5779688d3aab1b4e363
Author: Philip Withnall <pwithnall endlessos org>
Date:   Thu May 20 15:07:51 2021 +0100

    packagekit: Merge packagekit-history plugin into packagekit
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>

 contrib/gnome-software.spec.in                    |   1 -
 plugins/packagekit/gs-plugin-packagekit-history.c | 261 ----------------------
 plugins/packagekit/gs-plugin-packagekit.c         | 220 +++++++++++++++++-
 plugins/packagekit/meson.build                    |  16 --
 plugins/rpm-ostree/gs-plugin-rpm-ostree.c         |   1 -
 5 files changed, 219 insertions(+), 280 deletions(-)
---
diff --git a/contrib/gnome-software.spec.in b/contrib/gnome-software.spec.in
index 933adea6e..a624aae3b 100644
--- a/contrib/gnome-software.spec.in
+++ b/contrib/gnome-software.spec.in
@@ -163,7 +163,6 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
 %{gs_plugin_dir}/libgs_plugin_icons.so
 %{gs_plugin_dir}/libgs_plugin_modalias.so
 %{gs_plugin_dir}/libgs_plugin_os-release.so
-%{gs_plugin_dir}/libgs_plugin_packagekit-history.so
 %{gs_plugin_dir}/libgs_plugin_packagekit-local.so
 %{gs_plugin_dir}/libgs_plugin_packagekit-offline.so
 %{gs_plugin_dir}/libgs_plugin_packagekit-proxy.so
diff --git a/plugins/packagekit/gs-plugin-packagekit.c b/plugins/packagekit/gs-plugin-packagekit.c
index a6fbca4f3..358670976 100644
--- a/plugins/packagekit/gs-plugin-packagekit.c
+++ b/plugins/packagekit/gs-plugin-packagekit.c
@@ -20,12 +20,14 @@
 /*
  * SECTION:
  * Uses the system PackageKit instance to return installed packages,
- * sources and the ability to add and remove packages.
+ * sources and the ability to add and remove packages. Supports package history.
  *
  * Requires:    | [source-id]
  * Refines:     | [source-id], [source], [update-details], [management-plugin]
  */
 
+#define GS_PLUGIN_PACKAGEKIT_HISTORY_TIMEOUT   5000 /* ms */
+
 struct GsPluginData {
        PkTask                  *task;
        GMutex                   task_mutex;
@@ -33,10 +35,16 @@ struct GsPluginData {
        PkControl               *control_refine;
        PkClient                *client_refine;
        GMutex                   client_mutex_refine;
+
+       GDBusConnection         *connection_history;
 };
 
 static void gs_plugin_packagekit_updates_changed_cb (PkControl *control, GsPlugin *plugin);
 static void gs_plugin_packagekit_repo_list_changed_cb (PkControl *control, GsPlugin *plugin);
+static gboolean gs_plugin_packagekit_refine_history (GsPlugin      *plugin,
+                                                     GsAppList     *list,
+                                                     GCancellable  *cancellable,
+                                                     GError       **error);
 
 void
 gs_plugin_initialize (GsPlugin *plugin)
@@ -79,6 +87,10 @@ gs_plugin_destroy (GsPlugin *plugin)
        g_mutex_clear (&priv->client_mutex_refine);
        g_object_unref (priv->client_refine);
        g_object_unref (priv->control_refine);
+
+       /* history */
+       if (priv->connection_history != NULL)
+               g_object_unref (priv->connection_history);
 }
 
 static gboolean
@@ -1563,6 +1575,212 @@ gs_plugin_refine (GsPlugin *plugin,
                        gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_PACKAGE);
        }
 
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_HISTORY) != 0) {
+               gboolean ret;
+               guint i;
+               GsApp *app;
+               GPtrArray *sources;
+               g_autoptr(GsAppList) packages = NULL;
+
+               /* add any missing history data */
+               packages = gs_app_list_new ();
+               for (i = 0; i < gs_app_list_length (list); i++) {
+                       app = gs_app_list_index (list, i);
+                       if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
+                               continue;
+                       sources = gs_app_get_sources (app);
+                       if (sources->len == 0)
+                               continue;
+                       if (gs_app_get_install_date (app) != 0)
+                               continue;
+                       gs_app_list_add (packages, app);
+               }
+               if (gs_app_list_length (packages) > 0) {
+                       ret = gs_plugin_packagekit_refine_history (plugin,
+                                                                  packages,
+                                                                  cancellable,
+                                                                  error);
+                       if (!ret)
+                               return FALSE;
+               }
+       }
+
        /* success */
        return TRUE;
 }
+
+static void
+gs_plugin_packagekit_refine_add_history (GsApp *app, GVariant *dict)
+{
+       const gchar *version;
+       gboolean ret;
+       guint64 timestamp;
+       PkInfoEnum info_enum;
+       g_autoptr(GsApp) history = NULL;
+
+       /* create new history item with same ID as parent */
+       history = gs_app_new (gs_app_get_id (app));
+       gs_app_set_kind (history, AS_COMPONENT_KIND_GENERIC);
+       gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_PACKAGE);
+       gs_app_set_name (history, GS_APP_QUALITY_NORMAL, gs_app_get_name (app));
+
+       /* get the installed state */
+       ret = g_variant_lookup (dict, "info", "u", &info_enum);
+       g_assert (ret);
+       switch (info_enum) {
+       case PK_INFO_ENUM_INSTALLING:
+               gs_app_set_state (history, GS_APP_STATE_INSTALLED);
+               break;
+       case PK_INFO_ENUM_REMOVING:
+               gs_app_set_state (history, GS_APP_STATE_AVAILABLE);
+               break;
+       case PK_INFO_ENUM_UPDATING:
+               gs_app_set_state (history, GS_APP_STATE_UPDATABLE);
+               break;
+       default:
+               g_debug ("ignoring history kind: %s",
+                        pk_info_enum_to_string (info_enum));
+               return;
+       }
+
+       /* set the history time and date */
+       ret = g_variant_lookup (dict, "timestamp", "t", &timestamp);
+       g_assert (ret);
+       gs_app_set_install_date (history, timestamp);
+
+       /* set the history version number */
+       ret = g_variant_lookup (dict, "version", "&s", &version);
+       g_assert (ret);
+       gs_app_set_version (history, version);
+
+       /* add the package to the main application */
+       gs_app_add_history (app, history);
+
+       /* use the last event as approximation of the package timestamp */
+       gs_app_set_install_date (app, timestamp);
+}
+
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       priv->connection_history = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
+                                                  cancellable,
+                                                  error);
+       return priv->connection_history != NULL;
+}
+
+static gboolean
+gs_plugin_packagekit_refine_history (GsPlugin      *plugin,
+                                     GsAppList     *list,
+                                     GCancellable  *cancellable,
+                                     GError       **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       gboolean ret;
+       guint j;
+       GsApp *app;
+       guint i = 0;
+       GVariantIter iter;
+       GVariant *value;
+       g_autofree const gchar **package_names = NULL;
+       g_autoptr(GError) error_local = NULL;
+       g_autoptr(GVariant) result = NULL;
+       g_autoptr(GVariant) tuple = NULL;
+
+       /* get an array of package names */
+       package_names = g_new0 (const gchar *, gs_app_list_length (list) + 1);
+       for (j = 0; j < gs_app_list_length (list); j++) {
+               app = gs_app_list_index (list, j);
+               package_names[i++] = gs_app_get_source_default (app);
+       }
+
+       g_debug ("getting history for %u packages", gs_app_list_length (list));
+       result = g_dbus_connection_call_sync (priv->connection_history,
+                                             "org.freedesktop.PackageKit",
+                                             "/org/freedesktop/PackageKit",
+                                             "org.freedesktop.PackageKit",
+                                             "GetPackageHistory",
+                                             g_variant_new ("(^asu)", package_names, 0),
+                                             NULL,
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             GS_PLUGIN_PACKAGEKIT_HISTORY_TIMEOUT,
+                                             cancellable,
+                                             &error_local);
+       if (result == NULL) {
+               if (g_error_matches (error_local,
+                                    G_DBUS_ERROR,
+                                    G_DBUS_ERROR_UNKNOWN_METHOD)) {
+                       g_debug ("No history available as PackageKit is too old: %s",
+                                error_local->message);
+
+                       /* just set this to something non-zero so we don't keep
+                        * trying to call GetPackageHistory */
+                       for (i = 0; i < gs_app_list_length (list); i++) {
+                               app = gs_app_list_index (list, i);
+                               gs_app_set_install_date (app, GS_APP_INSTALL_DATE_UNKNOWN);
+                       }
+               } else if (g_error_matches (error_local,
+                                           G_IO_ERROR,
+                                           G_IO_ERROR_CANCELLED)) {
+                       g_set_error (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_CANCELLED,
+                                    "Failed to get history: %s",
+                                    error_local->message);
+                       return FALSE;
+               } else if (g_error_matches (error_local,
+                                           G_IO_ERROR,
+                                           G_IO_ERROR_TIMED_OUT)) {
+                       g_debug ("No history as PackageKit took too long: %s",
+                                error_local->message);
+                       for (i = 0; i < gs_app_list_length (list); i++) {
+                               app = gs_app_list_index (list, i);
+                               gs_app_set_install_date (app, GS_APP_INSTALL_DATE_UNKNOWN);
+                       }
+               }
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_NOT_SUPPORTED,
+                            "Failed to get history: %s",
+                            error_local->message);
+               return FALSE;
+       }
+
+       /* get any results */
+       tuple = g_variant_get_child_value (result, 0);
+       for (i = 0; i < gs_app_list_length (list); i++) {
+               g_autoptr(GVariant) entries = NULL;
+               app = gs_app_list_index (list, i);
+               ret = g_variant_lookup (tuple,
+                                       gs_app_get_source_default (app),
+                                       "@aa{sv}",
+                                       &entries);
+               if (!ret) {
+                       /* make up a fake entry as we know this package was at
+                        * least installed at some point in time */
+                       if (gs_app_get_state (app) == GS_APP_STATE_INSTALLED) {
+                               g_autoptr(GsApp) app_dummy = NULL;
+                               app_dummy = gs_app_new (gs_app_get_id (app));
+                               gs_plugin_packagekit_set_packaging_format (plugin, app);
+                               gs_app_set_metadata (app_dummy, "GnomeSoftware::Creator",
+                                                    gs_plugin_get_name (plugin));
+                               gs_app_set_install_date (app_dummy, GS_APP_INSTALL_DATE_UNKNOWN);
+                               gs_app_set_kind (app_dummy, AS_COMPONENT_KIND_GENERIC);
+                               gs_app_set_state (app_dummy, GS_APP_STATE_INSTALLED);
+                               gs_app_set_version (app_dummy, gs_app_get_version (app));
+                               gs_app_add_history (app, app_dummy);
+                       }
+                       gs_app_set_install_date (app, GS_APP_INSTALL_DATE_UNKNOWN);
+                       continue;
+               }
+
+               /* add history for application */
+               g_variant_iter_init (&iter, entries);
+               while ((value = g_variant_iter_next_value (&iter))) {
+                       gs_plugin_packagekit_refine_add_history (app, value);
+                       g_variant_unref (value);
+               }
+       }
+       return TRUE;
+}
diff --git a/plugins/packagekit/meson.build b/plugins/packagekit/meson.build
index 035ab3d57..c1dcabfbd 100644
--- a/plugins/packagekit/meson.build
+++ b/plugins/packagekit/meson.build
@@ -95,22 +95,6 @@ shared_module(
   dependencies : [ plugin_libs, packagekit ],
 )
 
-shared_module(
-  'gs_plugin_packagekit-history',
-  sources : [
-    'gs-plugin-packagekit-history.c',
-    'packagekit-common.c',
-  ],
-  include_directories : [
-    include_directories('../..'),
-    include_directories('../../lib'),
-  ],
-  install : true,
-  install_dir: plugin_dir,
-  c_args : cargs,
-  dependencies : [ plugin_libs, packagekit ],
-)
-
 shared_module(
   'gs_plugin_packagekit-upgrade',
   sources : [
diff --git a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
index 27def5045..b26c4e517 100644
--- a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
+++ b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
@@ -68,7 +68,6 @@ gs_plugin_initialize (GsPlugin *plugin)
         * more sense to use a custom plugin instead of using PackageKit.
         */
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit");
-       gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-history");
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-local");
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-offline");
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-proxy");


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