Commit dd100c88 authored by Matthew Leeds's avatar Matthew Leeds Committed by Richard Hughes

flatpak: Set app to installed when a related thing is updated

When an app's locale extension is updated but the app is not, we put
progress updates on the app so they are user visible. However since
_transaction_operation_done() is only ever called for the locale, the
app never gets set to AS_APP_STATE_INSTALLED and instead gets frozen in
the "Preparing..." state when gs_plugin_loader_helper_free() sets the
progress to GS_APP_PROGRESS_UNKNOWN on it.

So set the app to installed when one of its related refs is updated, if
the app itself is being skipped.

Relatedly, update the unit test which tests extension updates so it
succeeds with Flatpak older than 1.7.3, because the changes in this
patch aren't active for those versions.
parent b6f7d5d6
......@@ -523,13 +523,83 @@ _transaction_new_operation (FlatpakTransaction *transaction,
}
}
#if FLATPAK_CHECK_VERSION(1, 7, 3)
static gboolean
later_op_also_related (GList *ops,
FlatpakTransactionOperation *current_op,
FlatpakTransactionOperation *related_to_current_op)
{
/* Here we're determining if anything in @ops which comes after
* @current_op is related to @related_to_current_op and not skipped
* (but all @ops are not skipped so no need to check explicitly)
*/
gboolean found_later_op = FALSE, seen_current_op = FALSE;
for (GList *l = ops; l != NULL; l = l->next) {
FlatpakTransactionOperation *op = l->data;
GPtrArray *related_to_ops;
if (current_op == op) {
seen_current_op = TRUE;
continue;
}
if (!seen_current_op)
continue;
related_to_ops = flatpak_transaction_operation_get_related_to_ops (op);
for (gsize i = 0; related_to_ops != NULL && i < related_to_ops->len; i++) {
FlatpakTransactionOperation *related_to_op = g_ptr_array_index (related_to_ops, i);
if (related_to_op == related_to_current_op) {
g_assert (flatpak_transaction_operation_get_is_skipped (related_to_op));
found_later_op = TRUE;
}
}
}
return found_later_op;
}
static void
set_skipped_related_apps_to_installed (GsFlatpakTransaction *self,
FlatpakTransaction *transaction,
FlatpakTransactionOperation *operation)
{
/* It's possible the thing being updated/installed, @operation, is a
* related ref (e.g. extension or runtime) of an app which itself doesn't
* need an update and therefore won't have _transaction_operation_done()
* called for it directly. So we have to set the main app to installed
* here.
*/
g_autolist(GObject) ops = flatpak_transaction_get_operations (transaction);
GPtrArray *related_to_ops = flatpak_transaction_operation_get_related_to_ops (operation);
for (gsize i = 0; related_to_ops != NULL && i < related_to_ops->len; i++) {
FlatpakTransactionOperation *related_to_op = g_ptr_array_index (related_to_ops, i);
if (flatpak_transaction_operation_get_is_skipped (related_to_op)) {
const gchar *ref;
g_autoptr(GsApp) related_to_app = NULL;
/* Check that no later op is also related to related_to_op, in
* which case we want to let that operation finish before setting
* the main app to installed.
*/
if (later_op_also_related (ops, operation, related_to_op))
continue;
ref = flatpak_transaction_operation_get_ref (related_to_op);
related_to_app = _ref_to_app (self, ref);
if (related_to_app != NULL)
gs_app_set_state (related_to_app, AS_APP_STATE_INSTALLED);
}
}
}
#endif /* flatpak 1.7.3 */
static void
_transaction_operation_done (FlatpakTransaction *transaction,
FlatpakTransactionOperation *operation,
const gchar *commit,
FlatpakTransactionResult details)
{
#if !FLATPAK_CHECK_VERSION(1,5,1)
#if !FLATPAK_CHECK_VERSION(1,5,1) || FLATPAK_CHECK_VERSION(1,7,3)
GsFlatpakTransaction *self = GS_FLATPAK_TRANSACTION (transaction);
#endif
/* invalidate */
......@@ -560,6 +630,10 @@ _transaction_operation_done (FlatpakTransaction *transaction,
gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE);
else
gs_app_set_state (app, AS_APP_STATE_INSTALLED);
#if FLATPAK_CHECK_VERSION(1,7,3)
set_skipped_related_apps_to_installed (self, transaction, operation);
#endif
break;
case FLATPAK_TRANSACTION_OPERATION_UNINSTALL:
/* we don't actually know if this app is re-installable */
......
......@@ -933,6 +933,10 @@ gs_plugin_flatpak_update (GsPlugin *plugin,
gs_flatpak_error_convert (error);
return FALSE;
}
/* add to the transaction cache for quick look up -- other unrelated
* refs will be matched using gs_plugin_flatpak_find_app_by_ref() */
gs_flatpak_transaction_add_app (transaction, app);
}
/* run transaction */
......
......@@ -1762,7 +1762,14 @@ gs_plugins_flatpak_runtime_extension_func (GsPluginLoader *plugin_loader)
loop);
g_main_loop_run (loop);
gs_test_flush_main_context ();
#if !FLATPAK_CHECK_VERSION(1,7,3)
/* Older flatpak versions don't have the API we use to propagate state
* between extension and app
*/
gs_app_set_state (app, AS_APP_STATE_INSTALLED);
#else
g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
#endif
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_true (got_progress_installing);
g_assert_cmpint (pending_app_changed_cnt, ==, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment