[gnome-software/wip/temp/ubuntu-xenial-rebased: 209/326] Add the concept of UpdateAll into the plugin loader



commit db0295d02ae79cfd1df6cfc6a74ffd027303ef93
Author: Richard Hughes <richard hughsie com>
Date:   Fri Apr 8 09:02:34 2016 +0100

    Add the concept of UpdateAll into the plugin loader
    
    We had the gs_plugin_app_update() plugin vfunc to update a specific application,
    and a gs_plugin_offline_update() vfunc to schedule a list of updates to be
    installed offline. For us to support other packaging systems that supported
    updating *all* the updatable GsApps live (for instance aptd) we need an update
    method to take a list of GsApps, not a single object.
    
    We can just rename the gs_plugin_offline_update() to gs_plugin_update() which
    allows plugins that need to build a transaction of lots of packages rather than
    one transaction for each GsApp. To avoid plugins having to each traverse the
    list and check the management plugin, we also fall back to calling
    gs_plugin_update_app() on plugins just like we do for refine() and refine_app().
    
    This means that existing plugins that just schedule the install to be done just
    have to check if any application is OFFLINE rather than OFFLINE_LIVE, and
    plugins that don't issue a large transaction can continue to use the
    gs_plugin_update_app() vfunc as it will only be run when the management plugin
    is correct.
    
    Many thanks to William Hua for prototyping all the different ways to do this,
    and spending the time working out all the details.

 src/gs-application.c                    |   14 ++--
 src/gs-plugin-loader.c                  |   98 +++++++++++++++++++++++++------
 src/gs-plugin-loader.h                  |    4 +-
 src/gs-plugin.h                         |    8 +-
 src/gs-shell-updates.c                  |   24 ++++----
 src/plugins/gs-plugin-fwupd.c           |   22 +++++---
 src/plugins/gs-plugin-limba.c           |    4 +-
 src/plugins/gs-plugin-systemd-updates.c |   20 +++---
 src/plugins/gs-plugin-xdg-app.c         |    6 +-
 9 files changed, 132 insertions(+), 68 deletions(-)
---
diff --git a/src/gs-application.c b/src/gs-application.c
index 02270fa..025f2fa 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -426,7 +426,7 @@ reboot_failed_cb (GObject *source, GAsyncResult *res, gpointer user_data)
        /* cancel trigger */
        gs_plugin_loader_app_action_async (app->plugin_loader,
                                           NULL, /* everything! */
-                                          GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL,
+                                          GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL,
                                           app->cancellable,
                                           cancel_trigger_failed_cb,
                                           app);
@@ -442,7 +442,7 @@ offline_update_cb (GsPluginLoader *plugin_loader,
 {
        g_autoptr(GDBusConnection) bus = NULL;
        g_autoptr(GError) error = NULL;
-       if (!gs_plugin_loader_offline_update_finish (plugin_loader, res, &error)) {
+       if (!gs_plugin_loader_update_finish (plugin_loader, res, &error)) {
                g_warning ("Failed to trigger offline update: %s", error->message);
                return;
        }
@@ -467,11 +467,11 @@ reboot_and_install (GSimpleAction *action,
 {
        GsApplication *app = GS_APPLICATION (data);
        gs_application_initialize_plugins (app);
-       gs_plugin_loader_offline_update_async (app->plugin_loader,
-                                              NULL,
-                                              app->cancellable,
-                                              (GAsyncReadyCallback) offline_update_cb,
-                                              app);
+       gs_plugin_loader_update_async (app->plugin_loader,
+                                      NULL,
+                                      app->cancellable,
+                                      (GAsyncReadyCallback) offline_update_cb,
+                                      app);
 }
 
 static void
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 287d3b5..012c5af 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -2621,6 +2621,15 @@ gs_plugin_loader_app_action_async (GsPluginLoader *plugin_loader,
        g_return_if_fail (GS_IS_APP (app));
        g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
+       /* handle with a fake list */
+       if (action == GS_PLUGIN_LOADER_ACTION_UPDATE) {
+               g_autoptr(GsAppList) list = NULL;
+               gs_plugin_add_app (&list, app);
+               gs_plugin_loader_update_async (plugin_loader, list,
+                                              cancellable, callback,
+                                              user_data);
+       }
+
        if (action == GS_PLUGIN_LOADER_ACTION_REMOVE) {
                if (remove_app_from_install_queue (plugin_loader, app)) {
                        task = g_task_new (plugin_loader, cancellable, callback, user_data);
@@ -3760,21 +3769,22 @@ gs_plugin_loader_filename_to_app_finish (GsPluginLoader *plugin_loader,
 /******************************************************************************/
 
 /**
- * gs_plugin_loader_offline_update_thread_cb:
+ * gs_plugin_loader_update_thread_cb:
  **/
 static void
-gs_plugin_loader_offline_update_thread_cb (GTask *task,
-                                           gpointer object,
-                                           gpointer task_data,
-                                           GCancellable *cancellable)
+gs_plugin_loader_update_thread_cb (GTask *task,
+                                  gpointer object,
+                                  gpointer task_data,
+                                  GCancellable *cancellable)
 {
        GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (object);
        GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
-       const gchar *function_name = "gs_plugin_offline_update";
+       const gchar *function_name = "gs_plugin_update";
        gboolean ret = TRUE;
        GsPluginLoaderAsyncState *state = (GsPluginLoaderAsyncState *) task_data;
        GsPlugin *plugin;
-       GsPluginOfflineUpdateFunc plugin_func = NULL;
+       GsPluginUpdateFunc plugin_func = NULL;
+       GsPluginActionFunc plugin_app_func = NULL;
        guint i;
 
        /* run each plugin */
@@ -3808,21 +3818,71 @@ gs_plugin_loader_offline_update_thread_cb (GTask *task,
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 
+       /* run each plugin, per-app version */
+       function_name = "gs_plugin_update_app";
+       for (i = 0; i < priv->plugins->len; i++) {
+               GList *l;
+
+               plugin = g_ptr_array_index (priv->plugins, i);
+               if (!plugin->enabled)
+                       continue;
+               ret = g_task_return_error_if_cancelled (task);
+               if (ret)
+                       return;
+               ret = g_module_symbol (plugin->module,
+                                      function_name,
+                                      (gpointer *) &plugin_app_func);
+               if (!ret)
+                       continue;
+
+               /* for each app */
+               for (l = state->list; l != NULL; l = l->next) {
+                       GsApp *app = GS_APP (l->data);
+                       const gchar *management_plugin;
+                       g_autoptr(AsProfileTask) ptask = NULL;
+                       g_autoptr(GError) error_local = NULL;
+
+                       /* only run method for the correct plugin */
+                       management_plugin = gs_app_get_management_plugin (app);
+                       if (g_strcmp0 (management_plugin, plugin->name) != 0) {
+                               g_debug ("skipping %s:%s as invalid (%s)",
+                                        plugin->name, function_name, management_plugin);
+                               continue;
+                       }
+
+                       ptask = as_profile_start (priv->profile,
+                                                 "GsPlugin::%s(%s){%s}",
+                                                 plugin->name,
+                                                 function_name,
+                                                 gs_app_get_id (app));
+                       ret = plugin_app_func (plugin, app,
+                                              cancellable,
+                                              &error_local);
+                       if (!ret) {
+                               g_warning ("failed to call %s on %s: %s",
+                                          function_name, plugin->name,
+                                          error_local->message);
+                               continue;
+                       }
+               }
+               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
+       }
+
        g_task_return_boolean (task, TRUE);
 }
 
 /**
- * gs_plugin_loader_offline_update_async:
+ * gs_plugin_loader_update_async:
  *
- * This method calls all plugins that implement the gs_plugin_add_offline_update()
- * function.
+ * This method calls all plugins that implement the gs_plugin_update()
+ * or gs_plugin_update_app() functions.
  **/
 void
-gs_plugin_loader_offline_update_async (GsPluginLoader *plugin_loader,
-                                       GList *apps,
-                                       GCancellable *cancellable,
-                                       GAsyncReadyCallback callback,
-                                       gpointer user_data)
+gs_plugin_loader_update_async (GsPluginLoader *plugin_loader,
+                              GList *apps,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
 {
        GsPluginLoaderAsyncState *state;
        g_autoptr(GTask) task = NULL;
@@ -3841,12 +3901,12 @@ gs_plugin_loader_offline_update_async (GsPluginLoader *plugin_loader,
 }
 
 /**
- * gs_plugin_loader_offline_update_finish:
+ * gs_plugin_loader_update_finish:
  **/
 gboolean
-gs_plugin_loader_offline_update_finish (GsPluginLoader *plugin_loader,
-                                        GAsyncResult *res,
-                                        GError **error)
+gs_plugin_loader_update_finish (GsPluginLoader *plugin_loader,
+                               GAsyncResult *res,
+                               GError **error)
 {
        g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), FALSE);
        g_return_val_if_fail (G_IS_TASK (res), FALSE);
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index 1eeb095..a01d8b1 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -181,12 +181,12 @@ 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,
+void            gs_plugin_loader_update_async          (GsPluginLoader *plugin_loader,
                                                         GList          *apps,
                                                         GCancellable   *cancellable,
                                                         GAsyncReadyCallback callback,
                                                         gpointer        user_data);
-gboolean        gs_plugin_loader_offline_update_finish (GsPluginLoader *plugin_loader,
+gboolean        gs_plugin_loader_update_finish         (GsPluginLoader *plugin_loader,
                                                         GAsyncResult   *res,
                                                         GError         **error);
 gboolean        gs_plugin_loader_setup                 (GsPluginLoader *plugin_loader,
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index c1862e1..daddef7 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -195,7 +195,7 @@ typedef gboolean     (*GsPluginFilenameToAppFunc)   (GsPlugin       *plugin,
                                                         const gchar    *filename,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-typedef gboolean        (*GsPluginOfflineUpdateFunc)   (GsPlugin       *plugin,
+typedef gboolean        (*GsPluginUpdateFunc)          (GsPlugin       *plugin,
                                                         GList          *apps,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
@@ -315,7 +315,7 @@ gboolean     gs_plugin_launch                       (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-gboolean        gs_plugin_offline_update_cancel        (GsPlugin       *plugin,
+gboolean        gs_plugin_update_cancel                (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
@@ -331,7 +331,7 @@ gboolean     gs_plugin_app_set_rating               (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-gboolean        gs_plugin_app_update                   (GsPlugin       *plugin,
+gboolean        gs_plugin_update_app                   (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
@@ -383,7 +383,7 @@ gboolean     gs_plugin_filename_to_app              (GsPlugin       *plugin,
                                                         const gchar    *filename,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-gboolean        gs_plugin_offline_update               (GsPlugin       *plugin,
+gboolean        gs_plugin_update                       (GsPlugin       *plugin,
                                                         GList          *apps,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index 1e3156a..9aaf391 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -936,17 +936,17 @@ gs_shell_updates_reboot_failed_cb (GObject *source, GAsyncResult *res, gpointer
        apps = gs_update_list_get_apps (GS_UPDATE_LIST (self->list_box_updates));
        gs_plugin_loader_app_action_async (self->plugin_loader,
                                           GS_APP (apps->data),
-                                          GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL,
+                                          GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL,
                                           self->cancellable,
                                           cancel_trigger_failed_cb,
                                           self);
 }
 
 /**
- * gs_shell_updates_offline_update_cb:
+ * gs_shell_updates_perform_update_cb:
  **/
 static void
-gs_shell_updates_offline_update_cb (GsPluginLoader *plugin_loader,
+gs_shell_updates_perform_update_cb (GsPluginLoader *plugin_loader,
                                     GAsyncResult *res,
                                     GsShellUpdates *self)
 {
@@ -954,8 +954,8 @@ gs_shell_updates_offline_update_cb (GsPluginLoader *plugin_loader,
        g_autoptr(GError) error = NULL;
 
        /* get the results */
-       if (!gs_plugin_loader_offline_update_finish (plugin_loader, res, &error)) {
-               g_warning ("Failed to trigger offline update: %s", error->message);
+       if (!gs_plugin_loader_update_finish (plugin_loader, res, &error)) {
+               g_warning ("Failed to perform update: %s", error->message);
                return;
        }
 
@@ -981,11 +981,11 @@ gs_shell_updates_button_update_all_cb (GtkButton      *button,
 
        /* do the offline update */
        apps = gs_update_list_get_apps (GS_UPDATE_LIST (self->list_box_updates));
-       gs_plugin_loader_offline_update_async (self->plugin_loader,
-                                              apps,
-                                              self->cancellable,
-                                              (GAsyncReadyCallback) gs_shell_updates_offline_update_cb,
-                                              self);
+       gs_plugin_loader_update_async (self->plugin_loader,
+                                      apps,
+                                      self->cancellable,
+                                      (GAsyncReadyCallback) gs_shell_updates_perform_update_cb,
+                                      self);
 }
 
 typedef struct {
@@ -1092,7 +1092,7 @@ upgrade_reboot_failed_cb (GObject *source,
        apps = gs_update_list_get_apps (GS_UPDATE_LIST (self->list_box_updates));
        gs_plugin_loader_app_action_async (self->plugin_loader,
                                           GS_APP (apps->data),
-                                          GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL,
+                                          GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL,
                                           self->cancellable,
                                           cancel_trigger_failed_cb,
                                           self);
@@ -1108,7 +1108,7 @@ upgrade_trigger_finished_cb (GObject *source,
        g_autoptr(GError) error = NULL;
 
        /* get the results */
-       if (!gs_plugin_loader_offline_update_finish (self->plugin_loader, res, &error)) {
+       if (!gs_plugin_loader_update_finish (self->plugin_loader, res, &error)) {
                g_warning ("Failed to trigger offline update: %s", error->message);
                return;
        }
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index 99e7a3d..583ea3d 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -877,13 +877,13 @@ gs_plugin_app_upgrade (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_offline_update:
+ * gs_plugin_update:
  */
 gboolean
-gs_plugin_offline_update (GsPlugin *plugin,
-                          GList *apps,
-                          GCancellable *cancellable,
-                          GError **error)
+gs_plugin_update (GsPlugin *plugin,
+                  GList *apps,
+                  GCancellable *cancellable,
+                  GError **error)
 {
        GList *l;
 
@@ -906,6 +906,7 @@ gs_plugin_fwupd_install (GsPlugin *plugin,
                         GError **error)
 {
        const gchar *install_method;
+       const gchar *device_id;
        const gchar *filename;
        gboolean offline = FALSE;
 
@@ -923,6 +924,11 @@ gs_plugin_fwupd_install (GsPlugin *plugin,
                return FALSE;
        }
 
+       /* limit to single device? */
+       device_id = gs_app_get_metadata_item (app, "fwupd::DeviceID");
+       if (device_id == NULL)
+               device_id = FWUPD_DEVICE_ID_ANY;
+
        /* only offline supported */
        install_method = gs_app_get_metadata_item (app, "fwupd::InstallMethod");
        if (g_strcmp0 (install_method, "offline") == 0)
@@ -977,12 +983,12 @@ gs_plugin_fwupd_unlock (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_app_update:
+ * gs_plugin_update_app:
  *
- * This is only called when updating device firmware live.
+ * Called when a user clicks [Update] in the updates panel
  */
 gboolean
-gs_plugin_app_update (GsPlugin *plugin,
+gs_plugin_update_app (GsPlugin *plugin,
                      GsApp *app,
                      GCancellable *cancellable,
                      GError **error)
diff --git a/src/plugins/gs-plugin-limba.c b/src/plugins/gs-plugin-limba.c
index 997bb8c..7e0729a 100644
--- a/src/plugins/gs-plugin-limba.c
+++ b/src/plugins/gs-plugin-limba.c
@@ -388,12 +388,12 @@ gs_plugin_add_updates (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_app_update:
+ * gs_plugin_update_app:
  *
  * Used only for online-updates.
  */
 gboolean
-gs_plugin_app_update (GsPlugin *plugin,
+gs_plugin_update_app (GsPlugin *plugin,
                      GsApp *app,
                      GCancellable *cancellable,
                      GError **error)
diff --git a/src/plugins/gs-plugin-systemd-updates.c b/src/plugins/gs-plugin-systemd-updates.c
index e433ca2..eb1b4ec 100644
--- a/src/plugins/gs-plugin-systemd-updates.c
+++ b/src/plugins/gs-plugin-systemd-updates.c
@@ -140,13 +140,13 @@ gs_plugin_add_updates (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_offline_update:
+ * gs_plugin_update:
  */
 gboolean
-gs_plugin_offline_update (GsPlugin *plugin,
-                          GList *apps,
-                          GCancellable *cancellable,
-                          GError **error)
+gs_plugin_update (GsPlugin *plugin,
+                 GList *apps,
+                 GCancellable *cancellable,
+                 GError **error)
 {
        GList *l;
 
@@ -164,13 +164,13 @@ gs_plugin_offline_update (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_offline_update_cancel:
+ * gs_plugin_update_cancel:
  */
 gboolean
-gs_plugin_offline_update_cancel (GsPlugin *plugin,
-                                GsApp *app,
-                                GCancellable *cancellable,
-                                GError **error)
+gs_plugin_update_cancel (GsPlugin *plugin,
+                        GsApp *app,
+                        GCancellable *cancellable,
+                        GError **error)
 {
        /* only process this app if was created by this plugin */
        if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
diff --git a/src/plugins/gs-plugin-xdg-app.c b/src/plugins/gs-plugin-xdg-app.c
index ddc9ead..a937023 100644
--- a/src/plugins/gs-plugin-xdg-app.c
+++ b/src/plugins/gs-plugin-xdg-app.c
@@ -1327,12 +1327,10 @@ gs_plugin_app_install (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_app_update:
- *
- * This is only called when updating live.
+ * gs_plugin_update_app:
  */
 gboolean
-gs_plugin_app_update (GsPlugin *plugin,
+gs_plugin_update_app (GsPlugin *plugin,
                      GsApp *app,
                      GCancellable *cancellable,
                      GError **error)


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