diff --git a/.gitignore b/.gitignore
index 9b144e3..663ce4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/gnome-software-41.5.tar.xz
+SOURCES/gnome-software-45.3.tar.xz
diff --git a/.gnome-software.metadata b/.gnome-software.metadata
index 037f8ac..6921398 100644
--- a/.gnome-software.metadata
+++ b/.gnome-software.metadata
@@ -1 +1 @@
-bc37c8ed81ddff70749abcf7ab94bdcf3fffad0f SOURCES/gnome-software-41.5.tar.xz
+5f8d9e12db5da6b9e82b2cd7ec23768e5ac3df0c SOURCES/gnome-software-45.3.tar.xz
diff --git a/SOURCES/0001-Lower_glib_dependency_to_2_68.patch b/SOURCES/0001-Lower_glib_dependency_to_2_68.patch
new file mode 100644
index 0000000..074dfa1
--- /dev/null
+++ b/SOURCES/0001-Lower_glib_dependency_to_2_68.patch
@@ -0,0 +1,198 @@
+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/SOURCES/0001-crash-with-broken-theme.patch b/SOURCES/0001-crash-with-broken-theme.patch
deleted file mode 100644
index fd37e80..0000000
--- a/SOURCES/0001-crash-with-broken-theme.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 3a644c151f27f439c36170f0958fd21cf1cc54d0 Mon Sep 17 00:00:00 2001
-From: Milan Crha <mcrha@redhat.com>
-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/SOURCES/0002-Lower-pango-attributes.patch b/SOURCES/0002-Lower-pango-attributes.patch
new file mode 100644
index 0000000..f740e21
--- /dev/null
+++ b/SOURCES/0002-Lower-pango-attributes.patch
@@ -0,0 +1,42 @@
+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 @@
+                         <property name="margin-end">2</property>
+                         <attributes>
+                           <attribute name="weight" value="bold"/>
+-                          <attribute name="variant" value="all-small-caps"/>
++                          <!--<attribute name="variant" value="all-small-caps"/>-->
+                         </attributes>
+                       </object>
+                     </child>
+@@ -110,7 +110,7 @@
+                         <property name="margin-end">2</property>
+                         <attributes>
+                           <attribute name="weight" value="bold"/>
+-                          <attribute name="variant" value="all-small-caps"/>
++                          <!--<attribute name="variant" value="all-small-caps"/>-->
+                         </attributes>
+                       </object>
+                     </child>
+@@ -140,7 +140,7 @@
+                         <property name="margin-end">2</property>
+                         <attributes>
+                           <attribute name="weight" value="bold"/>
+-                          <attribute name="variant" value="all-small-caps"/>
++                          <!--<attribute name="variant" value="all-small-caps"/>-->
+                         </attributes>
+                       </object>
+                     </child>
+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 @@
+             <attributes>
+               <attribute name="scale" value="5.0"/>
+               <attribute name="weight" value="light"/>
+-              <attribute name="line-height" value="0.75"/>
++              <!--<attribute name="line-height" value="0.75"/>-->
+             </attributes>
+             <layout>
+               <property name="column">0</property>
diff --git a/SOURCES/0003-Verify-category-sizes.patch b/SOURCES/0003-Verify-category-sizes.patch
new file mode 100644
index 0000000..09b9357
--- /dev/null
+++ b/SOURCES/0003-Verify-category-sizes.patch
@@ -0,0 +1,335 @@
+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/SOURCES/0004-prefer-vendor-name.patch b/SOURCES/0004-prefer-vendor-name.patch
new file mode 100644
index 0000000..6ae3a9c
--- /dev/null
+++ b/SOURCES/0004-prefer-vendor-name.patch
@@ -0,0 +1,151 @@
+diff --git a/lib/gs-app.c b/lib/gs-app.c
+index fa266cdc1..66a5acad7 100644
+--- a/lib/gs-app.c
++++ b/lib/gs-app.c
+@@ -6319,8 +6319,11 @@ gs_app_dup_origin_ui (GsApp *app,
+ 	if (gs_app_has_quirk (app, GS_APP_QUIRK_PROVENANCE) &&
+ 	    gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY) {
+ 		os_release = gs_os_release_new (NULL);
+-		if (os_release != NULL)
+-			origin_str = gs_os_release_get_name (os_release);
++		if (os_release != NULL) {
++			origin_str = gs_os_release_get_vendor_name (os_release);
++			if (origin_str == NULL)
++				origin_str = gs_os_release_get_name (os_release);
++		}
+ 	}
+ 
+ 	priv = gs_app_get_instance_private (app);
+diff --git a/lib/gs-os-release.c b/lib/gs-os-release.c
+index 85ea24e2e..380c9c84e 100644
+--- a/lib/gs-os-release.c
++++ b/lib/gs-os-release.c
+@@ -37,6 +37,7 @@ struct _GsOsRelease
+ 	gchar			*distro_codename;
+ 	gchar			*home_url;
+ 	gchar			*logo;
++	gchar			*vendor_name;
+ };
+ 
+ static void gs_os_release_initable_iface_init (GInitableIface *iface);
+@@ -44,6 +45,18 @@ static void gs_os_release_initable_iface_init (GInitableIface *iface);
+ G_DEFINE_TYPE_WITH_CODE (GsOsRelease, gs_os_release, G_TYPE_OBJECT,
+ 			 G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, gs_os_release_initable_iface_init))
+ 
++static void
++gs_os_release_set_string_nonempty (gchar **inout_string,
++				   const gchar *value)
++{
++	if (*inout_string == value)
++		return;
++
++	g_clear_pointer (inout_string, g_free);
++	if (value != NULL && *value != '\0')
++		*inout_string = g_strdup (value);
++}
++
+ static gboolean
+ gs_os_release_initable_init (GInitable *initable,
+ 			     GCancellable *cancellable,
+@@ -89,43 +102,49 @@ gs_os_release_initable_init (GInitable *initable,
+ 
+ 		/* match fields we're interested in */
+ 		if (g_strcmp0 (lines[i], "NAME") == 0) {
+-			os_release->name = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->name, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "VERSION") == 0) {
+-			os_release->version = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->version, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "ID") == 0) {
+-			os_release->id = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->id, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "ID_LIKE") == 0) {
++			if (os_release->id_like != NULL)
++				g_strfreev (os_release->id_like);
+ 			os_release->id_like = g_strsplit (tmp, " ", 0);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "VERSION_ID") == 0) {
+-			os_release->version_id = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->version_id, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "PRETTY_NAME") == 0) {
+-			os_release->pretty_name = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->pretty_name, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "CPE_NAME") == 0) {
+-			os_release->cpe_name = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->cpe_name, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "UBUNTU_CODENAME") == 0) {
+-			os_release->distro_codename = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->distro_codename, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "HOME_URL") == 0) {
+-			os_release->home_url = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->home_url, tmp);
+ 			continue;
+ 		}
+ 		if (g_strcmp0 (lines[i], "LOGO") == 0) {
+-			os_release->logo = g_strdup (tmp);
++			gs_os_release_set_string_nonempty (&os_release->logo, tmp);
++			continue;
++		}
++		if (g_strcmp0 (lines[i], "VENDOR_NAME") == 0) {
++			gs_os_release_set_string_nonempty (&os_release->vendor_name, tmp);
+ 			continue;
+ 		}
+ 	}
+@@ -304,6 +323,23 @@ gs_os_release_get_logo (GsOsRelease *os_release)
+ 	return os_release->logo;
+ }
+ 
++/**
++ * gs_os_release_get_vendor_name:
++ * @os_release: A #GsOsRelease
++ *
++ * Gets the vendor name from the os-release parser.
++ *
++ * Returns: (nullable): a string, or %NULL
++ *
++ * Since: 46.3
++ **/
++const gchar *
++gs_os_release_get_vendor_name (GsOsRelease *os_release)
++{
++	g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL);
++	return os_release->vendor_name;
++}
++
+ static void
+ gs_os_release_finalize (GObject *object)
+ {
+@@ -318,6 +354,7 @@ gs_os_release_finalize (GObject *object)
+ 	g_free (os_release->distro_codename);
+ 	g_free (os_release->home_url);
+ 	g_free (os_release->logo);
++	g_free (os_release->vendor_name);
+ 
+ 	G_OBJECT_CLASS (gs_os_release_parent_class)->finalize (object);
+ }
+diff --git a/lib/gs-os-release.h b/lib/gs-os-release.h
+index e219e5c96..6d52ecdd2 100644
+--- a/lib/gs-os-release.h
++++ b/lib/gs-os-release.h
+@@ -30,5 +30,6 @@ const gchar		*gs_os_release_get_cpe_name		(GsOsRelease	*os_release);
+ const gchar		*gs_os_release_get_distro_codename	(GsOsRelease	*os_release);
+ const gchar		*gs_os_release_get_home_url		(GsOsRelease	*os_release);
+ const gchar		*gs_os_release_get_logo			(GsOsRelease	*os_release);
++const gchar		*gs_os_release_get_vendor_name		(GsOsRelease	*os_release);
+ 
+ G_END_DECLS
diff --git a/SOURCES/0006-optional-repos-cannot-be-disabled.patch b/SOURCES/0006-optional-repos-cannot-be-disabled.patch
deleted file mode 100644
index b581147..0000000
--- a/SOURCES/0006-optional-repos-cannot-be-disabled.patch
+++ /dev/null
@@ -1,498 +0,0 @@
-From dca731ff0daf904911dd6815fb9a1b181329c887 Mon Sep 17 00:00:00 2001
-From: Milan Crha <mcrha@redhat.com>
-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 <mcrha@redhat.com>
-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 <mcrha@redhat.com>
-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 @@
-       <default>[]</default>
-       <summary>A list of official repositories that should not be considered 3rd party</summary>
-     </key>
-+    <key name="required-repos" type="as">
-+      <default>[]</default>
-+      <summary>A list of required repositories that cannot be disabled or removed</summary>
-+    </key>
-     <key name="free-repos" type="as">
-       <default>[]</default>
-       <summary>A list of official repositories that should be considered free software</summary>
--- 
-GitLab
-
-
-From d6b8b206a596bb520a0b77066898b44a5ef18920 Mon Sep 17 00:00:00 2001
-From: Milan Crha <mcrha@redhat.com>
-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/SOURCES/0007-compulsory-only-for-repos.patch b/SOURCES/0007-compulsory-only-for-repos.patch
deleted file mode 100644
index fb266df..0000000
--- a/SOURCES/0007-compulsory-only-for-repos.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 895d1ca748f4f33a852853f5f07903fb549fb66f Mon Sep 17 00:00:00 2001
-From: Milan Crha <mcrha@redhat.com>
-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/SOURCES/0008-gs-removal-dialog-crrect-property-name.patch b/SOURCES/0008-gs-removal-dialog-crrect-property-name.patch
deleted file mode 100644
index 47325af..0000000
--- a/SOURCES/0008-gs-removal-dialog-crrect-property-name.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-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 @@
-     </child>
-   </object>
-   <template class="GsRemovalDialog" parent="GtkMessageDialog">
--    <property name="text" translatable="yes">Incompatible Software</property>
-+    <property name="title" translatable="yes">Incompatible Software</property>
-     <property name="modal">True</property>
-     <property name="destroy_with_parent">True</property>
-     <child type="action">
diff --git a/SOURCES/0009-hide-some-errors.patch b/SOURCES/0009-hide-some-errors.patch
deleted file mode 100644
index 3dd6ade..0000000
--- a/SOURCES/0009-hide-some-errors.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 19c19d37ec9ba8b15b806158572a8e4a34c55677 Mon Sep 17 00:00:00 2001
-From: Milan Crha <mcrha@redhat.com>
-Date: Wed, 7 Sep 2022 09:01:16 +0200
-Subject: [PATCH] misc: Hide some errors in non-debug builds
-
-These two errors are useless for the users, they cannot do anything with them.
-While it can be useful to know them, they can be also disturbing and they just
-fill the journal log for the users.
-
-Related to https://gitlab.gnome.org/GNOME/gnome-software/-/issues/753
----
- lib/gs-plugin-loader.c | 15 +++++++++++----
- src/gs-shell.c         | 15 +++++++++++----
- 2 files changed, 22 insertions(+), 8 deletions(-)
-
-diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
-index 63f741c37..e040358b7 100644
---- a/lib/gs-plugin-loader.c
-+++ b/lib/gs-plugin-loader.c
-@@ -358,10 +358,17 @@ gs_plugin_loader_claim_error (GsPluginLoader *plugin_loader,
- 
- 	/* invalid */
- 	if (error_copy->domain != GS_PLUGIN_ERROR) {
--		g_warning ("not GsPlugin error %s:%i: %s",
--			   g_quark_to_string (error_copy->domain),
--			   error_copy->code,
--			   error_copy->message);
-+		if (g_strcmp0 (BUILD_TYPE, "debug") == 0) {
-+			g_warning ("not GsPlugin error %s:%i: %s",
-+				   g_quark_to_string (error_copy->domain),
-+				   error_copy->code,
-+				   error_copy->message);
-+		} else {
-+			g_debug ("not GsPlugin error %s:%i: %s",
-+				 g_quark_to_string (error_copy->domain),
-+				 error_copy->code,
-+				 error_copy->message);
-+		}
- 		error_copy->domain = GS_PLUGIN_ERROR;
- 		error_copy->code = GS_PLUGIN_ERROR_FAILED;
- 	}
-diff --git a/src/gs-shell.c b/src/gs-shell.c
-index beb76f0e9..af297d240 100644
---- a/src/gs-shell.c
-+++ b/src/gs-shell.c
-@@ -2080,10 +2080,17 @@ gs_shell_rescan_events (GsShell *shell)
- 			    !g_error_matches (error,
- 					      G_IO_ERROR,
- 					      G_IO_ERROR_CANCELLED)) {
--				g_warning ("not handling error %s for action %s: %s",
--					   gs_plugin_error_to_string (error->code),
--					   gs_plugin_action_to_string (action),
--					   error->message);
-+				if (g_strcmp0 (BUILD_TYPE, "debug") == 0) {
-+					g_warning ("not handling error %s for action %s: %s",
-+						   gs_plugin_error_to_string (error->code),
-+						   gs_plugin_action_to_string (action),
-+						   error->message);
-+				} else {
-+					g_debug ("not handling error %s for action %s: %s",
-+						 gs_plugin_error_to_string (error->code),
-+						 gs_plugin_action_to_string (action),
-+						 error->message);
-+				}
- 			}
- 			gs_plugin_event_add_flag (event, GS_PLUGIN_EVENT_FLAG_INVALID);
- 			return;
--- 
-GitLab
-
diff --git a/SPECS/gnome-software.spec b/SPECS/gnome-software.spec
index b26f25b..383fefb 100644
--- a/SPECS/gnome-software.spec
+++ b/SPECS/gnome-software.spec
@@ -1,61 +1,80 @@
 %global appstream_version 0.14.0
+%global flatpak_version 1.9.1
+%global fwupd_version 1.5.6
+%global glib2_version 2.68.0
+%global gtk4_version 4.10.0
+%global json_glib_version 1.6.0
+%global libadwaita_version 1.3.alpha
 %global libxmlb_version 0.1.7
-%global glib2_version 2.61.1
-%global gtk3_version 3.22.4
-%global json_glib_version 1.2.0
-%global libsoup_version 2.52.0
-%global packagekit_version 1.1.1
-%global fwupd_version 1.3.3
-%global flatpak_version 1.5.1
+%global packagekit_version 1.2.5
+
+# Disable WebApps for RHEL builds
+%bcond webapps %[!0%{?rhel}]
+# Disable parental control for RHEL builds
+%bcond malcontent %[!0%{?rhel}]
+# Disable rpm-ostree support for RHEL builds
+%bcond rpmostree %[!0%{?rhel}]
+
+# this is not a library version
+%define gs_plugin_version 20
 
 %global tarball_version %%(echo %{version} | tr '~' '.')
 
+%global __provides_exclude_from ^%{_libdir}/%{name}/plugins-%{gs_plugin_version}/.*\\.so.*$
+
 Name:      gnome-software
-Version:   41.5
+Version:   45.3
 Release:   3%{?dist}
 Summary:   A software center for GNOME
 
-License:   GPLv2+
+License:   GPL-2.0-or-later
 URL:       https://wiki.gnome.org/Apps/Software
-Source0:   https://download.gnome.org/sources/gnome-software/41/%{name}-%{tarball_version}.tar.xz
+Source0:   https://download.gnome.org/sources/gnome-software/45/%{name}-%{tarball_version}.tar.xz
 
-Patch01:   0001-crash-with-broken-theme.patch
-Patch02:   0006-optional-repos-cannot-be-disabled.patch
-Patch03:   0007-compulsory-only-for-repos.patch
-Patch04:   0008-gs-removal-dialog-crrect-property-name.patch
-Patch05:   0009-hide-some-errors.patch
+Patch01:   0001-Lower_glib_dependency_to_2_68.patch
+Patch02:   0002-Lower-pango-attributes.patch
+Patch03:   0003-Verify-category-sizes.patch
+Patch04:   0004-prefer-vendor-name.patch
 
-BuildRequires: appstream-devel >= %{appstream_version}
-BuildRequires: gcc
-BuildRequires: gettext
-BuildRequires: libxslt
 BuildRequires: docbook-style-xsl
 BuildRequires: desktop-file-utils
-BuildRequires: fwupd-devel >= %{fwupd_version}
-BuildRequires: glib2-devel >= %{glib2_version}
-BuildRequires: gnome-online-accounts-devel
-BuildRequires: gsettings-desktop-schemas-devel
-BuildRequires: gspell-devel
-BuildRequires: gtk3-devel >= %{gtk3_version}
+BuildRequires: gcc
+BuildRequires: gettext
 BuildRequires: gtk-doc
-BuildRequires: json-glib-devel >= %{json_glib_version}
-BuildRequires: libdnf-devel
-BuildRequires: libhandy1-devel
-BuildRequires: libsoup-devel
-BuildRequires: libxmlb-devel >= %{libxmlb_version}
+BuildRequires: libxslt
 BuildRequires: meson
-BuildRequires: PackageKit-glib-devel >= %{packagekit_version}
-BuildRequires: polkit-devel
-BuildRequires: flatpak-devel >= %{flatpak_version}
-BuildRequires: ostree-devel
-BuildRequires: rpm-devel
-BuildRequires: rpm-ostree-devel
-BuildRequires: libgudev1-devel
-BuildRequires: sysprof-capture-devel
-BuildRequires: valgrind-devel
+BuildRequires: pkgconfig(appstream) >= %{appstream_version}
+BuildRequires: pkgconfig(flatpak) >= %{flatpak_version}
+BuildRequires: pkgconfig(fwupd) >= %{fwupd_version}
+BuildRequires: pkgconfig(gdk-pixbuf-2.0)
+BuildRequires: pkgconfig(gio-unix-2.0) >= %{glib2_version}
+BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version}
+BuildRequires: pkgconfig(gmodule-2.0) >= %{glib2_version}
+BuildRequires: pkgconfig(gsettings-desktop-schemas)
+BuildRequires: pkgconfig(gtk4) >= %{gtk4_version}
+BuildRequires: pkgconfig(gudev-1.0)
+BuildRequires: pkgconfig(json-glib-1.0) >= %{json_glib_version}
+BuildRequires: pkgconfig(libadwaita-1) >= %{libadwaita_version}
+BuildRequires: pkgconfig(libdnf)
+BuildRequires: pkgconfig(libsoup-2.4)
+%if %{with malcontent}
+BuildRequires: pkgconfig(malcontent-0)
+%endif
+BuildRequires: pkgconfig(ostree-1)
+BuildRequires: pkgconfig(packagekit-glib2) >= %{packagekit_version}
+BuildRequires: pkgconfig(polkit-gobject-1)
+BuildRequires: pkgconfig(rpm)
+%if %{with rpmostree}
+BuildRequires: pkgconfig(rpm-ostree-1)
+%endif
+#BuildRequires: pkgconfig(sysprof-capture-4)
+BuildRequires: pkgconfig(xmlb) >= %{libxmlb_version}
 
 Requires: appstream-data
 Requires: appstream%{?_isa} >= %{appstream_version}
+%if %{with webapps}
+Requires: epiphany-runtime%{?_isa}
+%endif
 Requires: flatpak%{?_isa} >= %{flatpak_version}
 Requires: flatpak-libs%{?_isa} >= %{flatpak_version}
 Requires: fwupd%{?_isa} >= %{fwupd_version}
@@ -63,12 +82,10 @@ Requires: glib2%{?_isa} >= %{glib2_version}
 # gnome-menus is needed for app folder .directory entries
 Requires: gnome-menus%{?_isa}
 Requires: gsettings-desktop-schemas%{?_isa}
-Requires: gtk3%{?_isa} >= %{gtk3_version}
 Requires: json-glib%{?_isa} >= %{json_glib_version}
 Requires: iso-codes
 # librsvg2 is needed for gdk-pixbuf svg loader
 Requires: librsvg2%{?_isa}
-Requires: libsoup%{?_isa} >= %{libsoup_version}
 Requires: libxmlb%{?_isa} >= %{libxmlb_version}
 
 Recommends: PackageKit%{?_isa} >= %{packagekit_version}
@@ -76,9 +93,6 @@ Recommends: PackageKit%{?_isa} >= %{packagekit_version}
 Obsoletes: gnome-software-snap < 3.33.1
 Obsoletes: gnome-software-editor < 3.35.1
 
-# this is not a library version
-%define gs_plugin_version               16
-
 %description
 gnome-software is an application that makes it easy to add, remove
 and update software in the GNOME desktop.
@@ -91,6 +105,7 @@ Requires: %{name}%{?_isa} = %{version}-%{release}
 These development files are for building gnome-software plugins outside
 the source tree. Most users do not need this subpackage installed.
 
+%if %{with rpmostree}
 %package rpm-ostree
 Summary: rpm-ostree backend for gnome-software
 Requires: %{name}%{?_isa} = %{version}-%{release}
@@ -102,18 +117,38 @@ gnome-software is an application that makes it easy to add, remove
 and update software in the GNOME desktop.
 
 This package includes the rpm-ostree backend.
+%endif
 
 %prep
-%autosetup -p1 -n %{name}-%{tarball_version} -S gendiff
+%autosetup -p1 -S gendiff -n %{name}-%{tarball_version}
 
 %build
 %meson \
+    -Dsoup2=true \
     -Dsnap=false \
+%if %{with malcontent}
+    -Dmalcontent=true \
+%else
     -Dmalcontent=false \
+%endif
     -Dgudev=true \
     -Dpackagekit=true \
+    -Dpackagekit_autoremove=true \
     -Dexternal_appstream=false \
+%if %{with rpmostree}
     -Drpm_ostree=true \
+%else
+    -Drpm_ostree=false \
+%endif
+%if %{with webapps}
+    -Dwebapps=true \
+    -Dhardcoded_foss_webapps=true \
+    -Dhardcoded_proprietary_webapps=false \
+%else
+    -Dwebapps=false \
+    -Dhardcoded_foss_webapps=false \
+    -Dhardcoded_proprietary_webapps=false \
+%endif
     -Dtests=false
 %meson_build
 
@@ -135,6 +170,7 @@ official-repos = [ 'rhel-%{?rhel}' ]
 %else
 official-repos = [ 'anaconda', 'fedora', 'fedora-debuginfo', 'fedora-source', 'koji-override-0', 'koji-override-1', 'rawhide', 'rawhide-debuginfo', 'rawhide-source', 'updates', 'updates-debuginfo', 'updates-source', 'updates-testing', 'updates-testing-debuginfo', 'updates-testing-source', 'fedora-modular', 'fedora-modular-debuginfo', 'fedora-modular-source', 'rawhide-modular', 'rawhide-modular-debuginfo', 'rawhide-modular-source', 'fedora-cisco-openh264', 'fedora-cisco-openh264-debuginfo' ]
 required-repos = [ 'fedora', 'updates' ]
+packaging-format-preference = [ 'flatpak:fedora-testing', 'flatpak:fedora', 'rpm' ]
 %endif
 FOE
 
@@ -147,44 +183,51 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
 %doc AUTHORS README.md
 %license COPYING
 %{_bindir}/gnome-software
-%{_datadir}/applications/gnome-software-local-file.desktop
+%{_datadir}/applications/gnome-software-local-file-flatpak.desktop
+%{_datadir}/applications/gnome-software-local-file-fwupd.desktop
+%{_datadir}/applications/gnome-software-local-file-packagekit.desktop
 %{_datadir}/applications/org.gnome.Software.desktop
-%dir %{_datadir}/gnome-software
-%{_datadir}/gnome-software/*.png
-%{_mandir}/man1/gnome-software.1.gz
+%{_mandir}/man1/gnome-software.1*
 %{_datadir}/icons/hicolor/*/apps/org.gnome.Software.svg
 %{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Software-symbolic.svg
 %{_datadir}/icons/hicolor/scalable/actions/app-remove-symbolic.svg
-%{_datadir}/icons/hicolor/scalable/actions/carousel-arrow-next-symbolic.svg
-%{_datadir}/icons/hicolor/scalable/actions/carousel-arrow-previous-symbolic.svg
-%{_datadir}/icons/hicolor/scalable/status/software-installed-symbolic.svg
-%{_datadir}/metainfo/org.gnome.Software.appdata.xml
+%{_datadir}/metainfo/org.gnome.Software.metainfo.xml
+%if %{with webapps}
+%{_datadir}/metainfo/org.gnome.Software.Plugin.Epiphany.metainfo.xml
+%endif
 %{_datadir}/metainfo/org.gnome.Software.Plugin.Flatpak.metainfo.xml
 %{_datadir}/metainfo/org.gnome.Software.Plugin.Fwupd.metainfo.xml
 %dir %{_libdir}/gnome-software/plugins-%{gs_plugin_version}
 %{_libdir}/gnome-software/libgnomesoftware.so.%{gs_plugin_version}
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_appstream.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_dummy.so
+%if %{with webapps}
+%{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_epiphany.so
+%endif
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_fedora-langpacks.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_fedora-pkgdb-collections.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_flatpak.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_fwupd.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_generic-updates.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_hardcoded-blocklist.so
-%{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_hardcoded-popular.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_icons.so
+%if %{with malcontent}
+%{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_malcontent.so
+%endif
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_modalias.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_os-release.so
-%{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_packagekit-refine-repos.so
-%{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_packagekit-refresh.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_packagekit.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_provenance-license.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_provenance.so
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_repos.so
-%{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_rewrite-resource.so
-%{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_systemd-updates.so
-%{_sysconfdir}/xdg/autostart/gnome-software-service.desktop
-%{_datadir}/app-info/xmls/org.gnome.Software.Featured.xml
+%{_sysconfdir}/xdg/autostart/org.gnome.Software.desktop
+%dir %{_datadir}/swcatalog
+%dir %{_datadir}/swcatalog/xml
+%if %{with webapps}
+%{_datadir}/swcatalog/xml/gnome-pwa-list-foss.xml
+%endif
+%{_datadir}/swcatalog/xml/org.gnome.Software.Curated.xml
+%{_datadir}/swcatalog/xml/org.gnome.Software.Featured.xml
 %{_datadir}/dbus-1/services/org.freedesktop.PackageKit.service
 %{_datadir}/dbus-1/services/org.gnome.Software.service
 %{_datadir}/gnome-shell/search-providers/org.gnome.Software-search-provider.ini
@@ -193,17 +236,27 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
 %{_libexecdir}/gnome-software-cmd
 %{_libexecdir}/gnome-software-restarter
 
+%if %{with rpmostree}
 %files rpm-ostree
 %{_libdir}/gnome-software/plugins-%{gs_plugin_version}/libgs_plugin_rpm-ostree.so
+%endif
 
 %files devel
 %{_libdir}/pkgconfig/gnome-software.pc
 %dir %{_includedir}/gnome-software
 %{_includedir}/gnome-software/*.h
 %{_libdir}/gnome-software/libgnomesoftware.so
-%{_datadir}/gtk-doc/html/gnome-software
+%dir %{_datadir}/gtk-doc
+%dir %{_datadir}/gtk-doc/html
+%{_datadir}/gtk-doc/html/gnome-software/
 
 %changelog
+* Mon May 27 2024 Milan Crha <mcrha@redhat.com> - 45.3-3
+- Resolves: RHEL-22268 (Prefer VENDOR_NAME in app origin)
+
+* Mon May 06 2024 Milan Crha <mcrha@redhat.com> - 45.3-2
+- Resolves: RHEL-843 (Rebase GNOME Software to its GNOME 45 version)
+
 * Thu Aug 03 2023 Milan Crha <mcrha@redhat.com> - 41.5-3
 - Resolves: #2228374 (Rebuild to move gnome-software-devel into CRB)