[gnome-software] Rework plugin interface for offline updates



commit 74de976f47c41e5da355e95a52d7a30ec4f5fda2
Author: Kalev Lember <kalevlember gmail com>
Date:   Sat May 30 00:29:04 2015 +0200

    Rework plugin interface for offline updates
    
    Instead of iterating over all apps-to-be-updated and triggering offline
    updates separately for each one of them, add a separate offline update
    plugin function that takes a list of apps to update in one go.
    
    This basically makes offline updates work again after fwupd support was
    added in commit 287e18b1111c2138a41acaf447ffda416718bcba.

 src/gs-plugin-loader.c                  |  104 +++++++++++++++++++++++++++++--
 src/gs-plugin-loader.h                  |    9 +++-
 src/gs-plugin.h                         |   12 +++-
 src/gs-shell-updates.c                  |   32 ++++------
 src/gs-update-list.c                    |   10 +--
 src/gs-update-list.h                    |    2 +-
 src/plugins/gs-plugin-fwupd.c           |   22 ++++++-
 src/plugins/gs-plugin-systemd-updates.c |   18 ++----
 8 files changed, 160 insertions(+), 49 deletions(-)
---
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index cf1ff72..80493ac 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -2585,11 +2585,6 @@ gs_plugin_loader_app_action_async (GsPluginLoader *plugin_loader,
                state->state_success = AS_APP_STATE_UNKNOWN;
                state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
-       case GS_PLUGIN_LOADER_ACTION_UPGRADE:
-               state->function_name = "gs_plugin_app_upgrade";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
-               break;
        default:
                g_assert_not_reached ();
                break;
@@ -3564,4 +3559,103 @@ gs_plugin_loader_filename_to_app_finish (GsPluginLoader *plugin_loader,
 
 /******************************************************************************/
 
+/**
+ * gs_plugin_loader_offline_update_thread_cb:
+ **/
+static void
+gs_plugin_loader_offline_update_thread_cb (GTask *task,
+                                           gpointer object,
+                                           gpointer task_data,
+                                           GCancellable *cancellable)
+{
+       const gchar *function_name = "gs_plugin_offline_update";
+       gboolean ret = TRUE;
+       GError *error = NULL;
+       GsPluginLoaderAsyncState *state = (GsPluginLoaderAsyncState *) task_data;
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (object);
+       GsPlugin *plugin;
+       GsPluginOfflineUpdateFunc plugin_func = NULL;
+       guint i;
+       _cleanup_free_ gchar *profile_id = NULL;
+
+       /* run each plugin */
+       for (i = 0; i < plugin_loader->priv->plugins->len; i++) {
+               plugin = g_ptr_array_index (plugin_loader->priv->plugins, i);
+               if (!plugin->enabled)
+                       continue;
+               ret = g_task_return_error_if_cancelled (task);
+               if (ret)
+                       goto out;
+               ret = g_module_symbol (plugin->module,
+                                      function_name,
+                                      (gpointer *) &plugin_func);
+               if (!ret)
+                       continue;
+               profile_id = g_strdup_printf ("GsPlugin::%s(%s)",
+                                             plugin->name, function_name);
+               gs_profile_start (plugin_loader->priv->profile, profile_id);
+               ret = plugin_func (plugin, state->list, cancellable, &error);
+               if (!ret) {
+                       g_task_return_error (task, error);
+                       goto out;
+               }
+               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
+               gs_profile_stop (plugin_loader->priv->profile, profile_id);
+               g_clear_pointer (&profile_id, g_free);
+       }
+
+       g_task_return_boolean (task, TRUE);
+out:
+       if (profile_id != NULL)
+               gs_profile_stop (plugin_loader->priv->profile, profile_id);
+}
+
+/**
+ * gs_plugin_loader_offline_update_async:
+ *
+ * This method calls all plugins that implement the gs_plugin_add_offline_update()
+ * function.
+ **/
+void
+gs_plugin_loader_offline_update_async (GsPluginLoader *plugin_loader,
+                                       GList *apps,
+                                       GCancellable *cancellable,
+                                       GAsyncReadyCallback callback,
+                                       gpointer user_data)
+{
+       GsPluginLoaderAsyncState *state;
+       _cleanup_object_unref_ GTask *task = NULL;
+
+       g_return_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+       /* save state */
+       state = g_slice_new0 (GsPluginLoaderAsyncState);
+       state->list = g_list_copy_deep (apps, (GCopyFunc) g_object_ref, NULL);
+
+       /* run in a thread */
+       task = g_task_new (plugin_loader, cancellable, callback, user_data);
+       g_task_set_task_data (task, state, (GDestroyNotify) gs_plugin_loader_free_async_state);
+       g_task_set_return_on_cancel (task, TRUE);
+       g_task_run_in_thread (task, gs_plugin_loader_offline_update_thread_cb);
+}
+
+/**
+ * gs_plugin_loader_offline_update_finish:
+ **/
+gboolean
+gs_plugin_loader_offline_update_finish (GsPluginLoader *plugin_loader,
+                                        GAsyncResult *res,
+                                        GError **error)
+{
+       g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), NULL);
+       g_return_val_if_fail (G_IS_TASK (res), NULL);
+       g_return_val_if_fail (g_task_is_valid (res, plugin_loader), NULL);
+       g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+       return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+/******************************************************************************/
+
 /* vim: set noexpandtab: */
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index c0f743b..de24cda 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -67,7 +67,6 @@ typedef enum {
        GS_PLUGIN_LOADER_ACTION_INSTALL,
        GS_PLUGIN_LOADER_ACTION_REMOVE,
        GS_PLUGIN_LOADER_ACTION_SET_RATING,
-       GS_PLUGIN_LOADER_ACTION_UPGRADE,
        GS_PLUGIN_LOADER_ACTION_LAST
 } GsPluginLoaderAction;
 
@@ -172,6 +171,14 @@ void                gs_plugin_loader_filename_to_app_async (GsPluginLoader 
*plugin_loader,
 GsApp          *gs_plugin_loader_filename_to_app_finish(GsPluginLoader *plugin_loader,
                                                         GAsyncResult   *res,
                                                         GError         **error);
+void            gs_plugin_loader_offline_update_async  (GsPluginLoader *plugin_loader,
+                                                        GList          *apps,
+                                                        GCancellable   *cancellable,
+                                                        GAsyncReadyCallback callback,
+                                                        gpointer        user_data);
+gboolean        gs_plugin_loader_offline_update_finish (GsPluginLoader *plugin_loader,
+                                                        GAsyncResult   *res,
+                                                        GError         **error);
 gboolean        gs_plugin_loader_setup                 (GsPluginLoader *plugin_loader,
                                                         GError         **error);
 void            gs_plugin_loader_dump_state            (GsPluginLoader *plugin_loader);
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index ccc2977..97dfe56 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -148,6 +148,10 @@ typedef gboolean    (*GsPluginFilenameToAppFunc)   (GsPlugin       *plugin,
                                                         const gchar    *filename,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+typedef gboolean        (*GsPluginOfflineUpdateFunc)   (GsPlugin       *plugin,
+                                                        GList          *apps,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 
 const gchar    *gs_plugin_get_name                     (void);
 void            gs_plugin_initialize                   (GsPlugin       *plugin);
@@ -237,10 +241,6 @@ gboolean    gs_plugin_app_set_rating               (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-gboolean        gs_plugin_app_upgrade                  (GsPlugin       *plugin,
-                                                        GsApp          *app,
-                                                        GCancellable   *cancellable,
-                                                        GError         **error);
 gboolean        gs_plugin_refresh                      (GsPlugin       *plugin,
                                                         guint           cache_age,
                                                         GsPluginRefreshFlags flags,
@@ -251,6 +251,10 @@ gboolean    gs_plugin_filename_to_app              (GsPlugin       *plugin,
                                                         const gchar    *filename,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+gboolean        gs_plugin_offline_update               (GsPlugin       *plugin,
+                                                        GList          *apps,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 
 G_END_DECLS
 
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index 4d11e3b..c1c15be 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -836,18 +836,18 @@ gs_offline_updates_cancel (void)
 }
 
 /**
- * gs_shell_updates_upgrade_cb:
+ * gs_shell_updates_offline_update_cb:
  **/
 static void
-gs_shell_updates_upgrade_cb (GsPluginLoader *plugin_loader,
-                            GAsyncResult *res,
-                            GsShellUpdates *shell_updates)
+gs_shell_updates_offline_update_cb (GsPluginLoader *plugin_loader,
+                                    GAsyncResult *res,
+                                    GsShellUpdates *shell_updates)
 {
        _cleanup_error_free_ GError *error = NULL;
 
        /* get the results */
-       if (!gs_plugin_loader_app_action_finish (plugin_loader, res, &error)) {
-               g_warning ("Failed to upgrade: %s", error->message);
+       if (!gs_plugin_loader_offline_update_finish (plugin_loader, res, &error)) {
+               g_warning ("Failed to trigger offline update: %s", error->message);
                return;
        }
        gs_reboot (gs_offline_updates_cancel);
@@ -857,23 +857,17 @@ static void
 gs_shell_updates_button_update_all_cb (GtkButton      *button,
                                       GsShellUpdates *shell_updates)
 {
-       GsApp *app;
        GsShellUpdatesPrivate *priv = shell_updates->priv;
-       guint i;
        _cleanup_error_free_ GError *error = NULL;
-       _cleanup_ptrarray_unref_ GPtrArray *apps = NULL;
+       _cleanup_list_free_ GList *apps = NULL;
 
-       /* do the upgrade action? */
+       /* do the offline update */
        apps = gs_update_list_get_apps (GS_UPDATE_LIST (priv->list_box_updates));
-       for (i = 0; i < apps->len; i++) {
-               app = g_ptr_array_index (apps, i);
-               gs_plugin_loader_app_action_async (priv->plugin_loader,
-                                                  app,
-                                                  GS_PLUGIN_LOADER_ACTION_UPGRADE,
-                                                  priv->cancellable,
-                                                  (GAsyncReadyCallback) gs_shell_updates_upgrade_cb,
-                                                  shell_updates);
-       }
+       gs_plugin_loader_offline_update_async (priv->plugin_loader,
+                                              apps,
+                                              priv->cancellable,
+                                              (GAsyncReadyCallback) gs_shell_updates_offline_update_cb,
+                                              shell_updates);
 }
 
 /**
diff --git a/src/gs-update-list.c b/src/gs-update-list.c
index a900bce..6fcc35f 100644
--- a/src/gs-update-list.c
+++ b/src/gs-update-list.c
@@ -56,19 +56,17 @@ gs_update_list_add_app (GsUpdateList *update_list,
        gtk_widget_show (app_row);
 }
 
-GPtrArray *
+GList *
 gs_update_list_get_apps (GsUpdateList *update_list)
 {
+       GList *apps = NULL;
        GList *l;
-       GPtrArray *apps;
-       GsAppRow *app_row;
        _cleanup_list_free_ GList *children = NULL;
 
-       apps = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
        children = gtk_container_get_children (GTK_CONTAINER (update_list));
        for (l = children; l != NULL; l = l->next) {
-               app_row = GS_APP_ROW (l->data);
-               g_ptr_array_add (apps, g_object_ref (gs_app_row_get_app (app_row)));
+               GsAppRow *app_row = GS_APP_ROW (l->data);
+               apps = g_list_prepend (apps, gs_app_row_get_app (app_row));
        }
        return apps;
 }
diff --git a/src/gs-update-list.h b/src/gs-update-list.h
index aa954aa..9572be8 100644
--- a/src/gs-update-list.h
+++ b/src/gs-update-list.h
@@ -53,7 +53,7 @@ GType          gs_update_list_get_type        (void);
 GtkWidget      *gs_update_list_new             (void);
 void            gs_update_list_add_app         (GsUpdateList   *update_list,
                                                 GsApp          *app);
-GPtrArray      *gs_update_list_get_apps        (GsUpdateList   *update_list);
+GList          *gs_update_list_get_apps        (GsUpdateList   *update_list);
 
 G_END_DECLS
 
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index ac50853..e541467 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -673,7 +673,7 @@ gs_plugin_fwupd_upgrade (GsPlugin *plugin,
 /**
  * gs_plugin_app_upgrade:
  */
-gboolean
+static gboolean
 gs_plugin_app_upgrade (GsPlugin *plugin,
                       GsApp *app,
                       GCancellable *cancellable,
@@ -705,6 +705,26 @@ gs_plugin_app_upgrade (GsPlugin *plugin,
 }
 
 /**
+ * gs_plugin_offline_update:
+ */
+gboolean
+gs_plugin_offline_update (GsPlugin *plugin,
+                          GList *apps,
+                          GCancellable *cancellable,
+                          GError **error)
+{
+       GList *l;
+
+       for (l = apps; l != NULL; l = l->next) {
+               gboolean ret = gs_plugin_app_upgrade (plugin, GS_APP (l->data), cancellable, error);
+               if (!ret)
+                       return FALSE;
+       }
+
+       return TRUE;
+}
+
+/**
  * gs_plugin_app_install:
  */
 gboolean
diff --git a/src/plugins/gs-plugin-systemd-updates.c b/src/plugins/gs-plugin-systemd-updates.c
index e6a47ef..264da63 100644
--- a/src/plugins/gs-plugin-systemd-updates.c
+++ b/src/plugins/gs-plugin-systemd-updates.c
@@ -31,7 +31,6 @@
 struct GsPluginPrivate {
        GFileMonitor            *monitor;
        gsize                    done_init;
-       gboolean                 is_triggered;
 };
 
 /**
@@ -146,18 +145,13 @@ gs_plugin_add_updates (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_app_upgrade:
+ * gs_plugin_offline_update:
  */
 gboolean
-gs_plugin_app_upgrade (GsPlugin *plugin,
-                      GsApp *app,
-                      GCancellable *cancellable,
-                      GError **error)
+gs_plugin_offline_update (GsPlugin *plugin,
+                          GList *apps,
+                          GCancellable *cancellable,
+                          GError **error)
 {
-       if (plugin->priv->is_triggered)
-               return TRUE;
-       if (!pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT, NULL, error))
-               return FALSE;
-       plugin->priv->is_triggered = TRUE;
-       return TRUE;
+       return pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT, cancellable, error);
 }


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