diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/flatpak-installation.c | 5 | ||||
-rw-r--r-- | common/flatpak-transaction.c | 120 | ||||
-rw-r--r-- | common/flatpak-transaction.h | 8 |
3 files changed, 126 insertions, 7 deletions
diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index 7dd95a21..2c8ca723 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -987,9 +987,8 @@ end_of_lifed_with_rebase (FlatpakTransaction *transaction, if (rebased_to_ref == NULL || remote == NULL) return FALSE; - /* No need to call flatpak_transaction_add_uninstall() and - * flatpak_transaction_add_rebase() here since we only care about what needs - * an update + /* No need to call flatpak_transaction_add_rebase_and_uninstall() here since + * we only care about what needs an update */ g_ptr_array_add (*eol_rebase_refs, g_strdup (ref)); return TRUE; diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c index 0df4d310..02bbca2f 100644 --- a/common/flatpak-transaction.c +++ b/common/flatpak-transaction.c @@ -128,7 +128,7 @@ struct _FlatpakTransactionOperation int run_after_prio; /* Higher => run later (when it becomes runnable). Used to run related ops (runtime extensions) before deps (apps using the runtime) */ GList *run_before_ops; gboolean run_last; /* Run this after all the other apps that are not run_last */ - FlatpakTransactionOperation *fail_if_op_fails; /* main app/runtime for related extensions, runtime for apps */ + FlatpakTransactionOperation *fail_if_op_fails; /* main app/runtime for related extensions, runtime for apps, install/update for uninstalls of eol-rebase apps */ /* main app/runtime for related extensions, app for runtimes; could be multiple * related-to-ops if this op is for a runtime which is needed by multiple apps * in the transaction: */ @@ -1275,9 +1275,8 @@ flatpak_transaction_class_init (FlatpakTransactionClass *klass) * ref. * * If the caller wants to install the rebased ref, they should call - * flatpak_transaction_add_uninstall() on @ref, - * flatpak_transaction_add_rebase() on @rebased_to_ref, and return %TRUE. - * Otherwise %FALSE may be returned. + * flatpak_transaction_add_rebase_and_uninstall() on @rebased_to_ref and @ref, + * and return %TRUE. Otherwise %FALSE may be returned. * * Returns: %TRUE if the operation on this end-of-lifed ref should * be skipped (e.g. because the rebased ref has been added to the @@ -2817,6 +2816,10 @@ flatpak_transaction_add_install (FlatpakTransaction *self, * treat @ref as the result of following an eol-rebase, and data migration from * the refs in @previous_ids will be set up. * + * If you want to rebase the ref and uninstall the old version of it, consider + * using flatpak_transaction_add_rebase_and_uninstall() instead. It will add + * appropriate dependencies between the rebase and uninstall operations. + * * See flatpak_transaction_add_install() for a description of @remote. * * Returns: %TRUE on success; %FALSE with @error set on failure. @@ -2855,6 +2858,115 @@ flatpak_transaction_add_rebase (FlatpakTransaction *self, } /** + * flatpak_transaction_add_rebase_and_uninstall: + * @self: a #FlatpakTransaction + * @remote: the name of the remote + * @new_ref: the ref to rebase to + * @old_ref: the ref to uninstall + * @subpaths: (nullable): the subpaths to include, or %NULL to install the complete ref + * @previous_ids: (nullable) (array zero-terminated=1): Previous ids to add to the + * given ref. These should simply be the ids, not the full ref names (e.g. org.foo.Bar, + * not org.foo.Bar/x86_64/master). + * @error: return location for a #GError + * + * Adds updating the @previous_ids of the given @new_ref to this transaction, + * via either installing the @new_ref if it was not already present or updating + * it. This will treat @new_ref as the result of following an eol-rebase, and + * data migration from the refs in @previous_ids will be set up. + * + * Also adds an operation to uninstall @old_ref to this transaction. This + * operation will only be run if the operation to install/update @new_ref + * succeeds. + * + * If @old_ref is not already installed (which can happen if requesting to + * install an EOLed app, rather than update one which is already installed), the + * uninstall operation will silently not be added, and this function will behave + * similarly to flatpak_transaction_add_rebase(). + * + * See flatpak_transaction_add_install() for a description of @remote. + * + * Returns: %TRUE on success; %FALSE with @error set on failure. + * Since: 1.15.4 + */ +gboolean +flatpak_transaction_add_rebase_and_uninstall (FlatpakTransaction *self, + const char *remote, + const char *new_ref, + const char *old_ref, + const char **subpaths, + const char **previous_ids, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + const char *all_paths[] = { NULL }; + g_autoptr(FlatpakDecomposed) old_decomposed = NULL; + g_autoptr(FlatpakDecomposed) new_decomposed = NULL; + g_autofree char *installed_origin = NULL; + g_autoptr(GError) local_error = NULL; + FlatpakTransactionOperation *rebase_op = NULL, *uninstall_op = NULL; + + g_return_val_if_fail (new_ref != NULL, FALSE); + g_return_val_if_fail (old_ref != NULL, FALSE); + g_return_val_if_fail (remote != NULL, FALSE); + /* flatpak_transaction_add_rebase_and_uninstall() without previous_ids doesn't make sense */ + g_return_val_if_fail (previous_ids != NULL, FALSE); + + new_decomposed = flatpak_decomposed_new_from_ref (new_ref, error); + if (new_decomposed == NULL) + return FALSE; + + old_decomposed = flatpak_decomposed_new_from_ref (old_ref, error); + if (old_decomposed == NULL) + return FALSE; + + /* If we install with no special args pull all subpaths */ + if (subpaths == NULL) + subpaths = all_paths; + + if (dir_ref_is_installed (priv->dir, new_decomposed, &installed_origin, NULL)) + remote = installed_origin; + + /* Add the install/update and uninstall ops. */ + if (!flatpak_transaction_add_ref (self, remote, new_decomposed, subpaths, + previous_ids, NULL, + FLATPAK_TRANSACTION_OPERATION_INSTALL_OR_UPDATE, + NULL, NULL, FALSE, &rebase_op, error)) + return FALSE; + + if (!flatpak_transaction_add_ref (self, NULL, old_decomposed, NULL, NULL, NULL, + FLATPAK_TRANSACTION_OPERATION_UNINSTALL, + NULL, NULL, FALSE, &uninstall_op, &local_error)) + { + /* If the user is trying to install an eol-rebased app from scratch, the + * @old_ref can’t be uninstalled because it’s not installed already. + * Silently ignore that. */ + if (g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED)) + { + g_clear_error (&local_error); + } + else + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + + /* Link the ops together so that the install/update is done first, and if + * that fails then the uninstall is skipped. @uninstall_op might be %NULL even + * if the flatpak_transaction_add_ref() call succeeded above, as this might be + * a no-deploy transaction. */ + if (uninstall_op != NULL) + { + uninstall_op->non_fatal = TRUE; + uninstall_op->fail_if_op_fails = rebase_op; + flatpak_transaction_operation_add_related_to_op (uninstall_op, rebase_op); + run_operation_before (rebase_op, uninstall_op, 1); + } + + return TRUE; +} + +/** * flatpak_transaction_add_install_bundle: * @self: a #FlatpakTransaction * @file: a #GFile that is an flatpak bundle diff --git a/common/flatpak-transaction.h b/common/flatpak-transaction.h index c5832dc8..0b8f2de8 100644 --- a/common/flatpak-transaction.h +++ b/common/flatpak-transaction.h @@ -313,6 +313,14 @@ gboolean flatpak_transaction_add_rebase (FlatpakTransaction *self, const char **previous_ids, GError **error); FLATPAK_EXTERN +gboolean flatpak_transaction_add_rebase_and_uninstall (FlatpakTransaction *self, + const char *remote, + const char *new_ref, + const char *old_ref, + const char **subpaths, + const char **previous_ids, + GError **error); +FLATPAK_EXTERN gboolean flatpak_transaction_add_install_bundle (FlatpakTransaction *self, GFile *file, GBytes *gpg_data, |