summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/flatpak-installation.c5
-rw-r--r--common/flatpak-transaction.c120
-rw-r--r--common/flatpak-transaction.h8
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,