[gnome-software] trivial: Respect priority when deduplicating apps
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] trivial: Respect priority when deduplicating apps
- Date: Mon, 27 Jun 2016 11:14:29 +0000 (UTC)
commit 2ad174ced7bf36f5c478b7c0834cbbd61de9c424
Author: Richard Hughes <richard hughsie com>
Date: Mon Jun 27 10:38:52 2016 +0100
trivial: Respect priority when deduplicating apps
src/gs-app-list-private.h | 17 ++++++++++++-
src/gs-app-list.c | 60 ++++++++++++++++++++++++++++++++++----------
src/gs-plugin-loader.c | 55 ++++++++++++++++++++++++++++------------
src/gs-self-test.c | 22 +++++++++++++++-
4 files changed, 121 insertions(+), 33 deletions(-)
---
diff --git a/src/gs-app-list-private.h b/src/gs-app-list-private.h
index 5ee70e8..96e0769 100644
--- a/src/gs-app-list-private.h
+++ b/src/gs-app-list-private.h
@@ -26,6 +26,20 @@
G_BEGIN_DECLS
+/**
+ * GsAppListFilterFlags:
+ * @GS_APP_LIST_FILTER_FLAG_NONE: No flags set
+ * @GS_APP_LIST_FILTER_FLAG_PRIORITY: Filter by application priority
+ *
+ * Flags to use when filtering.
+ **/
+typedef enum {
+ GS_APP_LIST_FILTER_FLAG_NONE = 0,
+ GS_APP_LIST_FILTER_FLAG_PRIORITY = 1 << 0,
+ /*< private >*/
+ GS_APP_LIST_FILTER_FLAG_LAST
+} GsAppListFilterFlags;
+
typedef gboolean (*GsAppListFilterFunc) (GsApp *app,
gpointer user_data);
typedef gboolean (*GsAppListSortFunc) (GsApp *app1,
@@ -39,7 +53,8 @@ void gs_app_list_filter (GsAppList *list,
void gs_app_list_sort (GsAppList *list,
GsAppListSortFunc func,
gpointer user_data);
-void gs_app_list_filter_duplicates (GsAppList *list);
+void gs_app_list_filter_duplicates (GsAppList *list,
+ GsAppListFilterFlags flags);
void gs_app_list_randomize (GsAppList *list);
void gs_app_list_remove_all (GsAppList *list);
diff --git a/src/gs-app-list.c b/src/gs-app-list.c
index f0858c1..238ff90 100644
--- a/src/gs-app-list.c
+++ b/src/gs-app-list.c
@@ -33,6 +33,7 @@
#include <glib.h>
+#include "gs-app-private.h"
#include "gs-app-list-private.h"
struct _GsAppList
@@ -254,38 +255,69 @@ gs_app_list_randomize (GsAppList *list)
* Filter any duplicate applications from the list.
**/
void
-gs_app_list_filter_duplicates (GsAppList *list)
+gs_app_list_filter_duplicates (GsAppList *list, GsAppListFilterFlags flags)
{
guint i;
GsApp *app;
GsApp *found;
const gchar *id;
g_autoptr(GHashTable) hash = NULL;
- g_autoptr(GsAppList) old = NULL;
+ g_autoptr(GList) values = NULL;
+ GList *l;
g_return_if_fail (GS_IS_APP_LIST (list));
- /* deep copy to a temp list and clear the current one */
- old = gs_app_list_copy (list);
- gs_app_list_remove_all (list);
-
/* create a new list with just the unique items */
- hash = g_hash_table_new (g_str_hash, g_str_equal);
- for (i = 0; i < old->array->len; i++) {
- app = gs_app_list_index (old, i);
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_object_unref);
+ for (i = 0; i < list->array->len; i++) {
+ app = gs_app_list_index (list, i);
id = gs_app_get_id (app);
+ if (flags & GS_APP_LIST_FILTER_FLAG_PRIORITY)
+ id = gs_app_get_id_no_prefix (app);
if (id == NULL) {
- gs_app_list_add (list, app);
+ g_autofree gchar *str = gs_app_to_string (app);
+ g_debug ("ignoring as no application id for: %s", str);
continue;
}
found = g_hash_table_lookup (hash, id);
if (found == NULL) {
- gs_app_list_add (list, app);
- g_hash_table_insert (hash, (gpointer) id,
- GUINT_TO_POINTER (1));
+ g_debug ("found new %s", gs_app_get_id (app));
+ g_hash_table_insert (hash,
+ g_strdup (id),
+ g_object_ref (app));
+ continue;
+ }
+
+ /* better? */
+ if (flags & GS_APP_LIST_FILTER_FLAG_PRIORITY) {
+ if (gs_app_get_priority (app) >
+ gs_app_get_priority (found)) {
+ g_debug ("using better %s (priority %u > %u)",
+ gs_app_get_id (app),
+ gs_app_get_priority (app),
+ gs_app_get_priority (found));
+ g_hash_table_insert (hash,
+ g_strdup (id),
+ g_object_ref (app));
+ continue;
+ }
+ g_debug ("ignoring worse duplicate %s (priority %u > %u)",
+ gs_app_get_id (app),
+ gs_app_get_priority (app),
+ gs_app_get_priority (found));
continue;
}
- g_debug ("ignoring duplicate %s", id);
+ g_debug ("ignoring duplicate %s", gs_app_get_id (app));
+ continue;
+ }
+
+ /* add back the best results to the existing list */
+ gs_app_list_remove_all (list);
+ values = g_hash_table_get_values (hash);
+ for (l = values; l != NULL; l = l->next) {
+ app = GS_APP (l->data);
+ gs_app_list_add (list, app);
}
}
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index b4f56a9..e233f54 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -639,9 +639,6 @@ gs_plugin_loader_run_results (GsPluginLoader *plugin_loader,
return NULL;
}
- /* filter package list */
- gs_app_list_filter_duplicates (list);
-
return g_steal_pointer (&list);
}
@@ -1091,13 +1088,13 @@ gs_plugin_loader_get_updates_thread_cb (GTask *task,
return;
}
- /* filter package list */
- gs_app_list_filter_duplicates (state->list);
-
/* remove any packages that are not proper applications or
* OS updates */
gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
+
+ /* filter duplicates with priority */
gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_NONE);
/* success */
g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1191,8 +1188,9 @@ gs_plugin_loader_get_distro_upgrades_thread_cb (GTask *task,
return;
}
- /* filter package list */
- gs_app_list_filter_duplicates (state->list);
+ /* filter duplicates with priority */
+ gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_NONE);
/* success */
g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1270,8 +1268,9 @@ gs_plugin_loader_get_unvoted_reviews_thread_cb (GTask *task,
return;
}
- /* filter package list */
- gs_app_list_filter_duplicates (state->list);
+ /* filter duplicates with priority */
+ gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_NONE);
/* success */
g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1349,8 +1348,9 @@ gs_plugin_loader_get_sources_thread_cb (GTask *task,
return;
}
- /* filter package list */
- gs_app_list_filter_duplicates (state->list);
+ /* filter duplicates with priority */
+ gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_NONE);
/* success */
g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1551,7 +1551,10 @@ gs_plugin_loader_get_popular_thread_cb (GTask *task,
gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
gs_app_list_filter (state->list, gs_plugin_loader_filter_qt_for_gtk, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_get_app_is_compatible, plugin_loader);
+
+ /* filter duplicates with priority */
gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_PRIORITY);
/* success */
g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1646,7 +1649,10 @@ gs_plugin_loader_get_featured_thread_cb (GTask *task,
gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
gs_app_list_filter (state->list, gs_plugin_loader_get_app_is_compatible, plugin_loader);
}
+
+ /* filter duplicates with priority */
gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_PRIORITY);
/* success */
g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1864,11 +1870,15 @@ gs_plugin_loader_search_thread_cb (GTask *task,
gs_plugin_loader_convert_unavailable (state->list, state->value);
/* filter package list */
- gs_app_list_filter_duplicates (state->list);
gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
gs_app_list_filter (state->list, gs_plugin_loader_filter_qt_for_gtk, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_get_app_is_compatible, plugin_loader);
+
+ /* filter duplicates with priority */
gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_NONE);
+
+ /* too many */
if (gs_app_list_length (state->list) > 500) {
g_task_return_new_error (task,
GS_PLUGIN_ERROR,
@@ -2027,12 +2037,16 @@ gs_plugin_loader_search_files_thread_cb (GTask *task,
gs_plugin_loader_convert_unavailable (state->list, state->value);
/* filter package list */
- gs_app_list_filter_duplicates (state->list);
gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
gs_app_list_filter (state->list, gs_plugin_loader_app_is_non_installed, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_filter_qt_for_gtk, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_get_app_is_compatible, plugin_loader);
+
+ /* filter duplicates with priority */
gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_NONE);
+
+ /* too many */
if (gs_app_list_length (state->list) > 500) {
g_task_return_new_error (task,
GS_PLUGIN_ERROR,
@@ -2191,12 +2205,16 @@ gs_plugin_loader_search_what_provides_thread_cb (GTask *task,
gs_plugin_loader_convert_unavailable (state->list, state->value);
/* filter package list */
- gs_app_list_filter_duplicates (state->list);
gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
gs_app_list_filter (state->list, gs_plugin_loader_app_is_non_installed, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_filter_qt_for_gtk, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_get_app_is_compatible, plugin_loader);
+
+ /* filter duplicates with priority */
gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_NONE);
+
+ /* too many */
if (gs_app_list_length (state->list) > 500) {
g_task_return_new_error (task,
GS_PLUGIN_ERROR,
@@ -2534,12 +2552,14 @@ gs_plugin_loader_get_category_apps_thread_cb (GTask *task,
}
/* filter package list */
- gs_app_list_filter_duplicates (state->list);
gs_app_list_filter (state->list, gs_plugin_loader_app_is_non_compulsory, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
gs_app_list_filter (state->list, gs_plugin_loader_filter_qt_for_gtk, NULL);
gs_app_list_filter (state->list, gs_plugin_loader_get_app_is_compatible, plugin_loader);
+
+ /* filter duplicates with priority */
gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_PRIORITY);
/* sort, just in case the UI doesn't do this */
gs_app_list_sort (state->list, gs_plugin_loader_app_sort_cb, NULL);
@@ -4367,7 +4387,8 @@ gs_plugin_loader_file_to_app_thread_cb (GTask *task,
}
/* filter package list */
- gs_app_list_filter_duplicates (state->list);
+ gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (state->list, GS_APP_LIST_FILTER_FLAG_PRIORITY);
/* check the apps have an icon set */
for (j = 0; j < gs_app_list_length (state->list); j++) {
diff --git a/src/gs-self-test.c b/src/gs-self-test.c
index f02fd2f..00c2908 100644
--- a/src/gs-self-test.c
+++ b/src/gs-self-test.c
@@ -141,9 +141,29 @@ gs_plugin_func (void)
gs_app_set_id (app, "e");
g_object_unref (app);
g_assert_cmpint (gs_app_list_length (list_remove), ==, 2);
- gs_app_list_filter_duplicates (list_remove);
+ gs_app_list_filter_duplicates (list_remove, GS_APP_LIST_FILTER_FLAG_NONE);
g_assert_cmpint (gs_app_list_length (list_remove), ==, 1);
g_object_unref (list_remove);
+
+ /* respect priority when deduplicating */
+ list = gs_app_list_new ();
+ app = gs_app_new ("foo:e");
+ gs_app_list_add (list, app);
+ gs_app_set_priority (app, 0);
+ g_object_unref (app);
+ app = gs_app_new ("bar:e");
+ gs_app_list_add (list, app);
+ gs_app_set_priority (app, 99);
+ g_object_unref (app);
+ app = gs_app_new ("baz:e");
+ gs_app_list_add (list, app);
+ gs_app_set_priority (app, 50);
+ g_object_unref (app);
+ g_assert_cmpint (gs_app_list_length (list), ==, 3);
+ gs_app_list_filter_duplicates (list, GS_APP_LIST_FILTER_FLAG_PRIORITY);
+ g_assert_cmpint (gs_app_list_length (list), ==, 1);
+ g_assert_cmpstr (gs_app_get_id (gs_app_list_index (list, 0)), ==, "bar:e");
+ g_object_unref (list);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]