[gnome-software/mwleeds/fix-deprecated-install] flatpak: Migrate flatpakref handling to FlatpakTransaction




commit 9a15a7e204b3c7900e29616812a45c0179191a61
Author: Phaedrus Leeds <mwleeds protonmail com>
Date:   Mon Oct 11 12:30:02 2021 -0700

    flatpak: Migrate flatpakref handling to FlatpakTransaction
    
    Currently we use flatpak_installation_install_ref_file() when parsing a
    .flatpakref file for displaying it to the user, but that function is
    deprecated in favor of flatpak_transaction_add_install_flatpakref(). So,
    migrate to the replacement function.
    
    This is unfortunately not a simple migration, mainly because while the
    deprecated function only adds the appropriate remote but doesn't install
    the thing, by default a FlatpakTransaction will execute the install
    operation unless aborted. So, abort the transaction so that we have
    enough information to display the app to the user and let them decide
    whether to install it.

 plugins/flatpak/gs-flatpak.c | 121 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 104 insertions(+), 17 deletions(-)
---
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index 88bb69a72..ec2fd5ca1 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -3438,6 +3438,12 @@ gs_flatpak_file_to_app_bundle (GsFlatpak *self,
        return g_steal_pointer (&app);
 }
 
+static gboolean
+_abort_on_txn_ready (FlatpakTransaction *transaction)
+{
+       return FALSE;
+}
+
 GsApp *
 gs_flatpak_file_to_app_ref (GsFlatpak *self,
                            GFile *file,
@@ -3447,8 +3453,11 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
        GsApp *runtime;
        const gchar *const *locales = g_get_language_names ();
        const gchar *remote_name;
+       gboolean is_runtime;
        gsize len = 0;
+       GList *txn_ops;
        g_autofree gchar *contents = NULL;
+       g_autoptr(FlatpakRef) parsed_ref = NULL;
        g_autoptr(FlatpakRemoteRef) xref = NULL;
        g_autoptr(FlatpakRemote) xremote = NULL;
        g_autoptr(GBytes) ref_file_data = NULL;
@@ -3464,6 +3473,7 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
        g_autofree gchar *ref_icon = NULL;
        g_autofree gchar *ref_title = NULL;
        g_autofree gchar *ref_name = NULL;
+       g_autofree gchar *ref_branch = NULL;
 
        /* add current locales */
        for (guint i = 0; locales[i] != NULL; i++)
@@ -3499,35 +3509,115 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
                }
        }
 
-       /* get name */
+       /* get name, branch, kind */
        ref_name = g_key_file_get_string (kf, "Flatpak Ref", "Name", error);
        if (ref_name == NULL) {
                gs_utils_error_convert_gio (error);
                return NULL;
        }
+       ref_branch = g_key_file_get_string (kf, "Flatpak Ref", "Branch", error);
+       if (ref_branch == NULL) {
+               gs_utils_error_convert_gio (error);
+               return NULL;
+       }
+       is_runtime = g_key_file_get_boolean (kf, "Flatpak Ref", "IsRuntime", error);
+       if (error != NULL) {
+               gs_utils_error_convert_gio (error);
+               return NULL;
+       }
 
-       /* install the remote, but not the app */
+       /* install the remote, but not the app by aborting the transaction at the "ready" signal */
+       transaction = flatpak_transaction_new_for_installation (self->installation, cancellable, error);
+       if (transaction == NULL) {
+               gs_flatpak_error_convert (error);
+               return NULL;
+       }
+       g_signal_connect (transaction, "ready", G_CALLBACK (_abort_on_txn_ready), NULL);
        ref_file_data = g_bytes_new (contents, len);
-       xref = flatpak_installation_install_ref_file (self->installation,
-                                                     ref_file_data,
-                                                     cancellable,
-                                                     error);
-       if (xref == NULL) {
+       if (!flatpak_transaction_add_install_flatpakref (transaction, ref_file_data, error)) {
                gs_flatpak_error_convert (error);
                return NULL;
        }
+       g_assert (!flatpak_transaction_run (transaction, cancellable, &error_local));
 
-       /* load metadata */
-       app = gs_flatpak_create_app (self, NULL /* origin */, FLATPAK_REF (xref), NULL, cancellable);
-       if (gs_app_get_state (app) == GS_APP_STATE_INSTALLED) {
-               if (gs_flatpak_app_get_ref_name (app) == NULL)
-                       gs_flatpak_set_metadata (self, app, FLATPAK_REF (xref));
-               return g_steal_pointer (&app);
+       if (!g_error_matches (error_local, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED) &&
+           !g_error_matches (error_local, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED)) {
+               g_propagate_error (error, g_steal_pointer (&error_local));
+               gs_flatpak_error_convert (error);
+               return NULL;
+       }
+
+       /* handle the already installed case */
+       if (g_error_matches (error_local, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) {
+               g_autoptr(FlatpakInstalledRef) installed_ref = NULL;
+               installed_ref = flatpak_installation_get_installed_ref (self->installation,
+                                                                       is_runtime ? FLATPAK_REF_KIND_RUNTIME 
: FLATPAK_REF_KIND_APP,
+                                                                       ref_name,
+                                                                       NULL, /* arch */
+                                                                       ref_branch,
+                                                                       cancellable,
+                                                                       error);
+               if (installed_ref == NULL) {
+                       gs_flatpak_error_convert (error);
+                       return NULL;
+               }
+               app = gs_flatpak_create_app (self, NULL /* origin */, FLATPAK_REF (installed_ref), NULL, 
cancellable);
+               if (gs_app_get_state (app) == GS_APP_STATE_INSTALLED) {
+                       if (gs_flatpak_app_get_ref_name (app) == NULL)
+                               gs_flatpak_set_metadata (self, app, FLATPAK_REF (installed_ref));
+                       return g_steal_pointer (&app);
+               } else {
+                       g_set_error (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "cannot find installed app %s", ref_name);
+                       return NULL;
+               }
        }
+
+       g_clear_error (&error_local);
+
+       /* find the operation for the flatpakref */
+       txn_ops = flatpak_transaction_get_operations (transaction);
+       for (GList *l = txn_ops; l != NULL; l = l->next) {
+               FlatpakTransactionOperation *op = l->data;
+               const char *op_ref = flatpak_transaction_operation_get_ref (op);
+               parsed_ref = flatpak_ref_parse (op_ref, error);
+               if (parsed_ref == NULL) {
+                       gs_flatpak_error_convert (error);
+                       return NULL;
+               }
+               if (g_strcmp0 (flatpak_ref_get_name (parsed_ref), ref_name) != 0) {
+                       g_clear_object (&parsed_ref);
+               } else {
+                       remote_name = flatpak_transaction_operation_get_remote (op);
+                       g_debug ("auto-created remote name: %s", remote_name);
+                       break;
+               }
+       }
+       g_assert (parsed_ref != NULL);
+       g_list_free_full (g_steal_pointer (&txn_ops), g_object_unref);
+
+       /* fetch remote ref */
+       remote_ref = flatpak_installation_fetch_remote_ref_sync (self->installation,
+                                                          remote_name,
+                                                          flatpak_ref_get_kind (parsed_ref),
+                                                          flatpak_ref_get_name (parsed_ref),
+                                                          flatpak_ref_get_arch (parsed_ref),
+                                                          flatpak_ref_get_branch (parsed_ref),
+                                                          cancellable,
+                                                          error);
+       if (remote_ref == NULL) {
+               gs_flatpak_error_convert (error);
+               return NULL;
+       }
+
+       /* load metadata */
+       app = gs_flatpak_create_app (self, remote_name, FLATPAK_REF (remote_ref), NULL, cancellable);
        gs_app_add_quirk (app, GS_APP_QUIRK_HAS_SOURCE);
        gs_flatpak_app_set_file_kind (app, GS_FLATPAK_APP_FILE_KIND_REF);
        gs_app_set_state (app, GS_APP_STATE_AVAILABLE_LOCAL);
-       gs_flatpak_set_metadata (self, app, FLATPAK_REF (xref));
+       gs_flatpak_set_metadata (self, app, FLATPAK_REF (remote_ref));
 
        /* use the data from the flatpakref file as a fallback */
        ref_title = g_key_file_get_string (kf, "Flatpak Ref", "Title", NULL);
@@ -3551,8 +3641,6 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
        }
 
        /* set the origin data */
-       remote_name = flatpak_remote_ref_get_remote_name (xref);
-       g_debug ("auto-created remote name: %s", remote_name);
        xremote = flatpak_installation_get_remote_by_name (self->installation,
                                                           remote_name,
                                                           cancellable,
@@ -3570,7 +3658,6 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
                             flatpak_remote_get_name (xremote));
                return NULL;
        }
-       gs_flatpak_set_app_origin (self, app, remote_name, xremote, cancellable);
        gs_app_set_origin_hostname (app, origin_url);
 
        /* get the new appstream data (nonfatal for failure) */


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