summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <pwithnall@endlessos.org>2023-03-02 20:10:48 +0000
committerAlexander Larsson <alexander.larsson@gmail.com>2023-03-30 14:54:18 +0200
commita0f80cb32abd21dd3bc68224385dda0ed2411bfa (patch)
tree01ea6f9fca67327f12b6fd478a962b3d0900feec
parent0fff6ac1719449750b6c54dfae89ebd4395818b8 (diff)
downloadflatpak-a0f80cb32abd21dd3bc68224385dda0ed2411bfa.tar.gz
transaction: Add new flatpak_transaction_add_rebase_and_uninstall() API
This mostly replaces `flatpak_transaction_add_rebase()`. It’s necessary because the uninstall op for an eol-rebased app needs to be linked to the install/update op for the rebased app, otherwise one op can proceed after the other has failed (or they can be run in the wrong order) and result in the old app being uninstalled but the new one not installed. The following commit will port the internal flatpak `FlatpakTransaction` subclasses to use it. Other consumers of `FlatpakTransaction` (such as gnome-software) will have to be ported as well. Signed-off-by: Philip Withnall <pwithnall@endlessos.org> Fixes: #3991
-rw-r--r--common/flatpak-installation.c5
-rw-r--r--common/flatpak-transaction.c120
-rw-r--r--common/flatpak-transaction.h8
-rw-r--r--doc/reference/flatpak-sections.txt1
4 files changed, 127 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,
diff --git a/doc/reference/flatpak-sections.txt b/doc/reference/flatpak-sections.txt
index fb390a6c..81cfa7c4 100644
--- a/doc/reference/flatpak-sections.txt
+++ b/doc/reference/flatpak-sections.txt
@@ -265,6 +265,7 @@ flatpak_transaction_add_install
flatpak_transaction_add_install_bundle
flatpak_transaction_add_install_flatpakref
flatpak_transaction_add_rebase
+flatpak_transaction_add_rebase_and_uninstall
flatpak_transaction_add_update
flatpak_transaction_add_uninstall
flatpak_transaction_add_default_dependency_sources