From ae0de69b17cd09acca819a6bf3d3568f6436d20e Mon Sep 17 00:00:00 2001 From: Phaedrus Leeds Date: Tue, 21 Jun 2022 14:19:31 -0700 Subject: [PATCH] app: Improve checking for dependent apps in EOL messages flatpak_dir_list_app_refs_with_runtime_extension() only works when the runtime extension it is passed and the apps it returns are both installed. Sometimes a end-of-life message is printed for a runtime that is not installed but is being installed by the current transaction, or a runtime that is installed but one of the apps that needs it is being installed by the current transaction. To cover these cases, check the operations in the current transaction when building informational messages about EOL runtimes. --- app/flatpak-cli-transaction.c | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/app/flatpak-cli-transaction.c b/app/flatpak-cli-transaction.c index 24f2dafe..78a4ea4f 100644 --- a/app/flatpak-cli-transaction.c +++ b/app/flatpak-cli-transaction.c @@ -729,6 +729,49 @@ print_eol_info_message (FlatpakDir *dir, } } +static void +check_current_transaction_for_dependent_apps (GPtrArray *apps, + FlatpakTransaction *transaction, + FlatpakDecomposed *ref) +{ + g_autoptr(FlatpakTransactionOperation) ref_op = NULL; + GPtrArray *related_ops; + + ref_op = flatpak_transaction_get_operation_for_ref (transaction, NULL, flatpak_decomposed_get_ref (ref), NULL); + g_assert (ref_op != NULL); + + /* Get the related ops to find any apps that use @ref as a runtime or extension */ + related_ops = flatpak_transaction_operation_get_related_to_ops (ref_op); + if (related_ops == NULL) + return; + + for (int i = 0; i < related_ops->len; i++) + { + FlatpakTransactionOperation *related_op = g_ptr_array_index (related_ops, i); + const char *related_op_ref = flatpak_transaction_operation_get_ref (related_op); + g_autoptr(FlatpakDecomposed) related_op_decomposed = flatpak_decomposed_new_from_ref (related_op_ref, NULL); + + if (related_op_decomposed == NULL) + continue; + if (flatpak_decomposed_id_is_subref (related_op_decomposed)) + continue; + + /* Recurse in case @ref was a runtime extension. We need to check since a + * runtime can have a runtime extension in its related ops in the + * extra-data case, so if we recurse unconditionally it could be infinite + * recursion. + */ + if (flatpak_decomposed_is_runtime (related_op_decomposed)) + { + GKeyFile *metadata = flatpak_transaction_operation_get_metadata (ref_op); + if (g_key_file_has_group (metadata, FLATPAK_METADATA_GROUP_EXTENSION_OF)) + check_current_transaction_for_dependent_apps (apps, transaction, related_op_decomposed); + } + else if (!g_ptr_array_find_with_equal_func (apps, related_op_decomposed, (GEqualFunc)flatpak_decomposed_equal, NULL)) + g_ptr_array_add (apps, g_steal_pointer (&related_op_decomposed)); + } +} + static GPtrArray * find_reverse_dep_apps (FlatpakTransaction *transaction, FlatpakDir *dir, @@ -767,6 +810,14 @@ find_reverse_dep_apps (FlatpakTransaction *transaction, } } + /* Also check the current transaction since it's possible the EOL ref + * and/or any app(s) that depend on it are not installed. It's also + * possible the current transaction updates one of the apps to a + * newer runtime but we don't handle that yet + * (https://github.com/flatpak/flatpak/issues/4832) + */ + check_current_transaction_for_dependent_apps (apps, transaction, ref); + return g_steal_pointer (&apps); }