[gnome-software/mwleeds/fix-deprecated-install] WIP: flatpak: Migrate flatpakref handling to FlatpakTransaction
- From: Phaedrus Leeds <mwleeds src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/mwleeds/fix-deprecated-install] WIP: flatpak: Migrate flatpakref handling to FlatpakTransaction
- Date: Mon, 11 Oct 2021 22:39:42 +0000 (UTC)
commit e078256e1864a479b708b77a96e65e4977dc2907
Author: Phaedrus Leeds <mwleeds protonmail com>
Date: Mon Oct 11 12:30:02 2021 -0700
WIP: 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 | 148 +++++++++++++++++++++++++++++++++++++------
1 file changed, 130 insertions(+), 18 deletions(-)
---
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index 88bb69a72..fd3ea8521 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -3438,6 +3438,33 @@ gs_flatpak_file_to_app_bundle (GsFlatpak *self,
return g_steal_pointer (&app);
}
+static gboolean
+_txn_abort_on_ready (FlatpakTransaction *transaction)
+{
+ return FALSE;
+}
+
+static gboolean
+_txn_add_new_remote (FlatpakTransaction *transaction,
+ FlatpakTransactionRemoteReason reason,
+ const char *from_id,
+ const char *remote_name,
+ const char *url)
+{
+ return TRUE;
+}
+
+static int
+_txn_choose_remote_for_ref (FlatpakTransaction *transaction,
+ const char *for_ref,
+ const char *runtime_ref,
+ const char * const *remotes)
+{
+ /* This transaction is just for displaying the app not installing it so
+ * this choice shouldn't matter */
+ return 0;
+}
+
GsApp *
gs_flatpak_file_to_app_ref (GsFlatpak *self,
GFile *file,
@@ -3447,9 +3474,13 @@ 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(FlatpakRemoteRef) xref = NULL;
+ g_autoptr(FlatpakTransaction) transaction = NULL;
+ g_autoptr(FlatpakRef) parsed_ref = NULL;
+ g_autoptr(FlatpakRemoteRef) remote_ref = NULL;
g_autoptr(FlatpakRemote) xremote = NULL;
g_autoptr(GBytes) ref_file_data = NULL;
g_autoptr(GError) error_local = NULL;
@@ -3464,6 +3495,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 +3531,118 @@ 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 && *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;
+ }
+ flatpak_transaction_set_no_interaction (transaction, TRUE);
+ g_signal_connect (transaction, "ready", G_CALLBACK (_txn_abort_on_ready), NULL);
+ g_signal_connect (transaction, "add-new-remote", G_CALLBACK (_txn_add_new_remote), NULL);
+ g_signal_connect (transaction, "choose-remote-for-ref", G_CALLBACK (_txn_choose_remote_for_ref),
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 +3666,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 +3683,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]