Compare commits
12 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0b0c23ce0 | ||
|
|
ab5e4457e4 | ||
|
|
5f0a66c87b | ||
|
|
3025fb5ba5 | ||
|
|
9094b1656e | ||
|
|
975a1e4c06 | ||
|
|
43d8246f4b | ||
|
|
b60b90e758 | ||
|
|
33a8261ad0 | ||
|
|
ba25bafa5f | ||
|
|
e7d886350b | ||
|
|
73ce07b97a |
4 changed files with 1062 additions and 59 deletions
|
|
@ -1,5 +1,5 @@
|
|||
at commit 8a1f0ca6564157dd688c84ffd25af9747c1e038e
|
||||
Date: Mon Aug 11 17:07:06 2025 +0200
|
||||
at commit 786bab5f1928920251ee9e93d51953ff9dd9faa4
|
||||
Date: Mon Sep 1 18:23:09 2025 +0200
|
||||
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index cd49cf529..27fa15e8b 100644
|
||||
|
|
@ -610,10 +610,10 @@ index 000000000..5d522468c
|
|||
+G_END_DECLS
|
||||
diff --git a/plugins/dnf5/gs-plugin-dnf5.c b/plugins/dnf5/gs-plugin-dnf5.c
|
||||
new file mode 100644
|
||||
index 000000000..88d7e25d8
|
||||
index 000000000..82f3e19a8
|
||||
--- /dev/null
|
||||
+++ b/plugins/dnf5/gs-plugin-dnf5.c
|
||||
@@ -0,0 +1,4275 @@
|
||||
@@ -0,0 +1,4589 @@
|
||||
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
|
||||
+ *
|
||||
|
|
@ -1671,9 +1671,13 @@ index 000000000..88d7e25d8
|
|||
+ gchar *details;
|
||||
+ gchar *accept_label;
|
||||
+ gchar *key_id;
|
||||
+ gchar *key_filename;
|
||||
+ gchar *session_path;
|
||||
+ GCancellable *cancellable; /* (owned) */
|
||||
+ GsPluginDnf5 *self; /* (owned) */
|
||||
+ GWeakRef repo_proxy_weakref; /* GsDnf5RpmRepo */
|
||||
+ gboolean interactive;
|
||||
+ gboolean confirmed_by_repo;
|
||||
+} QuestionData;
|
||||
+
|
||||
+static void
|
||||
|
|
@ -1685,6 +1689,9 @@ index 000000000..88d7e25d8
|
|||
+ g_free (data->details);
|
||||
+ g_free (data->accept_label);
|
||||
+ g_free (data->key_id);
|
||||
+ g_free (data->key_filename);
|
||||
+ g_free (data->session_path);
|
||||
+ g_clear_object (&data->cancellable);
|
||||
+ g_clear_object (&data->self);
|
||||
+ g_weak_ref_clear (&data->repo_proxy_weakref);
|
||||
+ g_free (data);
|
||||
|
|
@ -1702,7 +1709,10 @@ index 000000000..88d7e25d8
|
|||
+ g_autoptr(GVariantBuilder) options_builder = NULL;
|
||||
+ gboolean confirmed;
|
||||
+
|
||||
+ confirmed = gs_plugin_ask_untrusted (GS_PLUGIN (data->self), data->title, data->msg, data->details, data->accept_label);
|
||||
+ /* auto-accept new keys, just as PacakgeKit plugin used to do */
|
||||
+ confirmed = data->confirmed_by_repo;
|
||||
+ if (!confirmed)
|
||||
+ confirmed = gs_plugin_ask_untrusted (GS_PLUGIN (data->self), data->title, data->msg, data->details, data->accept_label);
|
||||
+
|
||||
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "interactive",
|
||||
|
|
@ -1712,7 +1722,7 @@ index 000000000..88d7e25d8
|
|||
+ data->key_id,
|
||||
+ confirmed,
|
||||
+ g_variant_builder_end (options_builder),
|
||||
+ NULL,
|
||||
+ data->cancellable,
|
||||
+ gs_dnf5_confirm_key_response_cb,
|
||||
+ NULL);
|
||||
+ }
|
||||
|
|
@ -1720,10 +1730,184 @@ index 000000000..88d7e25d8
|
|||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+gs_dnf5_read_package_repo_ids_cb (GsPluginDnf5 *self,
|
||||
+ GVariant *package_array,
|
||||
+ gpointer user_data,
|
||||
+ GCancellable *cancellable,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ GPtrArray **out_repo_ids = user_data;
|
||||
+ g_autoptr(GVariantDict) dict = NULL;
|
||||
+ g_autoptr(GVariant) value = NULL;
|
||||
+
|
||||
+ dict = g_variant_dict_new (package_array);
|
||||
+
|
||||
+ value = g_variant_dict_lookup_value (dict, "from_repo_id", G_VARIANT_TYPE_STRING);
|
||||
+ if (value != NULL) {
|
||||
+ const gchar *repo_id_const = g_variant_get_string (value, NULL);
|
||||
+ if (repo_id_const != NULL && *repo_id_const != '\0') {
|
||||
+ if (*out_repo_ids == NULL)
|
||||
+ *out_repo_ids = g_ptr_array_new_with_free_func (g_free);
|
||||
+ g_ptr_array_add (*out_repo_ids, g_strdup (repo_id_const));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+gs_dnf5_read_repo_gpg_info_cb (GsPluginDnf5 *self,
|
||||
+ GVariant *package_array,
|
||||
+ gpointer user_data,
|
||||
+ GCancellable *cancellable,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ guint *out_n_good = user_data;
|
||||
+ g_autoptr(GVariantDict) dict = NULL;
|
||||
+ g_autoptr(GVariant) id_value = NULL;
|
||||
+ g_autoptr(GVariant) gpgcheck_value = NULL;
|
||||
+
|
||||
+ dict = g_variant_dict_new (package_array);
|
||||
+
|
||||
+ id_value = g_variant_dict_lookup_value (dict, "id", G_VARIANT_TYPE_STRING);
|
||||
+ gpgcheck_value = g_variant_dict_lookup_value (dict, "gpgcheck", G_VARIANT_TYPE_BOOLEAN);
|
||||
+
|
||||
+ if (id_value != NULL && gpgcheck_value != NULL) {
|
||||
+ gboolean gpgcheck = g_variant_get_boolean (gpgcheck_value);
|
||||
+
|
||||
+ if (gpgcheck)
|
||||
+ *out_n_good = (*out_n_good) + 1;
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static gpointer
|
||||
+gs_dnf5_check_key_source_thread (gpointer user_data)
|
||||
+{
|
||||
+ QuestionData *data = user_data;
|
||||
+ g_autoptr(GsDnf5RpmRpm) rpm_proxy = NULL;
|
||||
+ g_autoptr(GPtrArray) repo_ids = NULL;
|
||||
+ g_autoptr(GError) local_error = NULL;
|
||||
+ gboolean success;
|
||||
+
|
||||
+ rpm_proxy = gs_dnf5_rpm_rpm_proxy_new_sync (data->self->connection,
|
||||
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
+ GS_DNF5_INTERFACE_RPM_DNF,
|
||||
+ data->session_path,
|
||||
+ data->cancellable,
|
||||
+ &local_error);
|
||||
+ success = rpm_proxy != NULL;
|
||||
+ if (!success) {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to create Rpm proxy: ");
|
||||
+ }
|
||||
+
|
||||
+ /* try to get whether the key comes from any package */
|
||||
+ if (success) {
|
||||
+ g_autoptr(GVariantBuilder) options_builder = NULL;
|
||||
+ g_autoptr(GVariantBuilder) package_attrs_builder = NULL;
|
||||
+ g_autoptr(GVariantBuilder) whatprovides_builder = NULL;
|
||||
+ g_autoptr(GVariant) result = NULL;
|
||||
+
|
||||
+ g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (rpm_proxy), G_MAXINT);
|
||||
+
|
||||
+ package_attrs_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
|
||||
+ g_variant_builder_add (package_attrs_builder, "s", "from_repo_id");
|
||||
+
|
||||
+ whatprovides_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
|
||||
+ g_variant_builder_add (whatprovides_builder, "s", data->key_filename);
|
||||
+
|
||||
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "package_attrs",
|
||||
+ g_variant_builder_end (package_attrs_builder));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "whatprovides",
|
||||
+ g_variant_builder_end (whatprovides_builder));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "scope",
|
||||
+ g_variant_new_string ("installed"));
|
||||
+
|
||||
+ success = gs_dnf5_rpm_rpm_call_list_sync (rpm_proxy,
|
||||
+ g_variant_builder_end (options_builder),
|
||||
+ &result,
|
||||
+ data->cancellable,
|
||||
+ &local_error);
|
||||
+
|
||||
+ if (success) {
|
||||
+ success = gs_dnf5_foreach_item (data->self, result, gs_dnf5_read_package_repo_ids_cb, &repo_ids, data->cancellable, &local_error);
|
||||
+ } else {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to call rpm::list: ");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (success && repo_ids != NULL) {
|
||||
+ g_autoptr(GVariantBuilder) patterns_builder = NULL;
|
||||
+ guint n_verify = 0;
|
||||
+
|
||||
+ for (guint i = 0; i < repo_ids->len; i++) {
|
||||
+ const gchar *repo_id = g_ptr_array_index (repo_ids, i);
|
||||
+ /* those are special repos, like `@commandline` */
|
||||
+ if (*repo_id != '@') {
|
||||
+ if (patterns_builder == NULL)
|
||||
+ patterns_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
|
||||
+ g_variant_builder_add (patterns_builder, "s", repo_id);
|
||||
+ n_verify++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (patterns_builder != NULL) {
|
||||
+ g_autoptr(GsDnf5RpmRepo) repo_proxy = NULL;
|
||||
+
|
||||
+ repo_proxy = g_weak_ref_get (&data->repo_proxy_weakref);
|
||||
+ if (repo_proxy != NULL) {
|
||||
+ g_autoptr(GVariantBuilder) repo_attrs_builder = NULL;
|
||||
+ g_autoptr(GVariantBuilder) options_builder = NULL;
|
||||
+ g_autoptr(GVariant) result = NULL;
|
||||
+
|
||||
+ repo_attrs_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
|
||||
+ g_variant_builder_add (repo_attrs_builder, "s", "id");
|
||||
+ g_variant_builder_add (repo_attrs_builder, "s", "gpgcheck");
|
||||
+
|
||||
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "patterns",
|
||||
+ g_variant_builder_end (patterns_builder));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "repo_attrs",
|
||||
+ g_variant_builder_end (repo_attrs_builder));
|
||||
+
|
||||
+ success = gs_dnf5_rpm_repo_call_list_sync (repo_proxy,
|
||||
+ g_variant_builder_end (options_builder),
|
||||
+ &result,
|
||||
+ data->cancellable,
|
||||
+ &local_error);
|
||||
+
|
||||
+ if (success) {
|
||||
+ guint n_good = 0;
|
||||
+
|
||||
+ success = gs_dnf5_foreach_item (data->self, result, gs_dnf5_read_repo_gpg_info_cb, &n_good, data->cancellable, &local_error);
|
||||
+
|
||||
+ data->confirmed_by_repo = success && n_verify == n_good;
|
||||
+ } else {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to call repo::list: ");
|
||||
+ }
|
||||
+ } else {
|
||||
+ success = FALSE;
|
||||
+ g_set_error_literal (&local_error, G_IO_ERROR, G_IO_ERROR_FAILED, "Repo proxy vanished");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE, gs_dnf5_ask_question_idle_cb, data, (GDestroyNotify) question_data_free);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+typedef struct {
|
||||
+ GsPluginDnf5 *self; /* (not owned) */
|
||||
+ const gchar *session_path; /* (not owned) */
|
||||
+ GsDnf5RpmRepo *repo_proxy; /* (not owned) */
|
||||
+ GCancellable *cancellable; /* (not owned) */
|
||||
+ gboolean interactive;
|
||||
+} RepoKeyImportData;
|
||||
+
|
||||
|
|
@ -1798,11 +1982,18 @@ index 000000000..88d7e25d8
|
|||
+ data->details = g_string_free (details, FALSE);
|
||||
+ data->accept_label = g_strdup (_("_Import Key"));
|
||||
+ data->key_id = g_strdup (arg_key_id);
|
||||
+ data->key_filename = g_steal_pointer (&key_filename);
|
||||
+ data->session_path = g_strdup (repo_key_import_data->session_path);
|
||||
+ data->self = g_object_ref (repo_key_import_data->self);
|
||||
+ data->interactive = repo_key_import_data->interactive;
|
||||
+ data->confirmed_by_repo = FALSE;
|
||||
+ g_set_object (&data->cancellable, repo_key_import_data->cancellable);
|
||||
+ g_weak_ref_init (&data->repo_proxy_weakref, repo_key_import_data->repo_proxy);
|
||||
+
|
||||
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE, gs_dnf5_ask_question_idle_cb, data, (GDestroyNotify) question_data_free);
|
||||
+ if (data->key_filename != NULL)
|
||||
+ g_thread_unref (g_thread_new ("gs-dnf5-check-key-source_thread", gs_dnf5_check_key_source_thread, data));
|
||||
+ else
|
||||
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE, gs_dnf5_ask_question_idle_cb, data, (GDestroyNotify) question_data_free);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
|
|
@ -1884,7 +2075,8 @@ index 000000000..88d7e25d8
|
|||
+ GS_DNF5_TRANSACTION_FLAG_OFFLINE = 1 << 0,
|
||||
+ GS_DNF5_TRANSACTION_FLAG_RESOLVE_ONLY = 1 << 1,
|
||||
+ GS_DNF5_TRANSACTION_FLAG_DISALLOW_ERASING = 1 << 2, /* negative flag, to not have it everywhere */
|
||||
+ GS_DNF5_TRANSACTION_FLAG_INTERACTIVE = 1 << 3
|
||||
+ GS_DNF5_TRANSACTION_FLAG_INTERACTIVE = 1 << 3,
|
||||
+ GS_DNF5_TRANSACTION_FLAG_DOWNLOAD_ONLY = 1 << 4
|
||||
+} GsDnf5TransactionFlags;
|
||||
+
|
||||
+static gboolean
|
||||
|
|
@ -1963,6 +2155,7 @@ index 000000000..88d7e25d8
|
|||
+ repo_key_import_data.session_path = session_path;
|
||||
+ repo_key_import_data.repo_proxy = repo_proxy;
|
||||
+ repo_key_import_data.interactive = interactive;
|
||||
+ repo_key_import_data.cancellable = cancellable;
|
||||
+ repo_key_import_id = g_signal_connect (base_proxy, "repo_key_import_request",
|
||||
+ G_CALLBACK (gs_dnf5_repo_key_import_request_cb), &repo_key_import_data);
|
||||
+
|
||||
|
|
@ -2015,6 +2208,10 @@ index 000000000..88d7e25d8
|
|||
+ g_variant_builder_add (options_builder, "{sv}", "offline",
|
||||
+ g_variant_new_boolean (TRUE));
|
||||
+ }
|
||||
+ if ((flags & GS_DNF5_TRANSACTION_FLAG_DOWNLOAD_ONLY) != 0) {
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "downloadonly",
|
||||
+ g_variant_new_boolean (TRUE));
|
||||
+ }
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "interactive",
|
||||
+ g_variant_new_boolean (interactive));
|
||||
+
|
||||
|
|
@ -2570,54 +2767,57 @@ index 000000000..88d7e25d8
|
|||
+ g_prefix_error_literal (&local_error, "Failed to call Rpm::list: ");
|
||||
+ }
|
||||
+ } else if (is_historical_update == GS_APP_QUERY_TRISTATE_TRUE) {
|
||||
+ g_autoptr(GsDnf5History) history_proxy = NULL;
|
||||
+ g_autoptr(GSettings) settings = NULL;
|
||||
+ gint64 timestamp;
|
||||
+
|
||||
+ history_proxy = gs_dnf5_history_proxy_new_sync (self->connection,
|
||||
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
+ GS_DNF5_INTERFACE_RPM_DNF,
|
||||
+ session_path,
|
||||
+ cancellable,
|
||||
+ &local_error);
|
||||
+ success = history_proxy != NULL;
|
||||
+ if (!success) {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to create History proxy: ");
|
||||
+ }
|
||||
+ /* use the option the GUI part uses */
|
||||
+ settings = g_settings_new ("org.gnome.software");
|
||||
+ timestamp = (gint64) g_settings_get_uint64 (settings, "packagekit-historical-updates-timestamp");
|
||||
+
|
||||
+ if (success) {
|
||||
+ g_autoptr(GVariantBuilder) options_builder = NULL;
|
||||
+ g_autoptr(GVariant) result = NULL;
|
||||
+ g_autoptr(GSettings) settings;
|
||||
+ gint64 timestamp;
|
||||
+ if (timestamp > 0) {
|
||||
+ g_autoptr(GsDnf5History) history_proxy = NULL;
|
||||
+
|
||||
+ /* use the option the GUI part uses */
|
||||
+ settings = g_settings_new ("org.gnome.software");
|
||||
+ timestamp = g_settings_get_int64 (settings, "install-timestamp");
|
||||
+
|
||||
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "since",
|
||||
+ g_variant_new_int64 (timestamp));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "package_attrs",
|
||||
+ gs_dnf5_dup_package_attrs ());
|
||||
+
|
||||
+ success = gs_dnf5_history_call_recent_changes_sync (history_proxy,
|
||||
+ g_variant_builder_end (options_builder),
|
||||
+ &result,
|
||||
+ cancellable,
|
||||
+ &local_error);
|
||||
+ history_proxy = gs_dnf5_history_proxy_new_sync (self->connection,
|
||||
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
+ GS_DNF5_INTERFACE_RPM_DNF,
|
||||
+ session_path,
|
||||
+ cancellable,
|
||||
+ &local_error);
|
||||
+ success = history_proxy != NULL;
|
||||
+ if (!success) {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to create History proxy: ");
|
||||
+ }
|
||||
+
|
||||
+ if (success) {
|
||||
+ ReadPackageData rpd = { 0, };
|
||||
+ g_autoptr(GVariantBuilder) options_builder = NULL;
|
||||
+ g_autoptr(GVariant) result = NULL;
|
||||
+
|
||||
+ rpd.list = list;
|
||||
+ rpd.set_state = GS_APP_STATE_UNKNOWN;
|
||||
+ rpd.nevra_to_app = NULL;
|
||||
+ rpd.timestamp = timestamp;
|
||||
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "since",
|
||||
+ g_variant_new_int64 (timestamp));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "package_attrs",
|
||||
+ gs_dnf5_dup_package_attrs ());
|
||||
+
|
||||
+ success = gs_dnf5_foreach_item (self, result, gs_dnf5_read_history_items_cb, &rpd, cancellable, &local_error);
|
||||
+ } else {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to call recent_changes: ");
|
||||
+ success = gs_dnf5_history_call_recent_changes_sync (history_proxy,
|
||||
+ g_variant_builder_end (options_builder),
|
||||
+ &result,
|
||||
+ cancellable,
|
||||
+ &local_error);
|
||||
+
|
||||
+ if (success) {
|
||||
+ ReadPackageData rpd = { 0, };
|
||||
+
|
||||
+ rpd.list = list;
|
||||
+ rpd.set_state = GS_APP_STATE_UNKNOWN;
|
||||
+ rpd.nevra_to_app = NULL;
|
||||
+ rpd.timestamp = timestamp;
|
||||
+
|
||||
+ success = gs_dnf5_foreach_item (self, result, gs_dnf5_read_history_items_cb, &rpd, cancellable, &local_error);
|
||||
+ } else {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to call recent_changes: ");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (gs_component_kind_array_contains (component_kinds, AS_COMPONENT_KIND_REPOSITORY)) {
|
||||
|
|
@ -3574,6 +3774,7 @@ index 000000000..88d7e25d8
|
|||
+ GsAppList *list,
|
||||
+ gboolean is_install,
|
||||
+ gboolean interactive,
|
||||
+ gboolean can_apply,
|
||||
+ GsPluginEventCallback event_callback,
|
||||
+ void *event_user_data,
|
||||
+ GCancellable *cancellable,
|
||||
|
|
@ -3698,7 +3899,8 @@ index 000000000..88d7e25d8
|
|||
+ success = rpm_proxy != NULL;
|
||||
+ if (success) {
|
||||
+ g_autoptr(GVariantBuilder) options_builder = NULL;
|
||||
+ GsDnf5TransactionFlags flags = interactive ? GS_DNF5_TRANSACTION_FLAG_INTERACTIVE : GS_DNF5_TRANSACTION_FLAG_NONE;
|
||||
+ GsDnf5TransactionFlags flags = (interactive ? GS_DNF5_TRANSACTION_FLAG_INTERACTIVE : GS_DNF5_TRANSACTION_FLAG_NONE) |
|
||||
+ (!can_apply ? GS_DNF5_TRANSACTION_FLAG_DOWNLOAD_ONLY : GS_DNF5_TRANSACTION_FLAG_NONE);
|
||||
+
|
||||
+ g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (rpm_proxy), G_MAXINT);
|
||||
+
|
||||
|
|
@ -3730,7 +3932,7 @@ index 000000000..88d7e25d8
|
|||
+ success = success && gs_dnf5_run_transaction (self, session_path, rpm_proxy, progress_app, progress_list,
|
||||
+ flags | (is_install ? 0 : GS_DNF5_TRANSACTION_FLAG_OFFLINE),
|
||||
+ NULL, cancellable, error);
|
||||
+ if (success && !is_install) {
|
||||
+ if (success && !is_install && can_apply) {
|
||||
+ /* ensure the update is finished with the 'reboot' action */
|
||||
+ g_autoptr(GsDnf5Offline) offline_proxy = NULL;
|
||||
+
|
||||
|
|
@ -3767,6 +3969,10 @@ index 000000000..88d7e25d8
|
|||
+ } else if (!success) {
|
||||
+ gs_dnf5_convert_error (error);
|
||||
+ g_prefix_error_literal (error, "Failed to set finish action: ");
|
||||
+ } else {
|
||||
+ g_autoptr(GSettings) settings = g_settings_new ("org.gnome.software");
|
||||
+ /* to check anything installed/updated after today */
|
||||
+ g_settings_set (settings, "packagekit-historical-updates-timestamp", "t", g_get_real_time () / G_USEC_PER_SEC);
|
||||
+ }
|
||||
+ } else {
|
||||
+ gs_dnf5_convert_error (error);
|
||||
|
|
@ -3850,6 +4056,7 @@ index 000000000..88d7e25d8
|
|||
+
|
||||
+ success = gs_dnf5_install_update (plugin, data->apps, TRUE,
|
||||
+ (data->flags & GS_PLUGIN_INSTALL_APPS_FLAGS_INTERACTIVE) != 0,
|
||||
+ (data->flags & GS_PLUGIN_INSTALL_APPS_FLAGS_NO_APPLY) == 0,
|
||||
+ data->event_callback, data->event_user_data,
|
||||
+ cancellable, &local_error);
|
||||
+
|
||||
|
|
@ -4093,6 +4300,7 @@ index 000000000..88d7e25d8
|
|||
+
|
||||
+ success = gs_dnf5_install_update (plugin, data->apps, FALSE,
|
||||
+ (data->flags & GS_PLUGIN_UPDATE_APPS_FLAGS_INTERACTIVE) != 0,
|
||||
+ (data->flags & GS_PLUGIN_UPDATE_APPS_FLAGS_NO_APPLY) == 0,
|
||||
+ data->event_callback, data->event_user_data,
|
||||
+ cancellable, &local_error);
|
||||
+
|
||||
|
|
@ -4778,6 +4986,110 @@ index 000000000..88d7e25d8
|
|||
+ return g_task_propagate_boolean (G_TASK (result), error);
|
||||
+}
|
||||
+
|
||||
+/* Run in @worker. */
|
||||
+static void
|
||||
+gs_dnf5_cancel_offline_update_thread_cb (GTask *task,
|
||||
+ gpointer source_object,
|
||||
+ gpointer task_data,
|
||||
+ GCancellable *cancellable)
|
||||
+{
|
||||
+ GsPluginDnf5 *self = GS_PLUGIN_DNF5 (source_object);
|
||||
+ GsPluginCancelOfflineUpdateData *data = task_data;
|
||||
+ g_autofree gchar *session_path = NULL;
|
||||
+ g_autoptr(GsAppList) list = NULL;
|
||||
+ g_autoptr(GsDnf5SessionManager) session_manager = NULL;
|
||||
+ g_autoptr(GsDnf5Offline) offline_proxy = NULL;
|
||||
+ gboolean success;
|
||||
+ g_autoptr(GError) local_error = NULL;
|
||||
+
|
||||
+ assert_in_worker (self);
|
||||
+
|
||||
+ session_path = gs_dnf5_open_session (self, GS_DNF5_RELEASEVER_DEFAULT, &session_manager, cancellable, &local_error);
|
||||
+ if (session_path == NULL) {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_task_return_error (task, g_steal_pointer (&local_error));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ offline_proxy = gs_dnf5_offline_proxy_new_sync (self->connection,
|
||||
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
+ GS_DNF5_INTERFACE_RPM_DNF,
|
||||
+ session_path,
|
||||
+ cancellable,
|
||||
+ &local_error);
|
||||
+ success = offline_proxy != NULL;
|
||||
+ if (!success) {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to create Offline proxy: ");
|
||||
+ }
|
||||
+
|
||||
+ if (success) {
|
||||
+ gboolean pending = FALSE;
|
||||
+ g_autoptr(GVariant) transaction_status = NULL;
|
||||
+
|
||||
+ if (gs_dnf5_offline_call_get_status_sync (offline_proxy, &pending, &transaction_status, cancellable, &local_error) &&
|
||||
+ pending && transaction_status != NULL) {
|
||||
+ g_autoptr(GVariantBuilder) options_builder = NULL;
|
||||
+ g_autofree gchar *op_error_msg = NULL;
|
||||
+ gboolean op_success = FALSE;
|
||||
+
|
||||
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
+ g_variant_builder_add (options_builder, "{sv}", "interactive",
|
||||
+ g_variant_new_boolean ((data->flags & GS_PLUGIN_CANCEL_OFFLINE_UPDATE_FLAGS_INTERACTIVE) != 0));
|
||||
+
|
||||
+ success = gs_dnf5_offline_call_cancel_with_options_sync (offline_proxy, g_variant_builder_end (options_builder),
|
||||
+ &op_success, &op_error_msg, cancellable, &local_error);
|
||||
+ if (!success) {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to call OfflineProxy::cancel: ");
|
||||
+ } else if (!op_success) {
|
||||
+ success = FALSE;
|
||||
+ if (op_error_msg != NULL) {
|
||||
+ g_set_error_literal (&local_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, op_error_msg);
|
||||
+ g_prefix_error_literal (&local_error, "Failed to call OfflineProxy::cancel op: ");
|
||||
+ } else {
|
||||
+ g_set_error_literal (&local_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "Failed to call OfflineProxy::cancel op");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ gs_dnf5_close_session (self, session_manager, session_path);
|
||||
+
|
||||
+ if (success) {
|
||||
+ g_task_return_boolean (task, TRUE);
|
||||
+ } else {
|
||||
+ gs_dnf5_convert_error (&local_error);
|
||||
+ g_task_return_error (task, g_steal_pointer (&local_error));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gs_plugin_dnf5_cancel_offline_update_async (GsPlugin *plugin,
|
||||
+ GsPluginCancelOfflineUpdateFlags flags,
|
||||
+ GCancellable *cancellable,
|
||||
+ GAsyncReadyCallback callback,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ GsPluginDnf5 *self = GS_PLUGIN_DNF5 (plugin);
|
||||
+ g_autoptr(GTask) task = NULL;
|
||||
+ gboolean interactive = (flags & GS_PLUGIN_CANCEL_OFFLINE_UPDATE_FLAGS_INTERACTIVE) != 0;
|
||||
+
|
||||
+ task = gs_plugin_cancel_offline_update_data_new_task (plugin, flags, cancellable, callback, user_data);
|
||||
+ g_task_set_source_tag (task, gs_plugin_dnf5_cancel_offline_update_async);
|
||||
+
|
||||
+ gs_worker_thread_queue (self->worker, gs_dnf5_get_priority_for_interactivity (interactive),
|
||||
+ gs_dnf5_cancel_offline_update_thread_cb, g_steal_pointer (&task));
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+gs_plugin_dnf5_cancel_offline_update_finish (GsPlugin *plugin,
|
||||
+ GAsyncResult *result,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ return g_task_propagate_boolean (G_TASK (result), error);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gs_plugin_dnf5_dispose (GObject *object)
|
||||
+{
|
||||
|
|
@ -4863,6 +5175,8 @@ index 000000000..88d7e25d8
|
|||
+ plugin_class->download_upgrade_finish = gs_plugin_dnf5_download_upgrade_finish;
|
||||
+ plugin_class->trigger_upgrade_async = gs_plugin_dnf5_trigger_upgrade_async;
|
||||
+ plugin_class->trigger_upgrade_finish = gs_plugin_dnf5_trigger_upgrade_finish;
|
||||
+ plugin_class->cancel_offline_update_async = gs_plugin_dnf5_cancel_offline_update_async;
|
||||
+ plugin_class->cancel_offline_update_finish = gs_plugin_dnf5_cancel_offline_update_finish;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
|
|
|
|||
686
0002-rhbug2416542-crash-under-gs_flatpak_refine_wildcard.patch
Normal file
686
0002-rhbug2416542-crash-under-gs_flatpak_refine_wildcard.patch
Normal file
|
|
@ -0,0 +1,686 @@
|
|||
From 0c79d9fb08a348a45a18f15427c945a63b44982e Mon Sep 17 00:00:00 2001
|
||||
Date: Mon, 24 Nov 2025 16:06:51 +0100
|
||||
Subject: [PATCH 1/3] flatpak: Fix XbSilo lifetime in
|
||||
gs_flatpak_refine_wildcard()
|
||||
|
||||
The function uses pre-cached data in the hash tables, consisting of XbNode-s
|
||||
from an XbSilo. The nodes are referenced, but the silos the node belongs to
|
||||
is not referenced (by the XbNode).
|
||||
|
||||
This change keeps the XbSilo alive as long as it's needed for the nodes
|
||||
in the pre-cached data. It also does not call gs_flatpak_ref_silo() multiple
|
||||
times for the same GsFlatpak instance, which could invalidate the XbNode-s
|
||||
in the pre-cached data when a change in the silo or in the installation
|
||||
had been received while the function was still processing the apps.
|
||||
|
||||
Related downstream bug https://bugzilla.redhat.com/show_bug.cgi?id=2416542
|
||||
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/2900
|
||||
---
|
||||
plugins/flatpak/gs-flatpak.c | 18 ++++++++---
|
||||
plugins/flatpak/gs-flatpak.h | 4 +++
|
||||
plugins/flatpak/gs-plugin-flatpak.c | 49 ++++++++++++++++++++---------
|
||||
3 files changed, 51 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
|
||||
index b409475c7..a40ab54fb 100644
|
||||
--- a/plugins/flatpak/gs-flatpak.c
|
||||
+++ b/plugins/flatpak/gs-flatpak.c
|
||||
@@ -3748,16 +3748,19 @@ gboolean
|
||||
gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app,
|
||||
GsAppList *list, GsPluginRefineRequireFlags require_flags,
|
||||
gboolean interactive,
|
||||
+ XbSilo **inout_silo,
|
||||
+ gchar **inout_silo_filename,
|
||||
+ GHashTable **inout_installed_by_desktopid,
|
||||
GHashTable **inout_components_by_id,
|
||||
GHashTable **inout_components_by_bundle,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
const gchar *id;
|
||||
GPtrArray* components = NULL;
|
||||
+ XbSilo *silo;
|
||||
+ GHashTable *silo_installed_by_desktopid;
|
||||
+ const gchar *silo_filename;
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
- g_autoptr(XbSilo) silo = NULL;
|
||||
- g_autoptr(GHashTable) silo_installed_by_desktopid = NULL;
|
||||
- g_autofree gchar *silo_filename = NULL;
|
||||
|
||||
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcard, "Flatpak (refine wildcard)", NULL);
|
||||
|
||||
@@ -3766,10 +3769,15 @@ gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app,
|
||||
if (id == NULL)
|
||||
return TRUE;
|
||||
|
||||
- silo = gs_flatpak_ref_silo (self, interactive, &silo_filename, &silo_installed_by_desktopid, cancellable, error);
|
||||
- if (silo == NULL)
|
||||
+ if (*inout_silo == NULL)
|
||||
+ *inout_silo = gs_flatpak_ref_silo (self, interactive, inout_silo_filename, inout_installed_by_desktopid, cancellable, error);
|
||||
+ if (*inout_silo == NULL)
|
||||
return FALSE;
|
||||
|
||||
+ silo = *inout_silo;
|
||||
+ silo_filename = *inout_silo_filename;
|
||||
+ silo_installed_by_desktopid = *inout_installed_by_desktopid;
|
||||
+
|
||||
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardQuerySilo, "Flatpak (query silo)", NULL);
|
||||
|
||||
if (*inout_components_by_id != NULL) {
|
||||
diff --git a/plugins/flatpak/gs-flatpak.h b/plugins/flatpak/gs-flatpak.h
|
||||
index 66ff59967..34e1416b5 100644
|
||||
--- a/plugins/flatpak/gs-flatpak.h
|
||||
+++ b/plugins/flatpak/gs-flatpak.h
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <gnome-software.h>
|
||||
#include <flatpak.h>
|
||||
+#include <xmlb.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -108,6 +109,9 @@ gboolean gs_flatpak_refine_wildcard (GsFlatpak *self,
|
||||
GsAppList *list,
|
||||
GsPluginRefineRequireFlags require_flags,
|
||||
gboolean interactive,
|
||||
+ XbSilo **inout_silo,
|
||||
+ gchar **inout_silo_filename,
|
||||
+ GHashTable **inout_installed_by_desktopid,
|
||||
GHashTable **inout_components_by_id,
|
||||
GHashTable **inout_components_by_bundle,
|
||||
GCancellable *cancellable,
|
||||
diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c
|
||||
index 3d0503d46..f5d4a1d67 100644
|
||||
--- a/plugins/flatpak/gs-plugin-flatpak.c
|
||||
+++ b/plugins/flatpak/gs-plugin-flatpak.c
|
||||
@@ -667,12 +667,29 @@ gs_plugin_flatpak_refine_app (GsPluginFlatpak *self,
|
||||
return gs_flatpak_refine_app (flatpak, app, require_flags, interactive, FALSE, event_callback, event_user_data, cancellable, error);
|
||||
}
|
||||
|
||||
+typedef struct {
|
||||
+ XbSilo *silo;
|
||||
+ gchar *silo_filename;
|
||||
+ GHashTable *installed_by_desktopid;
|
||||
+ GHashTable *components_by_id;
|
||||
+ GHashTable *components_by_bundle;
|
||||
+} RefineInstallationData;
|
||||
+
|
||||
static void
|
||||
-unref_nonnull_hash_table (gpointer ptr)
|
||||
+refine_installation_data_free (gpointer ptr)
|
||||
{
|
||||
- GHashTable *hash_table = ptr;
|
||||
- if (hash_table != NULL)
|
||||
- g_hash_table_unref (hash_table);
|
||||
+ RefineInstallationData *data = ptr;
|
||||
+
|
||||
+ if (data == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ g_clear_pointer (&data->silo_filename, g_free);
|
||||
+ g_clear_pointer (&data->installed_by_desktopid, g_hash_table_unref);
|
||||
+ g_clear_pointer (&data->components_by_id, g_hash_table_unref);
|
||||
+ g_clear_pointer (&data->components_by_bundle, g_hash_table_unref);
|
||||
+ /* free the silo as the last, just in case, because the data from it is in the above hash tables */
|
||||
+ g_clear_object (&data->silo);
|
||||
+ g_free (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -761,8 +778,7 @@ refine_thread_cb (GTask *task,
|
||||
gboolean interactive = (data->job_flags & GS_PLUGIN_REFINE_FLAGS_INTERACTIVE) != 0;
|
||||
GsPluginEventCallback event_callback = data->event_callback;
|
||||
void *event_user_data = data->event_user_data;
|
||||
- g_autoptr(GPtrArray) array_components_by_id = NULL; /* (element-type GHashTable) */
|
||||
- g_autoptr(GPtrArray) array_components_by_bundle = NULL; /* (element-type GHashTable) */
|
||||
+ g_autoptr(GPtrArray) installation_data = NULL; /* (element-type RefineInstallationData) */
|
||||
g_autoptr(GsAppList) app_list = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
|
||||
@@ -783,10 +799,9 @@ refine_thread_cb (GTask *task,
|
||||
* (e.g. inserting an app in the list on every call results in
|
||||
* an infinite loop) */
|
||||
app_list = gs_app_list_copy (list);
|
||||
- array_components_by_id = g_ptr_array_new_full (self->installations->len, unref_nonnull_hash_table);
|
||||
- g_ptr_array_set_size (array_components_by_id, self->installations->len);
|
||||
- array_components_by_bundle = g_ptr_array_new_full (self->installations->len, unref_nonnull_hash_table);
|
||||
- g_ptr_array_set_size (array_components_by_bundle, self->installations->len);
|
||||
+
|
||||
+ installation_data = g_ptr_array_new_full (self->installations->len, refine_installation_data_free);
|
||||
+ g_ptr_array_set_size (installation_data, self->installations->len);
|
||||
|
||||
for (guint j = 0; j < gs_app_list_length (app_list); j++) {
|
||||
GsApp *app = gs_app_list_index (app_list, j);
|
||||
@@ -796,16 +811,20 @@ refine_thread_cb (GTask *task,
|
||||
|
||||
for (guint i = 0; i < self->installations->len; i++) {
|
||||
GsFlatpak *flatpak = g_ptr_array_index (self->installations, i);
|
||||
- GHashTable *components_by_id = array_components_by_id->pdata[i];
|
||||
- GHashTable *components_by_bundle = array_components_by_bundle->pdata[i];
|
||||
+ RefineInstallationData *inst_data = g_ptr_array_index (installation_data, i);
|
||||
+
|
||||
+ if (inst_data == NULL) {
|
||||
+ inst_data = g_new0 (RefineInstallationData, 1);
|
||||
+ installation_data->pdata[i] = inst_data;
|
||||
+ }
|
||||
|
||||
- if (!gs_flatpak_refine_wildcard (flatpak, app, list, require_flags, interactive, &components_by_id, &components_by_bundle,
|
||||
+ if (!gs_flatpak_refine_wildcard (flatpak, app, list, require_flags, interactive, &inst_data->silo,
|
||||
+ &inst_data->silo_filename, &inst_data->installed_by_desktopid,
|
||||
+ &inst_data->components_by_id, &inst_data->components_by_bundle,
|
||||
cancellable, &local_error)) {
|
||||
g_task_return_error (task, g_steal_pointer (&local_error));
|
||||
return;
|
||||
}
|
||||
- array_components_by_id->pdata[i] = components_by_id;
|
||||
- array_components_by_bundle->pdata[i] = components_by_bundle;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From 546c6ee17b5959d2a696a6cb346a1f8b94aba303 Mon Sep 17 00:00:00 2001
|
||||
Date: Wed, 7 Jan 2026 18:37:52 +0100
|
||||
Subject: [PATCH 2/3] flatpak: Simplify wildcard app lookup function
|
||||
|
||||
By flipping the order of traversing app and installation the code
|
||||
can be simplified to not have too many in/out arguments.
|
||||
|
||||
Suggested by Philip Withnall
|
||||
---
|
||||
plugins/flatpak/gs-flatpak.c | 251 ++++++++++++++--------------
|
||||
plugins/flatpak/gs-flatpak.h | 9 +-
|
||||
plugins/flatpak/gs-plugin-flatpak.c | 61 +------
|
||||
3 files changed, 130 insertions(+), 191 deletions(-)
|
||||
|
||||
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
|
||||
index a40ab54fb..782b0bb48 100644
|
||||
--- a/plugins/flatpak/gs-flatpak.c
|
||||
+++ b/plugins/flatpak/gs-flatpak.c
|
||||
@@ -3745,167 +3745,158 @@ gs_flatpak_refine_app (GsFlatpak *self,
|
||||
}
|
||||
|
||||
gboolean
|
||||
-gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app,
|
||||
- GsAppList *list, GsPluginRefineRequireFlags require_flags,
|
||||
- gboolean interactive,
|
||||
- XbSilo **inout_silo,
|
||||
- gchar **inout_silo_filename,
|
||||
- GHashTable **inout_installed_by_desktopid,
|
||||
- GHashTable **inout_components_by_id,
|
||||
- GHashTable **inout_components_by_bundle,
|
||||
- GCancellable *cancellable, GError **error)
|
||||
+gs_flatpak_refine_wildcards (GsFlatpak *self,
|
||||
+ GPtrArray *wildcard_apps,
|
||||
+ GsAppList *list,
|
||||
+ GsPluginRefineRequireFlags require_flags,
|
||||
+ gboolean interactive,
|
||||
+ GCancellable *cancellable,
|
||||
+ GError **error)
|
||||
{
|
||||
- const gchar *id;
|
||||
- GPtrArray* components = NULL;
|
||||
- XbSilo *silo;
|
||||
- GHashTable *silo_installed_by_desktopid;
|
||||
- const gchar *silo_filename;
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
+ g_autoptr(XbSilo) silo = NULL;
|
||||
+ g_autoptr(GHashTable) silo_installed_by_desktopid = NULL;
|
||||
+ g_autoptr(GHashTable) components_by_id = NULL;
|
||||
+ g_autoptr(GHashTable) components_by_bundle = NULL;
|
||||
+ g_autoptr(GPtrArray) components_with_id = NULL;
|
||||
+ g_autoptr(GPtrArray) bundles = NULL;
|
||||
+ g_autofree gchar *silo_filename = NULL;
|
||||
|
||||
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcard, "Flatpak (refine wildcard)", NULL);
|
||||
|
||||
- /* not enough info to find */
|
||||
- id = gs_app_get_id (app);
|
||||
- if (id == NULL)
|
||||
- return TRUE;
|
||||
-
|
||||
- if (*inout_silo == NULL)
|
||||
- *inout_silo = gs_flatpak_ref_silo (self, interactive, inout_silo_filename, inout_installed_by_desktopid, cancellable, error);
|
||||
- if (*inout_silo == NULL)
|
||||
+ silo = gs_flatpak_ref_silo (self, interactive, &silo_filename, &silo_installed_by_desktopid, cancellable, error);
|
||||
+ if (silo == NULL)
|
||||
return FALSE;
|
||||
|
||||
- silo = *inout_silo;
|
||||
- silo_filename = *inout_silo_filename;
|
||||
- silo_installed_by_desktopid = *inout_installed_by_desktopid;
|
||||
-
|
||||
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardQuerySilo, "Flatpak (query silo)", NULL);
|
||||
|
||||
- if (*inout_components_by_id != NULL) {
|
||||
- components = g_hash_table_lookup (*inout_components_by_id, gs_app_get_id (app));
|
||||
- } else {
|
||||
- g_autoptr(GPtrArray) components_with_id = NULL;
|
||||
- *inout_components_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref);
|
||||
- components_with_id = xb_silo_query (silo, "components/component/id", 0, &error_local);
|
||||
- if (components_with_id == NULL) {
|
||||
- if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
- return TRUE;
|
||||
- g_propagate_error (error, g_steal_pointer (&error_local));
|
||||
- return FALSE;
|
||||
+ components_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref);
|
||||
+ components_with_id = xb_silo_query (silo, "components/component/id", 0, &error_local);
|
||||
+ if (components_with_id == NULL) {
|
||||
+ if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
+ return TRUE;
|
||||
+ g_propagate_error (error, g_steal_pointer (&error_local));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ for (guint i = 0; i < components_with_id->len; i++) {
|
||||
+ XbNode *node = g_ptr_array_index (components_with_id, i);
|
||||
+ XbNode *comp_node = xb_node_get_parent (node);
|
||||
+ const gchar *comp_id = xb_node_get_text (node);
|
||||
+ GPtrArray *comps = g_hash_table_lookup (components_by_id, comp_id);
|
||||
+ if (comps == NULL) {
|
||||
+ comps = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
+ g_hash_table_insert (components_by_id, g_strdup (comp_id), comps);
|
||||
}
|
||||
- for (guint i = 0; i < components_with_id->len; i++) {
|
||||
- XbNode *node = g_ptr_array_index (components_with_id, i);
|
||||
- XbNode *comp_node = xb_node_get_parent (node);
|
||||
- const gchar *comp_id = xb_node_get_text (node);
|
||||
- GPtrArray *comps = g_hash_table_lookup (*inout_components_by_id, comp_id);
|
||||
- if (comps == NULL) {
|
||||
- comps = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
- g_hash_table_insert (*inout_components_by_id, g_strdup (comp_id), comps);
|
||||
+ g_ptr_array_add (comps, comp_node);
|
||||
+ }
|
||||
+
|
||||
+ components_by_bundle = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
+ bundles = xb_silo_query (silo, "/components/component/bundle[@type='flatpak']", 0, NULL);
|
||||
+ for (guint b = 0; bundles != NULL && b < bundles->len; b++) {
|
||||
+ XbNode *bundle_node = g_ptr_array_index (bundles, b);
|
||||
+ g_autoptr(XbNode) component_node = xb_node_get_parent (bundle_node);
|
||||
+ g_autoptr(XbNode) components_node = xb_node_get_parent (component_node);
|
||||
+ const gchar *origin = xb_node_get_attr (components_node, "origin");
|
||||
+ if (origin != NULL) {
|
||||
+ const gchar *bundle = xb_node_get_text (bundle_node);
|
||||
+ if (bundle != NULL) {
|
||||
+ g_autofree gchar *key = g_strconcat (origin, "\n", bundle, NULL);
|
||||
+ g_hash_table_insert (components_by_bundle, g_steal_pointer (&key), g_steal_pointer (&component_node));
|
||||
}
|
||||
- g_ptr_array_add (comps, comp_node);
|
||||
- if (components == NULL && g_strcmp0 (id, comp_id) == 0)
|
||||
- components = comps;
|
||||
}
|
||||
}
|
||||
|
||||
GS_PROFILER_END_SCOPED (FlatpakRefineWildcardQuerySilo);
|
||||
|
||||
- if (components == NULL)
|
||||
- return TRUE;
|
||||
-
|
||||
gs_flatpak_ensure_remote_title (self, interactive, cancellable);
|
||||
|
||||
- if (*inout_components_by_bundle == NULL) {
|
||||
- g_autoptr(GPtrArray) bundles = NULL;
|
||||
-
|
||||
- *inout_components_by_bundle = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
- bundles = xb_silo_query (silo, "/components/component/bundle[@type='flatpak']", 0, NULL);
|
||||
- for (guint b = 0; bundles != NULL && b < bundles->len; b++) {
|
||||
- XbNode *bundle_node = g_ptr_array_index (bundles, b);
|
||||
- g_autoptr(XbNode) component_node = xb_node_get_parent (bundle_node);
|
||||
- g_autoptr(XbNode) components_node = xb_node_get_parent (component_node);
|
||||
- const gchar *origin = xb_node_get_attr (components_node, "origin");
|
||||
- if (origin != NULL) {
|
||||
- const gchar *bundle = xb_node_get_text (bundle_node);
|
||||
- if (bundle != NULL) {
|
||||
- g_autofree gchar *key = g_strconcat (origin, "\n", bundle, NULL);
|
||||
- g_hash_table_insert (*inout_components_by_bundle, g_steal_pointer (&key), g_steal_pointer (&component_node));
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ for (guint j = 0; j < wildcard_apps->len; j++) {
|
||||
+ GsApp *app = g_ptr_array_index (wildcard_apps, j);
|
||||
+ GPtrArray *components = NULL;
|
||||
+ const gchar *id;
|
||||
|
||||
+ /* not enough info to find */
|
||||
+ id = gs_app_get_id (app);
|
||||
+ if (id == NULL)
|
||||
+ continue;
|
||||
|
||||
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardGenerateApps, "Flatpak (create app)", NULL);
|
||||
- for (guint i = 0; i < components->len; i++) {
|
||||
- XbNode *component = g_ptr_array_index (components, i);
|
||||
- g_autoptr(GsApp) new = NULL;
|
||||
+ components = g_hash_table_lookup (components_by_id, id);
|
||||
+ if (components == NULL)
|
||||
+ continue;
|
||||
|
||||
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardCreateAppstreamApp, "Flatpak (create Appstream app)", NULL);
|
||||
- new = gs_appstream_create_app (self->plugin, silo, component, silo_filename ? silo_filename : "",
|
||||
- self->scope, error);
|
||||
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardCreateAppstreamApp);
|
||||
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardGenerateApps, "Flatpak (create app)", NULL);
|
||||
+ for (guint i = 0; i < components->len; i++) {
|
||||
+ XbNode *component = g_ptr_array_index (components, i);
|
||||
+ g_autoptr(GsApp) new = NULL;
|
||||
|
||||
- if (new == NULL)
|
||||
- return FALSE;
|
||||
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardCreateAppstreamApp, "Flatpak (create Appstream app)", NULL);
|
||||
+ new = gs_appstream_create_app (self->plugin, silo, component, silo_filename ? silo_filename : "",
|
||||
+ self->scope, error);
|
||||
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardCreateAppstreamApp);
|
||||
|
||||
- gs_flatpak_claim_app (self, new);
|
||||
-
|
||||
- /* The appstream plugin did not find the component in the plugin's cache,
|
||||
- thus read the required info from the 'bundle' element. */
|
||||
- if (gs_flatpak_app_get_ref_name (new) == NULL ||
|
||||
- gs_flatpak_app_get_ref_arch (new) == NULL) {
|
||||
- const gchar *xref_str = NULL;
|
||||
- g_autoptr(XbNode) child = NULL;
|
||||
- g_autoptr(XbNode) next = NULL;
|
||||
- for (child = xb_node_get_child (component); child != NULL && xref_str == NULL;
|
||||
- g_object_unref (child), child = g_steal_pointer (&next)) {
|
||||
- next = xb_node_get_next (child);
|
||||
- if (g_strcmp0 (xb_node_get_element (child), "bundle") == 0 &&
|
||||
- g_strcmp0 (xb_node_get_attr (child, "type"), "flatpak") == 0) {
|
||||
- xref_str = xb_node_get_text (child);
|
||||
- break;
|
||||
+ if (new == NULL)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ gs_flatpak_claim_app (self, new);
|
||||
+
|
||||
+ /* The appstream plugin did not find the component in the plugin's cache,
|
||||
+ thus read the required info from the 'bundle' element. */
|
||||
+ if (gs_flatpak_app_get_ref_name (new) == NULL ||
|
||||
+ gs_flatpak_app_get_ref_arch (new) == NULL) {
|
||||
+ const gchar *xref_str = NULL;
|
||||
+ g_autoptr(XbNode) child = NULL;
|
||||
+ g_autoptr(XbNode) next = NULL;
|
||||
+ for (child = xb_node_get_child (component); child != NULL && xref_str == NULL;
|
||||
+ g_object_unref (child), child = g_steal_pointer (&next)) {
|
||||
+ next = xb_node_get_next (child);
|
||||
+ if (g_strcmp0 (xb_node_get_element (child), "bundle") == 0 &&
|
||||
+ g_strcmp0 (xb_node_get_attr (child, "type"), "flatpak") == 0) {
|
||||
+ xref_str = xb_node_get_text (child);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
- if (xref_str != NULL) {
|
||||
- g_auto(GStrv) split = NULL;
|
||||
-
|
||||
- /* get the kind/name/arch/branch */
|
||||
- split = g_strsplit (xref_str, "/", -1);
|
||||
- if (g_strv_length (split) == 4) {
|
||||
- const gchar *comp_type = xb_node_get_attr (component, "type");
|
||||
- AsComponentKind kind = as_component_kind_from_string (comp_type);
|
||||
- if (kind != AS_COMPONENT_KIND_UNKNOWN)
|
||||
- gs_app_set_kind (new, kind);
|
||||
- else if (g_ascii_strcasecmp (split[0], "app") == 0)
|
||||
- gs_app_set_kind (new, AS_COMPONENT_KIND_DESKTOP_APP);
|
||||
- else if (g_ascii_strcasecmp (split[0], "runtime") == 0)
|
||||
- gs_flatpak_set_runtime_kind_from_id (new);
|
||||
- gs_flatpak_app_set_ref_name (new, split[1]);
|
||||
- gs_flatpak_app_set_ref_arch (new, split[2]);
|
||||
- gs_app_set_branch (new, split[3]);
|
||||
- gs_app_set_metadata (new, "GnomeSoftware::packagename-value", xref_str);
|
||||
+ if (xref_str != NULL) {
|
||||
+ g_auto(GStrv) split = NULL;
|
||||
+
|
||||
+ /* get the kind/name/arch/branch */
|
||||
+ split = g_strsplit (xref_str, "/", -1);
|
||||
+ if (g_strv_length (split) == 4) {
|
||||
+ const gchar *comp_type = xb_node_get_attr (component, "type");
|
||||
+ AsComponentKind kind = as_component_kind_from_string (comp_type);
|
||||
+ if (kind != AS_COMPONENT_KIND_UNKNOWN)
|
||||
+ gs_app_set_kind (new, kind);
|
||||
+ else if (g_ascii_strcasecmp (split[0], "app") == 0)
|
||||
+ gs_app_set_kind (new, AS_COMPONENT_KIND_DESKTOP_APP);
|
||||
+ else if (g_ascii_strcasecmp (split[0], "runtime") == 0)
|
||||
+ gs_flatpak_set_runtime_kind_from_id (new);
|
||||
+ gs_flatpak_app_set_ref_name (new, split[1]);
|
||||
+ gs_flatpak_app_set_ref_arch (new, split[2]);
|
||||
+ gs_app_set_branch (new, split[3]);
|
||||
+ gs_app_set_metadata (new, "GnomeSoftware::packagename-value", xref_str);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
- }
|
||||
|
||||
- if (gs_flatpak_app_get_ref_name (new) == NULL ||
|
||||
- gs_flatpak_app_get_ref_arch (new) == NULL) {
|
||||
- g_debug ("Failed to get ref info for '%s' from wildcard '%s', skipping it...", gs_app_get_id (new), id);
|
||||
- } else {
|
||||
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardRefineNewApp, "Flatpak (refine new app)", NULL);
|
||||
- if (!gs_flatpak_refine_app_internal (self, new, require_flags, interactive, FALSE, *inout_components_by_bundle,
|
||||
- silo, silo_filename, silo_installed_by_desktopid, cancellable, error))
|
||||
- return FALSE;
|
||||
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardRefineNewApp);
|
||||
+ if (gs_flatpak_app_get_ref_name (new) == NULL ||
|
||||
+ gs_flatpak_app_get_ref_arch (new) == NULL) {
|
||||
+ g_debug ("Failed to get ref info for '%s' from wildcard '%s', skipping it...", gs_app_get_id (new), id);
|
||||
+ } else {
|
||||
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardRefineNewApp, "Flatpak (refine new app)", NULL);
|
||||
+ if (!gs_flatpak_refine_app_internal (self, new, require_flags, interactive, FALSE, components_by_bundle,
|
||||
+ silo, silo_filename, silo_installed_by_desktopid, cancellable, error))
|
||||
+ return FALSE;
|
||||
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardRefineNewApp);
|
||||
|
||||
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardSubsumeMetadata, "Flatpak (subsume metadata)", NULL);
|
||||
- gs_app_subsume_metadata (new, app);
|
||||
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardSubsumeMetadata);
|
||||
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardSubsumeMetadata, "Flatpak (subsume metadata)", NULL);
|
||||
+ gs_app_subsume_metadata (new, app);
|
||||
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardSubsumeMetadata);
|
||||
|
||||
- gs_app_list_add (list, new);
|
||||
+ gs_app_list_add (list, new);
|
||||
+ }
|
||||
}
|
||||
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardGenerateApps);
|
||||
}
|
||||
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardGenerateApps);
|
||||
|
||||
GS_PROFILER_END_SCOPED (FlatpakRefineWildcard);
|
||||
|
||||
diff --git a/plugins/flatpak/gs-flatpak.h b/plugins/flatpak/gs-flatpak.h
|
||||
index 34e1416b5..1f7d35a8f 100644
|
||||
--- a/plugins/flatpak/gs-flatpak.h
|
||||
+++ b/plugins/flatpak/gs-flatpak.h
|
||||
@@ -104,16 +104,11 @@ gboolean gs_flatpak_refine_app_state (GsFlatpak *self,
|
||||
void *event_user_data,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
-gboolean gs_flatpak_refine_wildcard (GsFlatpak *self,
|
||||
- GsApp *app,
|
||||
+gboolean gs_flatpak_refine_wildcards (GsFlatpak *self,
|
||||
+ GPtrArray *wildcard_apps,
|
||||
GsAppList *list,
|
||||
GsPluginRefineRequireFlags require_flags,
|
||||
gboolean interactive,
|
||||
- XbSilo **inout_silo,
|
||||
- gchar **inout_silo_filename,
|
||||
- GHashTable **inout_installed_by_desktopid,
|
||||
- GHashTable **inout_components_by_id,
|
||||
- GHashTable **inout_components_by_bundle,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean gs_flatpak_launch (GsFlatpak *self,
|
||||
diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c
|
||||
index f5d4a1d67..c06b1fb5f 100644
|
||||
--- a/plugins/flatpak/gs-plugin-flatpak.c
|
||||
+++ b/plugins/flatpak/gs-plugin-flatpak.c
|
||||
@@ -667,31 +667,6 @@ gs_plugin_flatpak_refine_app (GsPluginFlatpak *self,
|
||||
return gs_flatpak_refine_app (flatpak, app, require_flags, interactive, FALSE, event_callback, event_user_data, cancellable, error);
|
||||
}
|
||||
|
||||
-typedef struct {
|
||||
- XbSilo *silo;
|
||||
- gchar *silo_filename;
|
||||
- GHashTable *installed_by_desktopid;
|
||||
- GHashTable *components_by_id;
|
||||
- GHashTable *components_by_bundle;
|
||||
-} RefineInstallationData;
|
||||
-
|
||||
-static void
|
||||
-refine_installation_data_free (gpointer ptr)
|
||||
-{
|
||||
- RefineInstallationData *data = ptr;
|
||||
-
|
||||
- if (data == NULL)
|
||||
- return;
|
||||
-
|
||||
- g_clear_pointer (&data->silo_filename, g_free);
|
||||
- g_clear_pointer (&data->installed_by_desktopid, g_hash_table_unref);
|
||||
- g_clear_pointer (&data->components_by_id, g_hash_table_unref);
|
||||
- g_clear_pointer (&data->components_by_bundle, g_hash_table_unref);
|
||||
- /* free the silo as the last, just in case, because the data from it is in the above hash tables */
|
||||
- g_clear_object (&data->silo);
|
||||
- g_free (data);
|
||||
-}
|
||||
-
|
||||
static gboolean
|
||||
refine_app (GsPluginFlatpak *self,
|
||||
GsApp *app,
|
||||
@@ -778,8 +753,7 @@ refine_thread_cb (GTask *task,
|
||||
gboolean interactive = (data->job_flags & GS_PLUGIN_REFINE_FLAGS_INTERACTIVE) != 0;
|
||||
GsPluginEventCallback event_callback = data->event_callback;
|
||||
void *event_user_data = data->event_user_data;
|
||||
- g_autoptr(GPtrArray) installation_data = NULL; /* (element-type RefineInstallationData) */
|
||||
- g_autoptr(GsAppList) app_list = NULL;
|
||||
+ g_autoptr(GPtrArray) wildcard_apps = g_ptr_array_new_with_free_func (g_object_unref); /* (element-type GsApp) (owned) */
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
|
||||
assert_in_worker (self);
|
||||
@@ -790,38 +764,17 @@ refine_thread_cb (GTask *task,
|
||||
g_task_return_error (task, g_steal_pointer (&local_error));
|
||||
return;
|
||||
}
|
||||
- }
|
||||
-
|
||||
- /* Refine wildcards.
|
||||
- *
|
||||
- * Use a copy of the list for the loop because a function called
|
||||
- * on the plugin may affect the list which can lead to problems
|
||||
- * (e.g. inserting an app in the list on every call results in
|
||||
- * an infinite loop) */
|
||||
- app_list = gs_app_list_copy (list);
|
||||
-
|
||||
- installation_data = g_ptr_array_new_full (self->installations->len, refine_installation_data_free);
|
||||
- g_ptr_array_set_size (installation_data, self->installations->len);
|
||||
-
|
||||
- for (guint j = 0; j < gs_app_list_length (app_list); j++) {
|
||||
- GsApp *app = gs_app_list_index (app_list, j);
|
||||
|
||||
- if (!gs_app_has_quirk (app, GS_APP_QUIRK_IS_WILDCARD))
|
||||
- continue;
|
||||
+ if (gs_app_has_quirk (app, GS_APP_QUIRK_IS_WILDCARD) && gs_app_get_id (app) != NULL)
|
||||
+ g_ptr_array_add (wildcard_apps, g_object_ref (app));
|
||||
+ }
|
||||
|
||||
+ /* Refine wildcards. */
|
||||
+ if (wildcard_apps->len > 0) {
|
||||
for (guint i = 0; i < self->installations->len; i++) {
|
||||
GsFlatpak *flatpak = g_ptr_array_index (self->installations, i);
|
||||
- RefineInstallationData *inst_data = g_ptr_array_index (installation_data, i);
|
||||
-
|
||||
- if (inst_data == NULL) {
|
||||
- inst_data = g_new0 (RefineInstallationData, 1);
|
||||
- installation_data->pdata[i] = inst_data;
|
||||
- }
|
||||
|
||||
- if (!gs_flatpak_refine_wildcard (flatpak, app, list, require_flags, interactive, &inst_data->silo,
|
||||
- &inst_data->silo_filename, &inst_data->installed_by_desktopid,
|
||||
- &inst_data->components_by_id, &inst_data->components_by_bundle,
|
||||
- cancellable, &local_error)) {
|
||||
+ if (!gs_flatpak_refine_wildcards (flatpak, wildcard_apps, list, require_flags, interactive, cancellable, &local_error)) {
|
||||
g_task_return_error (task, g_steal_pointer (&local_error));
|
||||
return;
|
||||
}
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From 8472d717356a801e6c0171156738ea48480fa695 Mon Sep 17 00:00:00 2001
|
||||
Date: Wed, 7 Jan 2026 18:45:47 +0100
|
||||
Subject: [PATCH 3/3] flatpak: Hold silo lock when refining wildcard apps
|
||||
|
||||
The refine can take a long time, thus hold the silo lock to not have
|
||||
it invalidated from another thread. Object reference is not enough
|
||||
for the XbSilo, it breaks as soon as the underlying file changes.
|
||||
---
|
||||
plugins/flatpak/gs-flatpak.c | 16 +++++++++++-----
|
||||
1 file changed, 11 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
|
||||
index 782b0bb48..c5437125d 100644
|
||||
--- a/plugins/flatpak/gs-flatpak.c
|
||||
+++ b/plugins/flatpak/gs-flatpak.c
|
||||
@@ -59,7 +59,7 @@ struct _GsFlatpak {
|
||||
AsComponentScope scope;
|
||||
GsPlugin *plugin;
|
||||
XbSilo *silo;
|
||||
- GMutex silo_lock;
|
||||
+ GRecMutex silo_lock;
|
||||
gchar *silo_filename;
|
||||
GHashTable *silo_installed_by_desktopid;
|
||||
gint silo_change_stamp;
|
||||
@@ -1187,11 +1187,11 @@ gs_flatpak_ref_silo (GsFlatpak *self,
|
||||
g_autoptr(GFile) file = NULL;
|
||||
g_autoptr(GPtrArray) xremotes = NULL;
|
||||
g_autoptr(GPtrArray) desktop_paths = NULL;
|
||||
- g_autoptr(GMutexLocker) locker = NULL;
|
||||
+ g_autoptr(GRecMutexLocker) locker = NULL;
|
||||
g_autoptr(XbBuilder) builder = NULL;
|
||||
g_autoptr(GMainContext) old_thread_default = NULL;
|
||||
|
||||
- locker = g_mutex_locker_new (&self->silo_lock);
|
||||
+ locker = g_rec_mutex_locker_new (&self->silo_lock);
|
||||
/* everything is okay */
|
||||
if (self->silo != NULL && xb_silo_is_valid (self->silo) &&
|
||||
g_atomic_int_get (&self->silo_change_stamp_current) == g_atomic_int_get (&self->silo_change_stamp)) {
|
||||
@@ -3754,6 +3754,7 @@ gs_flatpak_refine_wildcards (GsFlatpak *self,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
+ g_autoptr(GRecMutexLocker) silo_locker = NULL;
|
||||
g_autoptr(XbSilo) silo = NULL;
|
||||
g_autoptr(GHashTable) silo_installed_by_desktopid = NULL;
|
||||
g_autoptr(GHashTable) components_by_id = NULL;
|
||||
@@ -3764,6 +3765,11 @@ gs_flatpak_refine_wildcards (GsFlatpak *self,
|
||||
|
||||
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcard, "Flatpak (refine wildcard)", NULL);
|
||||
|
||||
+ /* the refine can take a long time, thus hold the silo lock to not have
|
||||
+ it invalidated from another thread; object reference is not enough
|
||||
+ for the XbSilo, it breaks as soon as the underlying file changes */
|
||||
+ silo_locker = g_rec_mutex_locker_new (&self->silo_lock);
|
||||
+
|
||||
silo = gs_flatpak_ref_silo (self, interactive, &silo_filename, &silo_installed_by_desktopid, cancellable, error);
|
||||
if (silo == NULL)
|
||||
return FALSE;
|
||||
@@ -4810,7 +4816,7 @@ gs_flatpak_finalize (GObject *object)
|
||||
g_object_unref (self->plugin);
|
||||
g_hash_table_unref (self->broken_remotes);
|
||||
g_mutex_clear (&self->broken_remotes_mutex);
|
||||
- g_mutex_clear (&self->silo_lock);
|
||||
+ g_rec_mutex_clear (&self->silo_lock);
|
||||
g_hash_table_unref (self->app_silos);
|
||||
g_mutex_clear (&self->app_silos_mutex);
|
||||
g_clear_pointer (&self->remote_title, g_hash_table_unref);
|
||||
@@ -4831,7 +4837,7 @@ gs_flatpak_init (GsFlatpak *self)
|
||||
{
|
||||
/* XbSilo needs external locking as we destroy the silo and build a new
|
||||
* one when something changes */
|
||||
- g_mutex_init (&self->silo_lock);
|
||||
+ g_rec_mutex_init (&self->silo_lock);
|
||||
|
||||
g_mutex_init (&self->installed_refs_mutex);
|
||||
self->installed_refs = NULL;
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
# Disable DKMS/akmods support for RHEL builds
|
||||
%bcond dkms %[!0%{?rhel}]
|
||||
|
||||
%bcond packagekit 0
|
||||
%bcond dnf5 1
|
||||
%bcond packagekit 1
|
||||
%bcond dnf5 0
|
||||
|
||||
# this is not a library version
|
||||
%define gs_plugin_version 23
|
||||
|
|
@ -29,17 +29,22 @@
|
|||
%global __provides_exclude_from ^%{_libdir}/%{name}/plugins-%{gs_plugin_version}/.*\\.so.*$
|
||||
|
||||
Name: gnome-software
|
||||
Version: 49~beta
|
||||
Release: 3%{?dist}
|
||||
Version: 49.3
|
||||
Release: 1%{?dist}
|
||||
Summary: A software center for GNOME
|
||||
|
||||
License: GPL-2.0-or-later
|
||||
URL: https://apps.gnome.org/Software
|
||||
Source0: https://download.gnome.org/sources/gnome-software/49/%{name}-%{tarball_version}.tar.xz
|
||||
|
||||
%if %{with dnf5}
|
||||
# to update the patch enter the ./dnf5-plugin/ directory and run from
|
||||
# it the ./update-patch.sh script
|
||||
Patch: 0001-dnf5-plugin.patch
|
||||
%endif
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2416542
|
||||
Patch: 0002-rhbug2416542-crash-under-gs_flatpak_refine_wildcard.patch
|
||||
|
||||
# ostree and flatpak not on i686 for Fedora and RHEL 10
|
||||
# https://github.com/containers/composefs/pull/229#issuecomment-1838735764
|
||||
|
|
@ -158,7 +163,7 @@ This package includes the rpm-ostree backend.
|
|||
%endif
|
||||
|
||||
%prep
|
||||
%autosetup -p1 -S git -n %{name}-%{tarball_version}
|
||||
%autosetup -p1 -S gendiff -n %{name}-%{tarball_version}
|
||||
|
||||
%build
|
||||
%meson \
|
||||
|
|
@ -177,8 +182,6 @@ This package includes the rpm-ostree backend.
|
|||
%endif
|
||||
%if %{with dnf5}
|
||||
-Ddnf5=true \
|
||||
%else
|
||||
-Ddnf5=false \
|
||||
%endif
|
||||
-Dexternal_appstream=false \
|
||||
%if %{with rpmostree}
|
||||
|
|
|
|||
2
sources
2
sources
|
|
@ -1 +1 @@
|
|||
SHA512 (gnome-software-49.beta.tar.xz) = 9cb6d67216193840b2661871ef43da5e726a284d1164781f13423ee8dd86359334f199efc29f4b3a0b3eddfa8a3811d7dd38cd412fa53aaebb2e1c35ddc1f9df
|
||||
SHA512 (gnome-software-49.3.tar.xz) = 0414ea55ad3b83bcd50514985e3d2026207801c040934805bb26d162e88f0619a9d70aa6ba324a29acfab02573490b928c83594b54f57ec2a8ad00e6c127f657
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue