[gnome-software/630-flatpak-updates-are-stuck-in-installing-state-when-flatpak-update-was-already-done-outside: 103/103] flatpak: Refresh UI after changes made outside of Software




commit ba7df21bf37b630edcfa47f1b84c273b5206c006
Author: Milan Crha <mcrha redhat com>
Date:   Mon Mar 22 11:44:53 2021 +0100

    flatpak: Refresh UI after changes made outside of Software
    
    When the flatpak installation monitor claims it changed in the background,
    the memory plugin cache of the GsApp should be discarded and the information
    about installed/to-be-updated applications refreshed as well. The UI should
    be reloaded, to reflect the actual state, instead of showing stale data, aka
    the GsApp, which had been in the cache.
    
    Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/630

 plugins/flatpak/gs-flatpak-transaction.c | 11 +++++--
 plugins/flatpak/gs-flatpak.c             |  7 +++--
 plugins/flatpak/gs-self-test.c           | 50 ++++++++++++++++++++++++--------
 src/gs-details-page.c                    | 20 ++++++++++++-
 4 files changed, 70 insertions(+), 18 deletions(-)
---
diff --git a/plugins/flatpak/gs-flatpak-transaction.c b/plugins/flatpak/gs-flatpak-transaction.c
index 28dd912b5..08baef74b 100644
--- a/plugins/flatpak/gs-flatpak-transaction.c
+++ b/plugins/flatpak/gs-flatpak-transaction.c
@@ -175,9 +175,13 @@ _transaction_ready (FlatpakTransaction *transaction)
                        _transaction_operation_set_app (op, app);
                        /* if we're updating a component, then mark all the apps
                         * involved to ensure updating the button state */
-                       if (flatpak_transaction_operation_get_operation_type (op) ==
-                                       FLATPAK_TRANSACTION_OPERATION_UPDATE)
+                       if (flatpak_transaction_operation_get_operation_type (op) == 
FLATPAK_TRANSACTION_OPERATION_UPDATE) {
+                               if (gs_app_get_state (app) == GS_APP_STATE_UNKNOWN ||
+                                   gs_app_get_state (app) == GS_APP_STATE_INSTALLED)
+                                       gs_app_set_state (app, GS_APP_STATE_UPDATABLE_LIVE);
+
                                gs_app_set_state (app, GS_APP_STATE_INSTALLING);
+                       }
                }
 
 #if FLATPAK_CHECK_VERSION(1, 7, 3)
@@ -516,7 +520,8 @@ _transaction_new_operation (FlatpakTransaction *transaction,
                gs_app_set_state (app, GS_APP_STATE_INSTALLING);
                break;
        case FLATPAK_TRANSACTION_OPERATION_UPDATE:
-               if (gs_app_get_state (app) == GS_APP_STATE_UNKNOWN)
+               if (gs_app_get_state (app) == GS_APP_STATE_UNKNOWN ||
+                   gs_app_get_state (app) == GS_APP_STATE_INSTALLED)
                        gs_app_set_state (app, GS_APP_STATE_UPDATABLE_LIVE);
                gs_app_set_state (app, GS_APP_STATE_INSTALLING);
                break;
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index 3ab980426..5b748c778 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -410,12 +410,15 @@ gs_plugin_flatpak_changed_cb (GFileMonitor *monitor,
        /* drop the installed refs cache */
        locker = g_mutex_locker_new (&self->installed_refs_mutex);
        g_clear_pointer (&self->installed_refs, g_ptr_array_unref);
-
        g_clear_pointer (&locker, g_mutex_locker_free);
 
        /* drop the remote title cache */
        locker = g_mutex_locker_new (&self->remote_title_mutex);
        g_hash_table_remove_all (self->remote_title);
+       g_clear_pointer (&locker, g_mutex_locker_free);
+
+       gs_plugin_cache_invalidate (self->plugin);
+       gs_plugin_reload (self->plugin);
 }
 
 static gboolean
@@ -1926,7 +1929,6 @@ gs_flatpak_refine_app_state_unlocked (GsFlatpak *self,
        }
 
        installed_refs = g_ptr_array_ref (self->installed_refs);
-       g_mutex_unlock (&self->installed_refs_mutex);
 
        for (guint i = 0; i < installed_refs->len; i++) {
                FlatpakInstalledRef *ref_tmp = g_ptr_array_index (installed_refs, i);
@@ -1942,6 +1944,7 @@ gs_flatpak_refine_app_state_unlocked (GsFlatpak *self,
                        break;
                }
        }
+       g_mutex_unlock (&self->installed_refs_mutex);
        if (ref != NULL) {
                g_debug ("marking %s as installed with flatpak",
                         gs_app_get_unique_id (app));
diff --git a/plugins/flatpak/gs-self-test.c b/plugins/flatpak/gs-self-test.c
index 3abe743ea..e17eaf385 100644
--- a/plugins/flatpak/gs-self-test.c
+++ b/plugins/flatpak/gs-self-test.c
@@ -1340,7 +1340,6 @@ gs_plugins_flatpak_app_update_func (GsPluginLoader *plugin_loader)
        GsApp *app;
        GsApp *app_tmp;
        GsApp *runtime;
-       GsApp *old_runtime;
        gboolean got_progress_installing = FALSE;
        gboolean ret;
        guint notify_progress_id;
@@ -1354,6 +1353,7 @@ gs_plugins_flatpak_app_update_func (GsPluginLoader *plugin_loader)
        g_autofree gchar *repodir2_fn = NULL;
        g_autoptr(GError) error = NULL;
        g_autoptr(GsApp) app_source = NULL;
+       g_autoptr(GsApp) old_runtime = NULL;
        g_autoptr(GsAppList) list = NULL;
        g_autoptr(GsAppList) list_updates = NULL;
        g_autoptr(GsPluginJob) plugin_job = NULL;
@@ -1470,16 +1470,22 @@ gs_plugins_flatpak_app_update_func (GsPluginLoader *plugin_loader)
        g_assert_no_error (error);
        g_assert_true (list_updates != NULL);
 
-       /* make sure there are two entries */
+       /* make sure there is one entry */
        g_assert_cmpint (gs_app_list_length (list_updates), ==, 1);
        for (guint i = 0; i < gs_app_list_length (list_updates); i++) {
                app_tmp = gs_app_list_index (list_updates, i);
                g_debug ("got update %s", gs_app_get_unique_id (app_tmp));
        }
 
-       /* check they are the same GObject */
-       app_tmp = gs_app_list_lookup (list_updates, "*/flatpak/test/org.test.Chiron/*");
-       g_assert_true (app_tmp == app);
+       /* check that the runtime is not the update's one */
+       old_runtime = gs_app_get_runtime (app);
+       g_assert_true (old_runtime != NULL);
+       g_object_ref (old_runtime);
+       g_assert_cmpstr (gs_app_get_branch (old_runtime), !=, "new_master");
+
+       /* use the returned app, which can be a different object instance from previously */
+       app = gs_app_list_lookup (list_updates, "*/flatpak/test/org.test.Chiron/*");
+       g_assert_nonnull (app);
        g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE_LIVE);
        g_assert_cmpstr (gs_app_get_update_details (app), ==, "Version 1.2.4:\nThis is best.\n\nVersion 
1.2.3:\nThis is better.");
        g_assert_cmpstr (gs_app_get_update_version (app), ==, "1.2.4");
@@ -1502,11 +1508,6 @@ gs_plugins_flatpak_app_update_func (GsPluginLoader *plugin_loader)
                                  G_CALLBACK (update_app_progress_notify_cb),
                                  &progress_cnt);
 
-       /* check that the runtime is not the update's one */
-       old_runtime = gs_app_get_runtime (app);
-       g_assert_true (old_runtime != NULL);
-       g_assert_cmpstr (gs_app_get_branch (old_runtime), !=, "new_master");
-
        /* use a mainloop so we get the events in the default context */
        g_object_unref (plugin_job);
        plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_UPDATE,
@@ -1734,8 +1735,7 @@ gs_plugins_flatpak_runtime_extension_func (GsPluginLoader *plugin_loader)
        g_assert_null (app_tmp);
 
        /* check that the app has an update (it's affected by the extension's update) */
-       app_tmp = gs_app_list_lookup (list_updates, "*/flatpak/test/org.test.Chiron/*");
-       g_assert_true (app_tmp == app);
+       app = gs_app_list_lookup (list_updates, "*/flatpak/test/org.test.Chiron/*");
        g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE_LIVE);
 
        /* care about signals */
@@ -1779,6 +1779,12 @@ gs_plugins_flatpak_runtime_extension_func (GsPluginLoader *plugin_loader)
        g_assert_true (got_progress_installing);
        g_assert_cmpint (pending_app_changed_cnt, ==, 0);
 
+       /* The install refreshes GsApp-s cache, thus re-get the extension */
+       g_clear_object (&extension);
+       extension = gs_plugin_loader_app_create (plugin_loader,
+                       "user/flatpak/*/org.test.Chiron.Extension/master");
+       g_assert_nonnull (extension);
+
        /* check the extension's state after the update */
        g_assert_cmpint (gs_app_get_state (extension), ==, GS_APP_STATE_INSTALLED);
 
@@ -1788,8 +1794,28 @@ gs_plugins_flatpak_runtime_extension_func (GsPluginLoader *plugin_loader)
        g_signal_handler_disconnect (app, notify_state_id);
        g_signal_handler_disconnect (app, notify_progress_id);
 
+       g_clear_object (&list);
+       /* Reload the 'app', as it could change due to repo change */
+       g_object_unref (plugin_job);
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SEARCH,
+                                        "search", "Bingo",
+                                        "refine-flags", GS_PLUGIN_REFINE_FLAGS_DEFAULT |
+                                                        GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME,
+                                        NULL);
+       list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
+       gs_test_flush_main_context ();
+       g_assert_no_error (error);
+       g_assert_nonnull (list);
+
+       /* make sure there is one entry, the flatpak app */
+       g_assert_cmpint (gs_app_list_length (list), ==, 1);
+       app = gs_app_list_index (list, 0);
+       g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
+       g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
+
        /* getting the runtime for later removal */
        runtime = gs_app_get_runtime (app);
+       g_assert_nonnull (runtime);
 
        /* remove the app */
        g_object_unref (plugin_job);
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 420d23681..8723987b7 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -34,6 +34,7 @@
 #define SHOW_NR_REVIEWS_INITIAL                4
 
 static void gs_details_page_refresh_all (GsDetailsPage *self);
+static void gs_details_page_refresh_buttons (GsDetailsPage *self);
 
 typedef enum {
        GS_DETAILS_PAGE_STATE_LOADING,
@@ -797,6 +798,7 @@ gs_details_page_get_alternates_cb (GObject *source_object,
        GtkWidget *origin_button_label;
        GtkWidget *origin_popover_list_box;
        g_autofree gchar *origin_ui = NULL;
+       gboolean instance_changed = FALSE;
 
        origin_box = GTK_WIDGET (gtk_builder_get_object (self->builder, "origin_box"));
        origin_button_label = GTK_WIDGET (gtk_builder_get_object (self->builder, "origin_button_label"));
@@ -835,8 +837,20 @@ gs_details_page_get_alternates_cb (GObject *source_object,
                GsApp *app = gs_app_list_index (list, i);
                GtkWidget *row = gs_origin_popover_row_new (app);
                gtk_widget_show (row);
-               if (app == self->app)
+               if (app == self->app || (
+                   gs_app_get_bundle_kind (app) == gs_app_get_bundle_kind (self->app) &&
+                   gs_app_get_scope (app) == gs_app_get_scope (self->app) &&
+                   g_strcmp0 (gs_app_get_origin (app), gs_app_get_origin (self->app)) == 0 &&
+                   g_strcmp0 (gs_app_get_branch (app), gs_app_get_branch (self->app)) == 0 &&
+                   g_strcmp0 (gs_app_get_version (app), gs_app_get_version (self->app)) == 0)) {
+                       /* This can happen on reload of the page */
+                       if (app != self->app) {
+                               g_clear_object (&self->app);
+                               self->app = g_object_ref (app);
+                               instance_changed = TRUE;
+                       }
                        gs_origin_popover_row_set_selected (GS_ORIGIN_POPOVER_ROW (row), TRUE);
+               }
                gs_origin_popover_row_set_size_group (GS_ORIGIN_POPOVER_ROW (row),
                                                      self->size_group_origin_popover);
                gtk_container_add (GTK_CONTAINER (origin_popover_list_box), row);
@@ -849,6 +863,10 @@ gs_details_page_get_alternates_cb (GObject *source_object,
                gtk_label_set_text (GTK_LABEL (origin_button_label), "");
 
        gtk_widget_show (origin_box);
+
+       /* The other parts of the app are the same, only the state/buttons could change */
+       if (instance_changed)
+               gs_details_page_refresh_buttons (self);
 }
 
 static gboolean


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