From 429ec744e6cdf2155772d7db463ca193231facdc Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Tue, 21 Sep 2021 14:53:27 +0200 Subject: gs-repos-dialog: Cannot disable all 3rd-party repositories All the 3rd-party repositories should be disable-able, thus the 3rd-party section should not use the heuristics to disallow disable of some of them. This could be seen on a 'flathub' Flatpak repository installed for the system, which is not allowed to be disabled in the Flatpak section. diff --git a/src/gs-repo-row.c b/src/gs-repo-row.c index 57493c2c..7df24e0e 100644 --- a/src/gs-repo-row.c +++ b/src/gs-repo-row.c @@ -27,6 +27,7 @@ typedef struct guint busy_counter; gboolean supports_remove; gboolean supports_enable_disable; + gboolean always_allow_enable_disable; } GsRepoRowPrivate; G_DEFINE_TYPE_WITH_PRIVATE (GsRepoRow, gs_repo_row, GTK_TYPE_LIST_BOX_ROW) @@ -86,7 +87,7 @@ refresh_ui (GsRepoRow *row) is_system_repo = gs_app_has_quirk (priv->repo, GS_APP_QUIRK_PROVENANCE); /* Disable for the system repos, if installed */ - gtk_widget_set_sensitive (priv->disable_switch, priv->supports_enable_disable && (state_sensitive || !is_system_repo)); + 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); /* Set only the 'state' to visually indicate the state is not saved yet */ @@ -337,13 +338,30 @@ gs_repo_row_class_init (GsRepoRowClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, disable_switch); } +/* + * gs_repo_row_new: + * @plugin_loader: a #GsPluginLoader + * @repo: a #GsApp to represent the repo in the new row + * @always_allow_enable_disable: always allow enabled/disable of the @repo + * + * The @plugin_loader is used to check which operations the associated plugin + * for the @repo can do and which not, to show only relevant buttons on the row. + * + * The @always_allow_enable_disable, when %TRUE, means that the @repo in this row + * can be always enabled/disabled by the user, if supported by the related plugin, + * regardless of the other heuristics, which can avoid the repo enable/disable. + * + * Returns: (transfer full): a newly created #GsRepoRow + */ GtkWidget * gs_repo_row_new (GsPluginLoader *plugin_loader, - GsApp *repo) + GsApp *repo, + gboolean always_allow_enable_disable) { GsRepoRow *row = g_object_new (GS_TYPE_REPO_ROW, NULL); GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); priv->plugin_loader = g_object_ref (plugin_loader); + priv->always_allow_enable_disable = always_allow_enable_disable; gs_repo_row_set_repo (row, repo); return GTK_WIDGET (row); } diff --git a/src/gs-repo-row.h b/src/gs-repo-row.h index e6f24bc8..83c8cdf4 100644 --- a/src/gs-repo-row.h +++ b/src/gs-repo-row.h @@ -25,7 +25,8 @@ struct _GsRepoRowClass }; GtkWidget *gs_repo_row_new (GsPluginLoader *plugin_loader, - GsApp *repo); + GsApp *repo, + gboolean always_allow_enable_disable); GsApp *gs_repo_row_get_repo (GsRepoRow *row); void gs_repo_row_mark_busy (GsRepoRow *row); void gs_repo_row_unmark_busy (GsRepoRow *row); diff --git a/src/gs-repos-dialog.c b/src/gs-repos-dialog.c index 98aa0f20..0f24149c 100644 --- a/src/gs-repos-dialog.c +++ b/src/gs-repos-dialog.c @@ -484,7 +484,7 @@ add_repo (GsReposDialog *dialog, origin_ui = g_strdup (gs_app_get_management_plugin (repo)); section = g_hash_table_lookup (dialog->sections, origin_ui); if (section == NULL) { - section = gs_repos_section_new (dialog->plugin_loader); + section = gs_repos_section_new (dialog->plugin_loader, FALSE); hdy_preferences_group_set_title (HDY_PREFERENCES_GROUP (section), origin_ui); g_signal_connect_object (section, "remove-clicked", @@ -627,7 +627,7 @@ get_sources_cb (GsPluginLoader *plugin_loader, gtk_container_add (GTK_CONTAINER (widget), row); gtk_container_add (GTK_CONTAINER (dialog->content_page), widget); - section = GS_REPOS_SECTION (gs_repos_section_new (dialog->plugin_loader)); + section = GS_REPOS_SECTION (gs_repos_section_new (dialog->plugin_loader, TRUE)); gs_repos_section_set_sort_key (section, "900"); g_signal_connect_object (section, "switch-clicked", G_CALLBACK (repo_section_switch_clicked_cb), dialog, 0); diff --git a/src/gs-repos-section.c b/src/gs-repos-section.c index 3bf59ad7..a9b08200 100644 --- a/src/gs-repos-section.c +++ b/src/gs-repos-section.c @@ -20,6 +20,7 @@ struct _GsReposSection GtkListBox *list; GsPluginLoader *plugin_loader; gchar *sort_key; + gboolean always_allow_enable_disable; }; G_DEFINE_TYPE (GsReposSection, gs_repos_section, HDY_TYPE_PREFERENCES_GROUP) @@ -130,8 +131,23 @@ gs_repos_section_init (GsReposSection *self) G_CALLBACK (gs_repos_section_row_activated_cb), self); } +/* + * gs_repos_section_new: + * @plugin_loader: a #GsPluginLoader + * @always_allow_enable_disable: always allow enable/disable of the repos in this section + * + * Creates a new #GsReposSection. The %plugin_loader is passed + * to each #GsRepoRow, the same as the @always_allow_enable_disable. + * + * The @always_allow_enable_disable, when %TRUE, means that every repo in this section + * can be enabled/disabled by the user, if supported by the related plugin, regardless + * of the other heuristics, which can avoid the repo enable/disable. + * + * Returns: (transfer full): a newly created #GsReposSection + */ GtkWidget * -gs_repos_section_new (GsPluginLoader *plugin_loader) +gs_repos_section_new (GsPluginLoader *plugin_loader, + gboolean always_allow_enable_disable) { GsReposSection *self; @@ -140,6 +156,7 @@ gs_repos_section_new (GsPluginLoader *plugin_loader) self = g_object_new (GS_TYPE_REPOS_SECTION, NULL); self->plugin_loader = g_object_ref (plugin_loader); + self->always_allow_enable_disable = always_allow_enable_disable; return GTK_WIDGET (self); } @@ -159,7 +176,7 @@ gs_repos_section_add_repo (GsReposSection *self, if (!self->sort_key) self->sort_key = g_strdup (gs_app_get_metadata_item (repo, "GnomeSoftware::SortKey")); - row = gs_repo_row_new (self->plugin_loader, repo); + row = gs_repo_row_new (self->plugin_loader, repo, self->always_allow_enable_disable); g_signal_connect (row, "remove-clicked", G_CALLBACK (repo_remove_clicked_cb), self); diff --git a/src/gs-repos-section.h b/src/gs-repos-section.h index 6e29769c..9a58a3e1 100644 --- a/src/gs-repos-section.h +++ b/src/gs-repos-section.h @@ -20,7 +20,8 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (GsReposSection, gs_repos_section, GS, REPOS_SECTION, HdyPreferencesGroup) -GtkWidget *gs_repos_section_new (GsPluginLoader *plugin_loader); +GtkWidget *gs_repos_section_new (GsPluginLoader *plugin_loader, + gboolean always_allow_enable_disable); void gs_repos_section_add_repo (GsReposSection *self, GsApp *repo); const gchar *gs_repos_section_get_title (GsReposSection *self); 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