diff --git a/0001-Lower_glib_dependency_to_2_68.patch b/0001-Lower_glib_dependency_to_2_68.patch deleted file mode 100644 index 074dfa1..0000000 --- a/0001-Lower_glib_dependency_to_2_68.patch +++ /dev/null @@ -1,198 +0,0 @@ -diff --git a/lib/gs-fedora-third-party.c b/lib/gs-fedora-third-party.c -index e79bba8..9e7115a 100644 ---- a/lib/gs-fedora-third-party.c -+++ b/lib/gs-fedora-third-party.c -@@ -11,6 +11,10 @@ - - #include "gs-fedora-third-party.h" - -+#if !GLIB_CHECK_VERSION(2, 70, 0) -+#define g_spawn_check_wait_status g_spawn_check_exit_status -+#endif -+ - struct _GsFedoraThirdParty - { - GObject parent_instance; -diff --git a/lib/gs-icon-downloader.c b/lib/gs-icon-downloader.c -index a1a669c..577fda2 100644 ---- a/lib/gs-icon-downloader.c -+++ b/lib/gs-icon-downloader.c -@@ -41,7 +41,7 @@ struct _GsIconDownloader - GCancellable *cancellable; /* (owned) */ - }; - --G_DEFINE_FINAL_TYPE (GsIconDownloader, gs_icon_downloader, G_TYPE_OBJECT) -+G_DEFINE_TYPE (GsIconDownloader, gs_icon_downloader, G_TYPE_OBJECT) - - typedef enum { - PROP_MAXIMUM_SIZE = 1, -diff --git a/lib/gs-job-manager.c b/lib/gs-job-manager.c -index 98d79a7..694a157 100644 ---- a/lib/gs-job-manager.c -+++ b/lib/gs-job-manager.c -@@ -100,7 +100,9 @@ watch_data_unref (WatchData *data) - watch_free_data_cb, - g_steal_pointer (&data), - (GDestroyNotify) watch_data_unref); -+ #if GLIB_CHECK_VERSION(2, 70, 0) - g_source_set_static_name (idle_source, G_STRFUNC); -+ #endif - g_source_attach (idle_source, callback_context); - - /* Freeing will eventually happen in watch_free_data_cb(). */ -@@ -359,7 +361,9 @@ gs_job_manager_add_job (GsJobManager *self, - watch_call_handler_cb, - g_steal_pointer (&idle_data), - (GDestroyNotify) watch_call_handler_data_free); -+ #if GLIB_CHECK_VERSION(2, 70, 0) - g_source_set_static_name (idle_source, G_STRFUNC); -+ #endif - g_source_attach (idle_source, data->callback_context); - } - } -@@ -420,7 +424,9 @@ gs_job_manager_remove_job (GsJobManager *self, - watch_call_handler_cb, - g_steal_pointer (&idle_data), - (GDestroyNotify) watch_call_handler_data_free); -+ #if GLIB_CHECK_VERSION(2, 70, 0) - g_source_set_static_name (idle_source, G_STRFUNC); -+ #endif - g_source_attach (idle_source, data->callback_context); - } - } -diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c -index 93b33f3..204d55f 100644 ---- a/lib/gs-plugin-loader.c -+++ b/lib/gs-plugin-loader.c -@@ -1965,7 +1965,7 @@ get_session_bus_cb (GObject *object, - plugin_loader->session_bus_connection = g_bus_get_finish (result, &local_error); - if (plugin_loader->session_bus_connection == NULL) { - notify_setup_complete (plugin_loader); -- g_prefix_error_literal (&local_error, "Error getting session bus: "); -+ g_prefix_error (&local_error, "%s", "Error getting session bus: "); - g_task_return_error (task, g_steal_pointer (&local_error)); - return; - } -@@ -1987,7 +1987,7 @@ get_system_bus_cb (GObject *object, - plugin_loader->system_bus_connection = g_bus_get_finish (result, &local_error); - if (plugin_loader->system_bus_connection == NULL) { - notify_setup_complete (plugin_loader); -- g_prefix_error_literal (&local_error, "Error getting system bus: "); -+ g_prefix_error (&local_error, "%s", "Error getting system bus: "); - g_task_return_error (task, g_steal_pointer (&local_error)); - return; - } -@@ -2753,12 +2753,21 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader) - /* Set up a thread pool for running old-style jobs - * FIXME: This will eventually disappear when all jobs are ported to - * be subclasses of #GsPluginJob. */ -+ #if GLIB_CHECK_VERSION(2, 70, 0) - plugin_loader->old_api_thread_pool = g_thread_pool_new_full (gs_plugin_loader_process_old_api_job_cb, - plugin_loader, - (GDestroyNotify) g_object_unref, - 20, - FALSE, - NULL); -+ #else -+ /* pre-glib 2.70.0 - The items will leak when the thread pool is freed before all jobs are finished */ -+ plugin_loader->old_api_thread_pool = g_thread_pool_new (gs_plugin_loader_process_old_api_job_cb, -+ plugin_loader, -+ 20, -+ FALSE, -+ NULL); -+ #endif - - /* get the job manager */ - plugin_loader->job_manager = gs_job_manager_new (); -diff --git a/meson.build b/meson.build -index da9e7ac..4c847c9 100644 ---- a/meson.build -+++ b/meson.build -@@ -156,7 +156,7 @@ gtk = dependency('gtk4', - 'demos=false', - ] - ) --glib = dependency('glib-2.0', version : '>= 2.70.0') -+glib = dependency('glib-2.0', version : '>= 2.68.0') - json_glib = dependency('json-glib-1.0', version : '>= 1.6.0') - libm = cc.find_library('m', required: false) - if get_option('soup2') -diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c -index c84db84..009a425 100644 ---- a/plugins/flatpak/gs-flatpak.c -+++ b/plugins/flatpak/gs-flatpak.c -@@ -4738,7 +4738,7 @@ gs_flatpak_purge_sync (GsFlatpak *self, - g_autoptr(FlatpakTransaction) transaction = NULL; - transaction = gs_flatpak_transaction_new (installation, GS_FLATPAK_ERROR_MODE_STOP_ON_FIRST_ERROR, cancellable, error); - if (transaction == NULL) { -- g_prefix_error_literal (error, "failed to build transaction: "); -+ g_prefix_error (error, "%s", "failed to build transaction: "); - return FALSE; - } - flatpak_transaction_set_no_interaction (transaction, TRUE); -diff --git a/plugins/fwupd/gs-plugin-fwupd.c b/plugins/fwupd/gs-plugin-fwupd.c -index e931b2b..43c4e9f 100644 ---- a/plugins/fwupd/gs-plugin-fwupd.c -+++ b/plugins/fwupd/gs-plugin-fwupd.c -@@ -1653,7 +1653,7 @@ finish_update_apps_op (GTask *task, - g_autoptr(GsPluginEvent) event = NULL; - - event_error = g_error_copy (error_owned); -- g_prefix_error_literal (&event_error, _("Firmware update could not be applied: ")); -+ g_prefix_error (&event_error, "%s", _("Firmware update could not be applied: ")); - gs_plugin_fwupd_error_convert (&event_error); - - event = gs_plugin_event_new ("app", self->app_current, -diff --git a/plugins/packagekit/gs-plugin-packagekit.c b/plugins/packagekit/gs-plugin-packagekit.c -index 3c5f926..409e831 100644 ---- a/plugins/packagekit/gs-plugin-packagekit.c -+++ b/plugins/packagekit/gs-plugin-packagekit.c -@@ -2040,7 +2040,7 @@ search_files_cb (GObject *source_object, - results = pk_client_generic_finish (client, result, &local_error); - - if (!gs_plugin_packagekit_results_valid (results, g_task_get_cancellable (refine_task), &local_error)) { -- g_prefix_error_literal (&local_error, "failed to search files: "); -+ g_prefix_error (&local_error, "%s", "failed to search files: "); - refine_task_complete_operation_with_error (refine_task, g_steal_pointer (&local_error)); - return; - } -@@ -3071,7 +3071,7 @@ gs_plugin_packagekit_convert_error (GError **error, - break; - } - if (prefix != NULL) -- g_prefix_error_literal (error, prefix); -+ g_prefix_error (error, "%s", prefix); - return FALSE; - } - -diff --git a/src/gs-common.c b/src/gs-common.c -index 997025a..d665c98 100644 ---- a/src/gs-common.c -+++ b/src/gs-common.c -@@ -1027,7 +1027,7 @@ gs_utils_invoke_reboot_ready2_got_session_bus_cb (GObject *source_object, - bus = g_bus_get_finish (result, &local_error); - if (bus == NULL) { - g_dbus_error_strip_remote_error (local_error); -- g_prefix_error_literal (&local_error, "Failed to get D-Bus session bus: "); -+ g_prefix_error (&local_error, "%s", "Failed to get D-Bus session bus: "); - g_task_return_error (task, g_steal_pointer (&local_error)); - return; - } -@@ -1098,7 +1098,7 @@ gs_utils_invoke_reboot_ready1_got_system_bus_cb (GObject *source_object, - bus = g_bus_get_finish (result, &local_error); - if (bus == NULL) { - g_dbus_error_strip_remote_error (local_error); -- g_prefix_error_literal (&local_error, "Failed to get D-Bus system bus: "); -+ g_prefix_error (&local_error, "%s", "Failed to get D-Bus system bus: "); - g_task_return_error (task, g_steal_pointer (&local_error)); - return; - } -@@ -1171,7 +1171,7 @@ gs_utils_invoke_reboot_got_session_bus_cb (GObject *source_object, - bus = g_bus_get_finish (result, &local_error); - if (bus == NULL) { - g_dbus_error_strip_remote_error (local_error); -- g_prefix_error_literal (&local_error, "Failed to get D-Bus session bus: "); -+ g_prefix_error (&local_error, "%s", "Failed to get D-Bus session bus: "); - g_task_return_error (task, g_steal_pointer (&local_error)); - return; - } diff --git a/0001-crash-with-broken-theme.patch b/0001-crash-with-broken-theme.patch new file mode 100644 index 0000000..fd37e80 --- /dev/null +++ b/0001-crash-with-broken-theme.patch @@ -0,0 +1,48 @@ +From 3a644c151f27f439c36170f0958fd21cf1cc54d0 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Thu, 3 Jun 2021 08:33:53 +0200 +Subject: [PATCH] gs-feature-tile: Do not abort when the theme is broken + +Just print a warning when the theme doesn't provide 'theme_fg_color' and +fallback to black color. + +Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1228 +--- + src/gs-feature-tile.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/src/gs-feature-tile.c b/src/gs-feature-tile.c +index 1c85083eb..158af1e56 100644 +--- a/src/gs-feature-tile.c ++++ b/src/gs-feature-tile.c +@@ -268,7 +268,6 @@ gs_feature_tile_refresh (GsAppTile *self) + if (key_colors != tile->key_colors_cache) { + g_autoptr(GArray) colors = NULL; + GdkRGBA fg_rgba; +- gboolean fg_rgba_valid; + GsHSBC fg_hsbc; + + /* Look up the foreground colour for the feature tile, +@@ -283,8 +282,17 @@ gs_feature_tile_refresh (GsAppTile *self) + * @min_abs_contrast contrast with the foreground, so + * that the text is legible. + */ +- fg_rgba_valid = gtk_style_context_lookup_color (context, "theme_fg_color", &fg_rgba); +- g_assert (fg_rgba_valid); ++ if (!gtk_style_context_lookup_color (context, "theme_fg_color", &fg_rgba)) { ++ static gboolean i_know = FALSE; ++ if (!i_know) { ++ i_know = TRUE; ++ g_warning ("The theme doesn't provide 'theme_fg_color', fallbacking to black"); ++ } ++ fg_rgba.red = 0.0; ++ fg_rgba.green = 0.0; ++ fg_rgba.blue = 0.0; ++ fg_rgba.alpha = 1.0; ++ } + + gtk_rgb_to_hsv (fg_rgba.red, fg_rgba.green, fg_rgba.blue, + &fg_hsbc.hue, &fg_hsbc.saturation, &fg_hsbc.brightness); +-- +GitLab + diff --git a/0002-Lower-pango-attributes.patch b/0002-Lower-pango-attributes.patch deleted file mode 100644 index f740e21..0000000 --- a/0002-Lower-pango-attributes.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff -up gnome-software-45.2/src/gs-origin-popover-row.ui.2 gnome-software-45.2/src/gs-origin-popover-row.ui ---- gnome-software-45.2/src/gs-origin-popover-row.ui.2 2023-12-08 10:14:07.848934874 +0100 -+++ gnome-software-45.2/src/gs-origin-popover-row.ui 2023-12-08 10:14:10.045961688 +0100 -@@ -79,7 +79,7 @@ - 2 - - -- -+ - - - -@@ -110,7 +110,7 @@ - 2 - - -- -+ - - - -@@ -140,7 +140,7 @@ - 2 - - -- -+ - - - -diff -up gnome-software-45.2/src/gs-review-histogram.ui.2 gnome-software-45.2/src/gs-review-histogram.ui ---- gnome-software-45.2/src/gs-review-histogram.ui.2 2023-12-08 10:15:28.246916110 +0100 -+++ gnome-software-45.2/src/gs-review-histogram.ui 2023-12-01 09:58:33.000000000 +0100 -@@ -18,7 +18,7 @@ - - - -- -+ - - - 0 diff --git a/0003-Verify-category-sizes.patch b/0003-Verify-category-sizes.patch deleted file mode 100644 index 09b9357..0000000 --- a/0003-Verify-category-sizes.patch +++ /dev/null @@ -1,335 +0,0 @@ -From f7e394840ff84ae8b55f13ff9692d6b02e8e6ea5 Mon Sep 17 00:00:00 2001 -Date: Wed, 20 Dec 2023 12:21:24 +0100 -Subject: [PATCH 1/3] gs-appstream: Increase limit to category apps lookup - -The Overview page currently checks for 100 apps in all categories. -Lookup for the same count per category. - -Note: The counts are not accurate, same apps can be in multiple -sub-categories, thus the parent category count suffers of duplicity, -which the following commit will correct in a different way than -checking for id duplicity. ---- - lib/gs-appstream.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/lib/gs-appstream.c b/lib/gs-appstream.c -index f110e3c47..d600cac53 100644 ---- a/lib/gs-appstream.c -+++ b/lib/gs-appstream.c -@@ -1836,7 +1836,8 @@ static guint - gs_appstream_count_component_for_groups (XbSilo *silo, - const gchar *desktop_group) - { -- guint limit = 10; -+ /* the overview page checks for 100 apps, then try to get them */ -+ const guint limit = 100; - g_autofree gchar *xpath = NULL; - g_auto(GStrv) split = g_strsplit (desktop_group, "::", -1); - g_autoptr(GPtrArray) array = NULL; -@@ -1896,7 +1897,6 @@ gs_appstream_refine_category_sizes (XbSilo *silo, - } - } - } -- continue; - } - return TRUE; - } --- -GitLab - - -From 617af44a56f6f62e07fd3fc13ae43d688aa3b85f Mon Sep 17 00:00:00 2001 -Date: Wed, 20 Dec 2023 12:24:25 +0100 -Subject: [PATCH 2/3] gs-overview-page: Add debug prints about discovered - categories - -For easier debugging, to see what the plugins returned. ---- - src/gs-overview-page.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c -index 6ef5079e9..72000e257 100644 ---- a/src/gs-overview-page.c -+++ b/src/gs-overview-page.c -@@ -496,6 +496,7 @@ gs_overview_page_get_categories_cb (GObject *source_object, - - if (gs_category_get_icon_name (cat) != NULL) { - found_apps_cnt += gs_category_get_size (cat); -+ g_debug ("overview page found category '%s' which claims %u apps", gs_category_get_name (cat), gs_category_get_size (cat)); - flowbox = GTK_FLOW_BOX (self->flowbox_categories); - } else - flowbox = GTK_FLOW_BOX (self->flowbox_iconless_categories); -@@ -524,6 +525,7 @@ out: - * See https://gitlab.gnome.org/GNOME/gnome-software/-/issues/2053 */ - gtk_widget_set_visible (self->flowbox_categories, found_apps_cnt >= MIN_CATEGORIES_APPS); - -+ g_debug ("overview page found %u category apps", found_apps_cnt); - if (found_apps_cnt < MIN_CATEGORIES_APPS && found_apps_cnt > 0) { - GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; - GatherAppsData *gather_apps_data = g_new0 (GatherAppsData, 1); --- -GitLab - - -From 98086eca23dbd46284039722887852e8c760a0fe Mon Sep 17 00:00:00 2001 -Date: Wed, 20 Dec 2023 12:32:21 +0100 -Subject: [PATCH 3/3] gs-overview-page: Verify category sizes - -The "list-categories" job can set inaccurate sizes for the categories, -thus check the actual category content to operate with proper numbers. -For example the appstream data can have information about apps, which -no plugin can provide due to disabled repository. ---- - src/gs-overview-page.c | 176 +++++++++++++++++++++++++++++++++++------ - 1 file changed, 153 insertions(+), 23 deletions(-) - -diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c -index 72000e257..3ec689ac1 100644 ---- a/src/gs-overview-page.c -+++ b/src/gs-overview-page.c -@@ -440,6 +440,7 @@ category_activated_cb (GsOverviewPage *self, GsCategoryTile *tile) - typedef struct { - GsOverviewPage *page; /* (unowned) */ - GsPluginJobListCategories *job; /* (owned) */ -+ guint n_pending_ops; - } GetCategoriesData; - - static void -@@ -451,31 +452,18 @@ get_categories_data_free (GetCategoriesData *data) - - G_DEFINE_AUTOPTR_CLEANUP_FUNC (GetCategoriesData, get_categories_data_free) - --static void --gs_overview_page_get_categories_cb (GObject *source_object, -- GAsyncResult *res, -- gpointer user_data) -+static guint -+update_categories_sections (GsOverviewPage *self, -+ GPtrArray *list) /* (element-type GsCategory) */ - { -- g_autoptr(GetCategoriesData) data = g_steal_pointer (&user_data); -- GsOverviewPage *self = GS_OVERVIEW_PAGE (data->page); -- GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object); -- guint i; - GsCategory *cat; - GtkFlowBox *flowbox; - GtkWidget *tile; - guint added_cnt = 0; - guint found_apps_cnt = 0; -- g_autoptr(GError) error = NULL; -- GPtrArray *list = NULL; /* (element-type GsCategory) */ - -- if (!gs_plugin_loader_job_action_finish (plugin_loader, res, &error)) { -- if (!g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) && -- !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) -- g_warning ("failed to get categories: %s", error->message); -- goto out; -- } -- -- list = gs_plugin_job_list_categories_get_result_list (data->job); -+ if (g_cancellable_is_cancelled (self->cancellable)) -+ return found_apps_cnt; - - gs_widget_remove_all (self->flowbox_categories, (GsRemoveFunc) gtk_flow_box_remove); - gs_widget_remove_all (self->flowbox_iconless_categories, (GsRemoveFunc) gtk_flow_box_remove); -@@ -488,7 +476,7 @@ gs_overview_page_get_categories_cb (GObject *source_object, - * be visually important, and are listed near the top of the page. - * Categories without icons are listed in a separate flowbox at the - * bottom of the page. Typically they are addons. */ -- for (i = 0; i < list->len; i++) { -+ for (guint i = 0; list != NULL && i < list->len; i++) { - cat = GS_CATEGORY (g_ptr_array_index (list, i)); - if (gs_category_get_size (cat) == 0) - continue; -@@ -510,7 +498,6 @@ gs_overview_page_get_categories_cb (GObject *source_object, - g_object_ref (cat)); - } - --out: - /* Show the heading for the iconless categories iff there are any. */ - gtk_widget_set_visible (self->iconless_categories_heading, - gtk_flow_box_get_child_at_index (GTK_FLOW_BOX (self->flowbox_iconless_categories), 0) != NULL); -@@ -525,6 +512,27 @@ out: - * See https://gitlab.gnome.org/GNOME/gnome-software/-/issues/2053 */ - gtk_widget_set_visible (self->flowbox_categories, found_apps_cnt >= MIN_CATEGORIES_APPS); - -+ return found_apps_cnt; -+} -+ -+static void -+finish_verify_category_op (GetCategoriesData *op_data) -+{ -+ g_autoptr(GetCategoriesData) data = g_steal_pointer (&op_data); -+ GsOverviewPage *self = GS_OVERVIEW_PAGE (data->page); -+ guint i, found_apps_cnt; -+ GPtrArray *list; /* (element-type GsCategory) */ -+ -+ data->n_pending_ops--; -+ if (data->n_pending_ops > 0) { -+ /* to not be freed */ -+ g_steal_pointer (&data); -+ return; -+ } -+ -+ list = gs_plugin_job_list_categories_get_result_list (data->job); -+ found_apps_cnt = update_categories_sections (self, list); -+ - g_debug ("overview page found %u category apps", found_apps_cnt); - if (found_apps_cnt < MIN_CATEGORIES_APPS && found_apps_cnt > 0) { - GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; -@@ -534,10 +542,10 @@ out: - gather_apps_data->self = g_object_ref (self); - gather_apps_data->list = gs_app_list_new (); - -- for (i = 0; i < list->len; i++) { -+ for (i = 0; list != NULL && i < list->len; i++) { - g_autoptr(GsPluginJob) plugin_job = NULL; - g_autoptr(GsAppQuery) query = NULL; -- GsCategory *subcat; -+ GsCategory *cat, *subcat; - - cat = GS_CATEGORY (g_ptr_array_index (list, i)); - if (gs_category_get_size (cat) == 0 || -@@ -578,6 +586,128 @@ out: - gs_overview_page_decrement_action_cnt (self); - } - -+typedef struct { -+ GsOverviewPage *page; /* (unowned) */ -+ GetCategoriesData *op_data; /* (unowned) */ -+ GsCategory *category; /* (owned) */ -+} VerifyCategoryData; -+ -+static void -+verify_category_data_free (VerifyCategoryData *data) -+{ -+ g_clear_object (&data->category); -+ g_free (data); -+} -+ -+G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyCategoryData, verify_category_data_free) -+ -+static void -+gs_overview_page_verify_category_cb (GObject *source_object, -+ GAsyncResult *res, -+ gpointer user_data) -+{ -+ g_autoptr(VerifyCategoryData) data = user_data; -+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object); -+ g_autoptr(GError) local_error = NULL; -+ g_autoptr(GsAppList) list = NULL; -+ -+ list = gs_plugin_loader_job_process_finish (plugin_loader, res, &local_error); -+ if (list == NULL) { -+ if (!g_error_matches (local_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) && -+ !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) -+ g_warning ("failed to get apps for category: %s", local_error->message); -+ g_debug ("Failed to get category content '%s' for overview page: %s", gs_category_get_id (data->category), local_error->message); -+ } else { -+ GsCategory *all_subcat = gs_category_find_child (data->category, "all"); -+ guint size = gs_app_list_length (list); -+ g_debug ("overview page verify category '%s' size:%u~>%u subcat:'%s' size:%u~>%u", -+ gs_category_get_id (data->category), gs_category_get_size (data->category), size, -+ gs_category_get_id (all_subcat), gs_category_get_size (all_subcat), size); -+ gs_category_set_size (data->category, size); -+ gs_category_set_size (all_subcat, size); -+ } -+ -+ finish_verify_category_op (data->op_data); -+} -+ -+static void -+gs_overview_page_get_categories_list_cb (GObject *source_object, -+ GAsyncResult *res, -+ gpointer user_data) -+{ -+ g_autoptr(GetCategoriesData) data = g_steal_pointer (&user_data); -+ GsOverviewPage *self = GS_OVERVIEW_PAGE (data->page); -+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object); -+ g_autoptr(GError) error = NULL; -+ -+ g_assert (data->n_pending_ops == 0); -+ -+ data->n_pending_ops++; -+ -+ /* The apps can be mentioned in the appstream data, but no plugin may provide actual app, -+ thus try to get the content as the Categories page and fine tune the numbers appropriately. */ -+ if (!gs_plugin_loader_job_action_finish (plugin_loader, res, &error)) { -+ if (!g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) && -+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) -+ g_warning ("failed to get categories: %s", error->message); -+ } else { -+ g_autoptr(GPtrArray) verify_categories = NULL; /* (element-type GsCategory) */ -+ GPtrArray *list = NULL; /* (element-type GsCategory) */ -+ guint found_apps_cnt; -+ -+ list = gs_plugin_job_list_categories_get_result_list (data->job); -+ found_apps_cnt = update_categories_sections (self, list); -+ -+ if (found_apps_cnt >= MIN_CATEGORIES_APPS) { -+ verify_categories = g_ptr_array_new_full (list != NULL ? list->len : 0, g_object_unref); -+ for (guint i = 0; list != NULL && i < list->len; i++) { -+ GsCategory *category = g_ptr_array_index (list, i); -+ if (gs_category_get_size (category) > 0 && -+ gs_category_find_child (category, "all") != NULL) { -+ g_ptr_array_add (verify_categories, g_object_ref (category)); -+ } -+ } -+ } -+ -+ if (verify_categories != NULL && verify_categories->len > 0 && !g_cancellable_is_cancelled (self->cancellable)) { -+ for (guint i = 0; i < verify_categories->len; i++) { -+ GsCategory *category = g_ptr_array_index (verify_categories, i); -+ GsCategory *all_subcat = gs_category_find_child (category, "all"); -+ g_autoptr(GsAppQuery) query = NULL; -+ g_autoptr(GsPluginJob) plugin_job = NULL; -+ VerifyCategoryData *ver_data; -+ -+ g_assert (all_subcat != NULL); -+ -+ data->n_pending_ops++; -+ -+ ver_data = g_new0 (VerifyCategoryData, 1); -+ ver_data->page = self; -+ ver_data->op_data = data; -+ ver_data->category = g_object_ref (category); -+ -+ query = gs_app_query_new ("category", all_subcat, -+ "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ID, -+ "dedupe-flags", GS_APP_LIST_FILTER_FLAG_KEY_ID_PROVIDES, -+ "license-type", gs_page_get_query_license_type (GS_PAGE (self)), -+ /*"developer-verified-type", gs_page_get_query_developer_verified_type (GS_PAGE (self)),*/ -+ NULL); -+ plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE); -+ gs_plugin_loader_job_process_async (plugin_loader, -+ plugin_job, -+ self->cancellable, -+ gs_overview_page_verify_category_cb, -+ ver_data); -+ } -+ -+ finish_verify_category_op (g_steal_pointer (&data)); -+ return; -+ } -+ } -+ -+ finish_verify_category_op (g_steal_pointer (&data)); -+} -+ - static void - third_party_destroy_cb (GtkWindow *window, - GsOverviewPage *self) -@@ -967,7 +1097,7 @@ gs_overview_page_load (GsOverviewPage *self) - data->job = g_object_ref (GS_PLUGIN_JOB_LIST_CATEGORIES (plugin_job)); - - gs_plugin_loader_job_process_async (self->plugin_loader, plugin_job, -- self->cancellable, gs_overview_page_get_categories_cb, -+ self->cancellable, gs_overview_page_get_categories_list_cb, - g_steal_pointer (&data)); - self->action_cnt++; - } --- -GitLab - diff --git a/0006-optional-repos-cannot-be-disabled.patch b/0006-optional-repos-cannot-be-disabled.patch new file mode 100644 index 0000000..b581147 --- /dev/null +++ b/0006-optional-repos-cannot-be-disabled.patch @@ -0,0 +1,498 @@ +From dca731ff0daf904911dd6815fb9a1b181329c887 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Tue, 5 Oct 2021 11:00:20 +0200 +Subject: [PATCH 1/4] gs-repo-row: Use GS_APP_QUIRK_COMPULSORY to recognize + required repositories + +The GS_APP_QUIRK_PROVENANCE quirk does not mean it's also required repository, +thus use the GS_APP_QUIRK_COMPULSORY for repos, which cannot be disabled. +The GS_APP_QUIRK_PROVENANCE is used only for repositories, which cannot be removed. +--- + src/gs-repo-row.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/gs-repo-row.c b/src/gs-repo-row.c +index 87926092f..bbf67c194 100644 +--- a/src/gs-repo-row.c ++++ b/src/gs-repo-row.c +@@ -48,7 +48,8 @@ refresh_ui (GsRepoRow *row) + gboolean active = FALSE; + gboolean state_sensitive = FALSE; + gboolean busy = priv->busy_counter> 0; +- gboolean is_system_repo; ++ gboolean is_provenance; ++ gboolean is_compulsory; + + if (priv->repo == NULL) { + gtk_widget_set_sensitive (priv->disable_switch, FALSE); +@@ -87,11 +88,12 @@ refresh_ui (GsRepoRow *row) + break; + } + +- is_system_repo = gs_app_has_quirk (priv->repo, GS_APP_QUIRK_PROVENANCE); ++ is_provenance = gs_app_has_quirk (priv->repo, GS_APP_QUIRK_PROVENANCE); ++ is_compulsory = gs_app_has_quirk (priv->repo, GS_APP_QUIRK_COMPULSORY); + + /* Disable for the system repos, if installed */ +- gtk_widget_set_sensitive (priv->disable_switch, priv->supports_enable_disable && (state_sensitive || !is_system_repo || priv->always_allow_enable_disable)); +- gtk_widget_set_visible (priv->remove_button, priv->supports_remove && !is_system_repo); ++ gtk_widget_set_sensitive (priv->disable_switch, priv->supports_enable_disable && (state_sensitive || !is_compulsory || priv->always_allow_enable_disable)); ++ gtk_widget_set_visible (priv->remove_button, priv->supports_remove && !is_provenance && !is_compulsory); + + /* Set only the 'state' to visually indicate the state is not saved yet */ + if (busy) +-- +GitLab + + +From 026218b9d3211de243dfc49eca8b8d46633882b0 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Tue, 5 Oct 2021 11:03:31 +0200 +Subject: [PATCH 2/4] gs-plugin-provenance: Improve search speed in list of + repositories + +Use a GHashTable for bare repository names and a GPtrArray for those +with wildcards. This helps with speed, due to not traversing all +the repository names with the fnmatch() call. +--- + plugins/core/gs-plugin-provenance.c | 55 ++++++++++++++++++++--------- + 1 file changed, 38 insertions(+), 17 deletions(-) + +diff --git a/plugins/core/gs-plugin-provenance.c b/plugins/core/gs-plugin-provenance.c +index 97ff76798..a72c25a27 100644 +--- a/plugins/core/gs-plugin-provenance.c ++++ b/plugins/core/gs-plugin-provenance.c +@@ -19,7 +19,8 @@ + + struct GsPluginData { + GSettings *settings; +- gchar **sources; ++ GHashTable *repos; /* gchar *name ~> NULL */ ++ GPtrArray *wildcards; /* non-NULL, when have names with wildcards */ + }; + + static gchar ** +@@ -42,8 +43,24 @@ gs_plugin_provenance_settings_changed_cb (GSettings *settings, + { + GsPluginData *priv = gs_plugin_get_data (plugin); + if (g_strcmp0 (key, "official-repos") == 0) { +- g_strfreev (priv->sources); +- priv->sources = gs_plugin_provenance_get_sources (plugin); ++ /* The keys are stolen by the hash table, thus free only the array */ ++ g_autofree gchar **repos = NULL; ++ g_hash_table_remove_all (priv->repos); ++ g_clear_pointer (&priv->wildcards, g_ptr_array_unref); ++ repos = gs_plugin_provenance_get_sources (plugin); ++ for (guint ii = 0; repos && repos[ii]; ii++) { ++ if (strchr (repos[ii], '*') || ++ strchr (repos[ii], '?') || ++ strchr (repos[ii], '[')) { ++ if (priv->wildcards == NULL) ++ priv->wildcards = g_ptr_array_new_with_free_func (g_free); ++ g_ptr_array_add (priv->wildcards, g_steal_pointer (&(repos[ii]))); ++ } else { ++ g_hash_table_insert (priv->repos, g_steal_pointer (&(repos[ii])), NULL); ++ } ++ } ++ if (priv->wildcards != NULL) ++ g_ptr_array_add (priv->wildcards, NULL); + } + } + +@@ -52,9 +69,10 @@ gs_plugin_initialize (GsPlugin *plugin) + { + GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData)); + priv->settings = g_settings_new ("org.gnome.software"); ++ priv->repos = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_signal_connect (priv->settings, "changed", + G_CALLBACK (gs_plugin_provenance_settings_changed_cb), plugin); +- priv->sources = gs_plugin_provenance_get_sources (plugin); ++ gs_plugin_provenance_settings_changed_cb (priv->settings, "official-repos", plugin); + + /* after the package source is set */ + gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "dummy"); +@@ -66,7 +84,8 @@ void + gs_plugin_destroy (GsPlugin *plugin) + { + GsPluginData *priv = gs_plugin_get_data (plugin); +- g_strfreev (priv->sources); ++ g_hash_table_unref (priv->repos); ++ g_clear_pointer (&priv->wildcards, g_ptr_array_unref); + g_object_unref (priv->settings); + } + +@@ -74,12 +93,12 @@ static gboolean + refine_app (GsPlugin *plugin, + GsApp *app, + GsPluginRefineFlags flags, ++ GHashTable *repos, ++ GPtrArray *wildcards, + GCancellable *cancellable, + GError **error) + { +- GsPluginData *priv = gs_plugin_get_data (plugin); + const gchar *origin; +- gchar **sources; + + /* not required */ + if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE) == 0) +@@ -87,14 +106,10 @@ refine_app (GsPlugin *plugin, + if (gs_app_has_quirk (app, GS_APP_QUIRK_PROVENANCE)) + return TRUE; + +- /* nothing to search */ +- sources = priv->sources; +- if (sources == NULL || sources[0] == NULL) +- return TRUE; +- + /* simple case */ + origin = gs_app_get_origin (app); +- if (origin != NULL && gs_utils_strv_fnmatch (sources, origin)) { ++ if (origin != NULL && (g_hash_table_contains (repos, origin) || ++ (wildcards != NULL && gs_utils_strv_fnmatch ((gchar **) wildcards->pdata, origin)))) { + gs_app_add_quirk (app, GS_APP_QUIRK_PROVENANCE); + return TRUE; + } +@@ -103,7 +118,8 @@ refine_app (GsPlugin *plugin, + * provenance quirk to the system-configured repositories (but not + * user-configured ones). */ + if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY && +- gs_utils_strv_fnmatch (sources, gs_app_get_id (app))) { ++ (g_hash_table_contains (repos, gs_app_get_id (app)) || ++ (wildcards != NULL && gs_utils_strv_fnmatch ((gchar **) wildcards->pdata, gs_app_get_id (app))))) { + if (gs_app_get_scope (app) != AS_COMPONENT_SCOPE_USER) + gs_app_add_quirk (app, GS_APP_QUIRK_PROVENANCE); + return TRUE; +@@ -118,7 +134,8 @@ refine_app (GsPlugin *plugin, + return TRUE; + if (g_str_has_prefix (origin + 1, "installed:")) + origin += 10; +- if (gs_utils_strv_fnmatch (sources, origin + 1)) { ++ if (g_hash_table_contains (repos, origin + 1) || ++ (wildcards != NULL && gs_utils_strv_fnmatch ((gchar **) wildcards->pdata, origin + 1))) { + gs_app_add_quirk (app, GS_APP_QUIRK_PROVENANCE); + return TRUE; + } +@@ -133,17 +150,21 @@ gs_plugin_refine (GsPlugin *plugin, + GError **error) + { + GsPluginData *priv = gs_plugin_get_data (plugin); ++ g_autoptr(GHashTable) repos = NULL; ++ g_autoptr(GPtrArray) wildcards = NULL; + + /* nothing to do here */ + if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE) == 0) + return TRUE; ++ repos = g_hash_table_ref (priv->repos); ++ wildcards = priv->wildcards != NULL ? g_ptr_array_ref (priv->wildcards) : NULL; + /* nothing to search */ +- if (priv->sources == NULL || priv->sources[0] == NULL) ++ if (g_hash_table_size (repos) == 0) + return TRUE; + + for (guint i = 0; i < gs_app_list_length (list); i++) { + GsApp *app = gs_app_list_index (list, i); +- if (!refine_app (plugin, app, flags, cancellable, error)) ++ if (!refine_app (plugin, app, flags, repos, wildcards, cancellable, error)) + return FALSE; + } + +-- +GitLab + + +From b5e3356aff5fcd257248f9bb697e272c879249ae Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Tue, 5 Oct 2021 13:03:44 +0200 +Subject: [PATCH 3/4] settings: Add 'required-repos' key + +To be used to list repositories, which cannot be removed or disabled. +It's a complementary option for the 'official-repos' key. +--- + data/org.gnome.software.gschema.xml | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/data/org.gnome.software.gschema.xml b/data/org.gnome.software.gschema.xml +index db1c27ce4..0e5706b7c 100644 +--- a/data/org.gnome.software.gschema.xml ++++ b/data/org.gnome.software.gschema.xml +@@ -94,6 +94,10 @@ + [] + A list of official repositories that should not be considered 3rd party + ++ ++ [] ++ A list of required repositories that cannot be disabled or removed ++ + + [] + A list of official repositories that should be considered free software +-- +GitLab + + +From d6b8b206a596bb520a0b77066898b44a5ef18920 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Tue, 5 Oct 2021 14:16:56 +0200 +Subject: [PATCH 4/4] gs-plugin-provenance: Handle also 'required-repos' key + +Let it handle also 'required-repos' settings key, beside the 'official-repos' +key, which are close enough to share the same code and memory. With this +done the repositories can be marked as compulsory, independently from the official +repositories. + +Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1479 +--- + plugins/core/gs-plugin-provenance.c | 142 +++++++++++++++++++++------- + 1 file changed, 108 insertions(+), 34 deletions(-) + +diff --git a/plugins/core/gs-plugin-provenance.c b/plugins/core/gs-plugin-provenance.c +index a72c25a27..22f3c98e1 100644 +--- a/plugins/core/gs-plugin-provenance.c ++++ b/plugins/core/gs-plugin-provenance.c +@@ -14,26 +14,61 @@ + /* + * SECTION: + * Sets the package provenance to TRUE if installed by an official +- * software source. ++ * software source. Also sets compulsory quirk when a required repository. + */ + + struct GsPluginData { + GSettings *settings; +- GHashTable *repos; /* gchar *name ~> NULL */ +- GPtrArray *wildcards; /* non-NULL, when have names with wildcards */ ++ GHashTable *repos; /* gchar *name ~> guint flags */ ++ GPtrArray *provenance_wildcards; /* non-NULL, when have names with wildcards */ ++ GPtrArray *compulsory_wildcards; /* non-NULL, when have names with wildcards */ + }; + ++static GHashTable * ++gs_plugin_provenance_remove_by_flag (GHashTable *old_repos, ++ GsAppQuirk quirk) ++{ ++ GHashTable *new_repos = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); ++ GHashTableIter iter; ++ gpointer key, value; ++ g_hash_table_iter_init (&iter, old_repos); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ guint flags = GPOINTER_TO_UINT (value); ++ flags = flags & (~quirk); ++ if (flags != 0) ++ g_hash_table_insert (new_repos, g_strdup (key), GUINT_TO_POINTER (flags)); ++ } ++ return new_repos; ++} ++ ++static void ++gs_plugin_provenance_add_quirks (GsApp *app, ++ guint quirks) ++{ ++ GsAppQuirk array[] = { ++ GS_APP_QUIRK_PROVENANCE, ++ GS_APP_QUIRK_COMPULSORY ++ }; ++ for (guint ii = 0; ii < G_N_ELEMENTS (array); ii++) { ++ if ((quirks & array[ii]) != 0) ++ gs_app_add_quirk (app, array[ii]); ++ } ++} ++ + static gchar ** +-gs_plugin_provenance_get_sources (GsPlugin *plugin) ++gs_plugin_provenance_get_sources (GsPlugin *plugin, ++ const gchar *key) + { + GsPluginData *priv = gs_plugin_get_data (plugin); + const gchar *tmp; + tmp = g_getenv ("GS_SELF_TEST_PROVENANCE_SOURCES"); + if (tmp != NULL) { ++ if (g_strcmp0 (key, "required-repos") == 0) ++ return NULL; + g_debug ("using custom provenance sources of %s", tmp); + return g_strsplit (tmp, ",", -1); + } +- return g_settings_get_strv (priv->settings, "official-repos"); ++ return g_settings_get_strv (priv->settings, key); + } + + static void +@@ -42,25 +77,43 @@ gs_plugin_provenance_settings_changed_cb (GSettings *settings, + GsPlugin *plugin) + { + GsPluginData *priv = gs_plugin_get_data (plugin); ++ GsAppQuirk quirk = GS_APP_QUIRK_NONE; ++ GPtrArray **pwildcards = NULL; ++ + if (g_strcmp0 (key, "official-repos") == 0) { ++ quirk = GS_APP_QUIRK_PROVENANCE; ++ pwildcards = &priv->provenance_wildcards; ++ } else if (g_strcmp0 (key, "required-repos") == 0) { ++ quirk = GS_APP_QUIRK_COMPULSORY; ++ pwildcards = &priv->compulsory_wildcards; ++ } ++ ++ if (quirk != GS_APP_QUIRK_NONE) { + /* The keys are stolen by the hash table, thus free only the array */ + g_autofree gchar **repos = NULL; +- g_hash_table_remove_all (priv->repos); +- g_clear_pointer (&priv->wildcards, g_ptr_array_unref); +- repos = gs_plugin_provenance_get_sources (plugin); ++ g_autoptr(GHashTable) old_repos = priv->repos; ++ g_autoptr(GPtrArray) old_wildcards = *pwildcards; ++ GHashTable *new_repos = gs_plugin_provenance_remove_by_flag (old_repos, quirk); ++ GPtrArray *new_wildcards = NULL; ++ repos = gs_plugin_provenance_get_sources (plugin, key); + for (guint ii = 0; repos && repos[ii]; ii++) { +- if (strchr (repos[ii], '*') || +- strchr (repos[ii], '?') || +- strchr (repos[ii], '[')) { +- if (priv->wildcards == NULL) +- priv->wildcards = g_ptr_array_new_with_free_func (g_free); +- g_ptr_array_add (priv->wildcards, g_steal_pointer (&(repos[ii]))); ++ gchar *repo = g_steal_pointer (&(repos[ii])); ++ if (strchr (repo, '*') || ++ strchr (repo, '?') || ++ strchr (repo, '[')) { ++ if (new_wildcards == NULL) ++ new_wildcards = g_ptr_array_new_with_free_func (g_free); ++ g_ptr_array_add (new_wildcards, repo); + } else { +- g_hash_table_insert (priv->repos, g_steal_pointer (&(repos[ii])), NULL); ++ g_hash_table_insert (new_repos, repo, ++ GUINT_TO_POINTER (quirk | ++ GPOINTER_TO_UINT (g_hash_table_lookup (new_repos, repo)))); + } + } +- if (priv->wildcards != NULL) +- g_ptr_array_add (priv->wildcards, NULL); ++ if (new_wildcards != NULL) ++ g_ptr_array_add (new_wildcards, NULL); ++ priv->repos = new_repos; ++ *pwildcards = new_wildcards; + } + } + +@@ -73,6 +126,7 @@ gs_plugin_initialize (GsPlugin *plugin) + g_signal_connect (priv->settings, "changed", + G_CALLBACK (gs_plugin_provenance_settings_changed_cb), plugin); + gs_plugin_provenance_settings_changed_cb (priv->settings, "official-repos", plugin); ++ gs_plugin_provenance_settings_changed_cb (priv->settings, "required-repos", plugin); + + /* after the package source is set */ + gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "dummy"); +@@ -85,20 +139,42 @@ gs_plugin_destroy (GsPlugin *plugin) + { + GsPluginData *priv = gs_plugin_get_data (plugin); + g_hash_table_unref (priv->repos); +- g_clear_pointer (&priv->wildcards, g_ptr_array_unref); ++ g_clear_pointer (&priv->provenance_wildcards, g_ptr_array_unref); ++ g_clear_pointer (&priv->compulsory_wildcards, g_ptr_array_unref); + g_object_unref (priv->settings); + } + ++static gboolean ++gs_plugin_provenance_find_repo_flags (GHashTable *repos, ++ GPtrArray *provenance_wildcards, ++ GPtrArray *compulsory_wildcards, ++ const gchar *repo, ++ guint *out_flags) ++{ ++ if (repo == NULL || *repo == '\0') ++ return FALSE; ++ *out_flags = GPOINTER_TO_UINT (g_hash_table_lookup (repos, repo)); ++ if (provenance_wildcards != NULL && ++ gs_utils_strv_fnmatch ((gchar **) provenance_wildcards->pdata, repo)) ++ *out_flags |= GS_APP_QUIRK_PROVENANCE; ++ if (compulsory_wildcards != NULL && ++ gs_utils_strv_fnmatch ((gchar **) compulsory_wildcards->pdata, repo)) ++ *out_flags |= GS_APP_QUIRK_COMPULSORY; ++ return *out_flags != 0; ++} ++ + static gboolean + refine_app (GsPlugin *plugin, + GsApp *app, + GsPluginRefineFlags flags, + GHashTable *repos, +- GPtrArray *wildcards, ++ GPtrArray *provenance_wildcards, ++ GPtrArray *compulsory_wildcards, + GCancellable *cancellable, + GError **error) + { + const gchar *origin; ++ guint quirks; + + /* not required */ + if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE) == 0) +@@ -108,9 +184,8 @@ refine_app (GsPlugin *plugin, + + /* simple case */ + origin = gs_app_get_origin (app); +- if (origin != NULL && (g_hash_table_contains (repos, origin) || +- (wildcards != NULL && gs_utils_strv_fnmatch ((gchar **) wildcards->pdata, origin)))) { +- gs_app_add_quirk (app, GS_APP_QUIRK_PROVENANCE); ++ if (gs_plugin_provenance_find_repo_flags (repos, provenance_wildcards, compulsory_wildcards, origin, &quirks)) { ++ gs_plugin_provenance_add_quirks (app, quirks); + return TRUE; + } + +@@ -118,10 +193,9 @@ refine_app (GsPlugin *plugin, + * provenance quirk to the system-configured repositories (but not + * user-configured ones). */ + if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY && +- (g_hash_table_contains (repos, gs_app_get_id (app)) || +- (wildcards != NULL && gs_utils_strv_fnmatch ((gchar **) wildcards->pdata, gs_app_get_id (app))))) { ++ gs_plugin_provenance_find_repo_flags (repos, provenance_wildcards, compulsory_wildcards, gs_app_get_id (app), &quirks)) { + if (gs_app_get_scope (app) != AS_COMPONENT_SCOPE_USER) +- gs_app_add_quirk (app, GS_APP_QUIRK_PROVENANCE); ++ gs_plugin_provenance_add_quirks (app, quirks); + return TRUE; + } + +@@ -134,11 +208,9 @@ refine_app (GsPlugin *plugin, + return TRUE; + if (g_str_has_prefix (origin + 1, "installed:")) + origin += 10; +- if (g_hash_table_contains (repos, origin + 1) || +- (wildcards != NULL && gs_utils_strv_fnmatch ((gchar **) wildcards->pdata, origin + 1))) { +- gs_app_add_quirk (app, GS_APP_QUIRK_PROVENANCE); +- return TRUE; +- } ++ if (gs_plugin_provenance_find_repo_flags (repos, provenance_wildcards, compulsory_wildcards, origin + 1, &quirks)) ++ gs_plugin_provenance_add_quirks (app, quirks); ++ + return TRUE; + } + +@@ -151,20 +223,22 @@ gs_plugin_refine (GsPlugin *plugin, + { + GsPluginData *priv = gs_plugin_get_data (plugin); + g_autoptr(GHashTable) repos = NULL; +- g_autoptr(GPtrArray) wildcards = NULL; ++ g_autoptr(GPtrArray) provenance_wildcards = NULL; ++ g_autoptr(GPtrArray) compulsory_wildcards = NULL; + + /* nothing to do here */ + if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE) == 0) + return TRUE; + repos = g_hash_table_ref (priv->repos); +- wildcards = priv->wildcards != NULL ? g_ptr_array_ref (priv->wildcards) : NULL; ++ provenance_wildcards = priv->provenance_wildcards != NULL ? g_ptr_array_ref (priv->provenance_wildcards) : NULL; ++ compulsory_wildcards = priv->compulsory_wildcards != NULL ? g_ptr_array_ref (priv->compulsory_wildcards) : NULL; + /* nothing to search */ +- if (g_hash_table_size (repos) == 0) ++ if (g_hash_table_size (repos) == 0 && provenance_wildcards == NULL && compulsory_wildcards == NULL) + return TRUE; + + for (guint i = 0; i < gs_app_list_length (list); i++) { + GsApp *app = gs_app_list_index (list, i); +- if (!refine_app (plugin, app, flags, repos, wildcards, cancellable, error)) ++ if (!refine_app (plugin, app, flags, repos, provenance_wildcards, compulsory_wildcards, cancellable, error)) + return FALSE; + } + +-- +GitLab + diff --git a/0007-compulsory-only-for-repos.patch b/0007-compulsory-only-for-repos.patch new file mode 100644 index 0000000..fb266df --- /dev/null +++ b/0007-compulsory-only-for-repos.patch @@ -0,0 +1,42 @@ +From 895d1ca748f4f33a852853f5f07903fb549fb66f Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Mon, 11 Oct 2021 09:13:59 +0200 +Subject: [PATCH] gs-plugin-provenance: Set COMPULSORY quirk only on REPOSITORY + apps + +The compulsory quirk related to repositories, which cannot be removed, +not to the applications provided by those repositories, thus set that +quirk only on repositories, not on the apps from it. + +Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1488 +--- + plugins/core/gs-plugin-provenance.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/plugins/core/gs-plugin-provenance.c b/plugins/core/gs-plugin-provenance.c +index 22f3c98e..e44a55f0 100644 +--- a/plugins/core/gs-plugin-provenance.c ++++ b/plugins/core/gs-plugin-provenance.c +@@ -45,14 +45,11 @@ static void + gs_plugin_provenance_add_quirks (GsApp *app, + guint quirks) + { +- GsAppQuirk array[] = { +- GS_APP_QUIRK_PROVENANCE, +- GS_APP_QUIRK_COMPULSORY +- }; +- for (guint ii = 0; ii < G_N_ELEMENTS (array); ii++) { +- if ((quirks & array[ii]) != 0) +- gs_app_add_quirk (app, array[ii]); +- } ++ if ((quirks & GS_APP_QUIRK_PROVENANCE) != 0) ++ gs_app_add_quirk (app, GS_APP_QUIRK_PROVENANCE); ++ if ((quirks & GS_APP_QUIRK_COMPULSORY) != 0 && ++ gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY) ++ gs_app_add_quirk (app, GS_APP_QUIRK_COMPULSORY); + } + + static gchar ** +-- +2.31.1 + diff --git a/0008-gs-removal-dialog-crrect-property-name.patch b/0008-gs-removal-dialog-crrect-property-name.patch new file mode 100644 index 0000000..47325af --- /dev/null +++ b/0008-gs-removal-dialog-crrect-property-name.patch @@ -0,0 +1,12 @@ +diff -up gnome-software-41.5/src/gs-removal-dialog.ui.4 gnome-software-41.5/src/gs-removal-dialog.ui +--- gnome-software-41.5/src/gs-removal-dialog.ui.4 2022-09-12 08:59:57.819169830 +0200 ++++ gnome-software-41.5/src/gs-removal-dialog.ui 2022-09-12 09:00:25.148201673 +0200 +@@ -20,7 +20,7 @@ + + +