666 lines
26 KiB
Diff
666 lines
26 KiB
Diff
From 429ec744e6cdf2155772d7db463ca193231facdc Mon Sep 17 00:00:00 2001
|
|
From: Milan Crha <mcrha@redhat.com>
|
|
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 <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
|
|
|