[gnome-software] Add the concept of UpdateAll into the plugin loader
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Add the concept of UpdateAll into the plugin loader
- Date: Fri, 8 Apr 2016 13:59:44 +0000 (UTC)
commit 7c8d6a2d53437f7d1b42e6a098e9c6612831249e
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 | 104 ++++++++++++++++++++++++-------
src/gs-plugin-loader.h | 6 +-
src/gs-plugin.h | 8 +-
src/gs-shell-updates.c | 24 ++++----
src/plugins/gs-plugin-fwupd.c | 67 ++++----------------
src/plugins/gs-plugin-limba.c | 4 +-
src/plugins/gs-plugin-systemd-updates.c | 32 ++++++---
src/plugins/gs-plugin-xdg-app.c | 6 +-
9 files changed, 145 insertions(+), 120 deletions(-)
---
diff --git a/src/gs-application.c b/src/gs-application.c
index 098f6d2..95491ec 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -427,7 +427,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);
@@ -443,7 +443,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;
}
@@ -468,11 +468,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 2c0004a..7c4f3b4 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -2664,6 +2664,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);
@@ -2720,8 +2729,8 @@ 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_OFFLINE_UPDATE_CANCEL:
- state->function_name = "gs_plugin_offline_update_cancel";
+ case GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL:
+ state->function_name = "gs_plugin_update_cancel";
state->state_success = AS_APP_STATE_UNKNOWN;
state->state_failure = AS_APP_STATE_UNKNOWN;
break;
@@ -3761,21 +3770,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 */
@@ -3807,21 +3817,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;
@@ -3837,16 +3897,16 @@ gs_plugin_loader_offline_update_async (GsPluginLoader *plugin_loader,
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);
+ g_task_run_in_thread (task, gs_plugin_loader_update_thread_cb);
}
/**
- * 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 f1a2d8c..8abf10a 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -60,7 +60,7 @@ typedef enum {
GS_PLUGIN_LOADER_ACTION_UPGRADE_DOWNLOAD,
GS_PLUGIN_LOADER_ACTION_UPGRADE_TRIGGER,
GS_PLUGIN_LOADER_ACTION_LAUNCH,
- GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL,
+ GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL,
GS_PLUGIN_LOADER_ACTION_LAST
} GsPluginLoaderAction;
@@ -180,12 +180,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 18f2e9d..de0d5f6 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -173,7 +173,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);
@@ -279,7 +279,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);
@@ -295,7 +295,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);
@@ -347,7 +347,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 70fffcb..414ea14 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -911,17 +911,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)
{
@@ -929,8 +929,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;
}
@@ -956,11 +956,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);
}
static void
@@ -1021,7 +1021,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);
@@ -1037,7 +1037,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 c5dfdb2..246b5b6 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -635,56 +635,6 @@ gs_plugin_refresh (GsPlugin *plugin,
}
/**
- * gs_plugin_app_upgrade:
- */
-static gboolean
-gs_plugin_app_upgrade (GsPlugin *plugin,
- GsApp *app,
- GCancellable *cancellable,
- GError **error)
-{
- const gchar *device_id;
- const gchar *filename;
-
- filename = gs_app_get_source_id_default (app);
- device_id = gs_app_get_metadata_item (app, "fwupd::DeviceID");
- if (filename == NULL || device_id == NULL) {
- g_set_error (error,
- GS_PLUGIN_ERROR,
- GS_PLUGIN_ERROR_FAILED,
- "not enough data for fwupd %s:%s",
- filename, device_id);
- return FALSE;
- }
- gs_app_set_state (app, AS_APP_STATE_INSTALLING);
- if (!fwupd_client_install (plugin->priv->client, device_id, filename,
- FWUPD_INSTALL_FLAG_OFFLINE, cancellable, error))
- return FALSE;
- gs_app_set_state (app, AS_APP_STATE_INSTALLED);
- return TRUE;
-}
-
-/**
- * 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_fwupd_install:
*/
static gboolean
@@ -693,6 +643,7 @@ gs_plugin_fwupd_install (GsPlugin *plugin,
GCancellable *cancellable,
GError **error)
{
+ const gchar *device_id;
const gchar *filename;
FwupdInstallFlags install_flags = 0;
@@ -706,13 +657,19 @@ 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 */
if (gs_app_has_quirk (app, AS_APP_QUIRK_NEEDS_REBOOT))
install_flags |= FWUPD_INSTALL_FLAG_OFFLINE;
gs_app_set_state (app, AS_APP_STATE_INSTALLING);
- if (!fwupd_client_install (plugin->priv->client, FWUPD_DEVICE_ID_ANY,
- filename, install_flags, cancellable, error))
+ if (!fwupd_client_install (plugin->priv->client, device_id,
+ filename, install_flags,
+ cancellable, error))
return FALSE;
gs_app_set_state (app, AS_APP_STATE_INSTALLED);
return TRUE;
@@ -733,12 +690,12 @@ gs_plugin_app_install (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 449e971..e1bfabc 100644
--- a/src/plugins/gs-plugin-limba.c
+++ b/src/plugins/gs-plugin-limba.c
@@ -366,12 +366,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 fcf5725..59569c1 100644
--- a/src/plugins/gs-plugin-systemd-updates.c
+++ b/src/plugins/gs-plugin-systemd-updates.c
@@ -151,25 +151,35 @@ 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)
{
- return pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT, cancellable, error);
+ GList *l;
+
+ /* any apps to process offline */
+ for (l = apps; l != NULL; l = l->next) {
+ GsApp *app = GS_APP (l->data);
+ if (gs_app_get_state (app) == AS_APP_STATE_UPDATABLE) {
+ return pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT,
+ cancellable, error);
+ }
+ }
+ return TRUE;
}
/**
- * 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)
{
return pk_offline_cancel (NULL, error);
}
diff --git a/src/plugins/gs-plugin-xdg-app.c b/src/plugins/gs-plugin-xdg-app.c
index 3d573f1..b805125 100644
--- a/src/plugins/gs-plugin-xdg-app.c
+++ b/src/plugins/gs-plugin-xdg-app.c
@@ -1343,12 +1343,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]