[gnome-software] trivial: Allow deduplicating using the provides ID as additional keys



commit 3c6509b5254c9572681ae53e34b82183be4067ce
Author: Richard Hughes <richard hughsie com>
Date:   Fri Sep 28 11:30:32 2018 +0100

    trivial: Allow deduplicating using the provides ID as additional keys
    
    This allows us to deduplicate firefox.desktop and org.mozilla.Firefox

 lib/gs-app-list-private.h |   2 +
 lib/gs-app-list.c         | 115 +++++++++++++++++++++++++++++-----------------
 lib/gs-self-test.c        |  24 +++++++++-
 3 files changed, 97 insertions(+), 44 deletions(-)
---
diff --git a/lib/gs-app-list-private.h b/lib/gs-app-list-private.h
index 30223f97..0ae8405f 100644
--- a/lib/gs-app-list-private.h
+++ b/lib/gs-app-list-private.h
@@ -55,6 +55,7 @@ typedef enum {
  * @GS_APP_LIST_FILTER_FLAG_KEY_SOURCE:                Filter by default source
  * @GS_APP_LIST_FILTER_FLAG_KEY_VERSION:       Filter by version
  * @GS_APP_LIST_FILTER_FLAG_PREFER_INSTALLED:  Prefer installed applications
+ * @GS_APP_LIST_FILTER_FLAG_KEY_ID_PROVIDES:   Filter using the provides ID
  *
  * Flags to use when filtering. The priority of eash #GsApp is used to choose
  * which application object to keep.
@@ -65,6 +66,7 @@ typedef enum {
        GS_APP_LIST_FILTER_FLAG_KEY_SOURCE      = 1 << 1,
        GS_APP_LIST_FILTER_FLAG_KEY_VERSION     = 1 << 2,
        GS_APP_LIST_FILTER_FLAG_PREFER_INSTALLED= 1 << 3,
+       GS_APP_LIST_FILTER_FLAG_KEY_ID_PROVIDES = 1 << 4,
        /*< private >*/
        GS_APP_LIST_FILTER_FLAG_LAST
 } GsAppListFilterFlags;
diff --git a/lib/gs-app-list.c b/lib/gs-app-list.c
index 640e1301..eab044d9 100644
--- a/lib/gs-app-list.c
+++ b/lib/gs-app-list.c
@@ -742,6 +742,55 @@ gs_app_list_filter_app_is_better (GsApp *app, GsApp *found, GsAppListFilterFlags
        return FALSE;
 }
 
+static GPtrArray *
+gs_app_list_filter_app_get_keys (GsApp *app, GsAppListFilterFlags flags)
+{
+       GPtrArray *keys = g_ptr_array_new_with_free_func (g_free);
+       g_autoptr(GString) key = NULL;
+
+       /* just use the unique ID */
+       if (flags == GS_APP_LIST_FILTER_FLAG_NONE) {
+               if (gs_app_get_unique_id (app) != NULL)
+                       g_ptr_array_add (keys, g_strdup (gs_app_get_unique_id (app)));
+               return keys;
+       }
+
+       /* use the ID and any provides */
+       if (flags & GS_APP_LIST_FILTER_FLAG_KEY_ID_PROVIDES) {
+               GPtrArray *provides = gs_app_get_provides (app);
+               g_ptr_array_add (keys, g_strdup (gs_app_get_id (app)));
+               for (guint i = 0; i < provides->len; i++) {
+                       AsProvide *prov = g_ptr_array_index (provides, i);
+                       if (as_provide_get_kind (prov) != AS_PROVIDE_KIND_ID)
+                               continue;
+                       g_ptr_array_add (keys, g_strdup (as_provide_get_value (prov)));
+               }
+               return keys;
+       }
+
+       /* specific compound type */
+       key = g_string_new (NULL);
+       if (flags & GS_APP_LIST_FILTER_FLAG_KEY_ID) {
+               const gchar *tmp = gs_app_get_id (app);
+               if (tmp != NULL)
+                       g_string_append (key, gs_app_get_id (app));
+       }
+       if (flags & GS_APP_LIST_FILTER_FLAG_KEY_SOURCE) {
+               const gchar *tmp = gs_app_get_source_default (app);
+               if (tmp != NULL)
+                       g_string_append_printf (key, ":%s", tmp);
+       }
+       if (flags & GS_APP_LIST_FILTER_FLAG_KEY_VERSION) {
+               const gchar *tmp = gs_app_get_version (app);
+               if (tmp != NULL)
+                       g_string_append_printf (key, ":%s", tmp);
+       }
+       if (key->len == 0)
+               return keys;
+       g_ptr_array_add (keys, g_string_free (g_steal_pointer (&key), FALSE));
+       return keys;
+}
+
 /**
  * gs_app_list_filter_duplicates:
  * @list: A #GsAppList
@@ -769,43 +818,25 @@ gs_app_list_filter_duplicates (GsAppList *list, GsAppListFilterFlags flags)
        kept_apps = g_hash_table_new (g_direct_hash, g_direct_equal);
 
        for (guint i = 0; i < list->array->len; i++) {
-               GsApp *app;
-               GsApp *found;
-               g_autoptr(GString) key = NULL;
-
-               app = gs_app_list_index (list, i);
-               if (flags == GS_APP_LIST_FILTER_FLAG_NONE) {
-                       key = g_string_new (gs_app_get_unique_id (app));
-               } else {
-                       key = g_string_new (NULL);
-                       if (flags & GS_APP_LIST_FILTER_FLAG_KEY_ID) {
-                               const gchar *tmp = gs_app_get_id (app);
-                               if (tmp != NULL)
-                                       g_string_append (key, gs_app_get_id (app));
-                       }
-                       if (flags & GS_APP_LIST_FILTER_FLAG_KEY_SOURCE) {
-                               const gchar *tmp = gs_app_get_source_default (app);
-                               if (tmp != NULL)
-                                       g_string_append_printf (key, ":%s", tmp);
-                       }
-                       if (flags & GS_APP_LIST_FILTER_FLAG_KEY_VERSION) {
-                               const gchar *tmp = gs_app_get_version (app);
-                               if (tmp != NULL)
-                                       g_string_append_printf (key, ":%s", tmp);
-                       }
-               }
-               if (key->len == 0) {
-                       g_autofree gchar *str = gs_app_to_string (app);
-                       g_debug ("adding without deduplication as no app key: %s", str);
-                       g_hash_table_add (kept_apps, app);
-                       continue;
+               GsApp *app = gs_app_list_index (list, i);
+               GsApp *found = NULL;
+               g_autoptr(GPtrArray) keys = NULL;
+
+               /* get all the keys used to identify this app */
+               keys = gs_app_list_filter_app_get_keys (app, flags);
+               for (guint j = 0; j < keys->len; j++) {
+                       const gchar *key = g_ptr_array_index (keys, j);
+                       found = g_hash_table_lookup (hash, key);
+                       if (found != NULL)
+                               break;
                }
-               found = g_hash_table_lookup (hash, key->str);
+
+               /* new app */
                if (found == NULL) {
-                       g_debug ("found new %s", key->str);
-                       g_hash_table_insert (hash,
-                                            g_strdup (key->str),
-                                            app);
+                       for (guint j = 0; j < keys->len; j++) {
+                               const gchar *key = g_ptr_array_index (keys, j);
+                               g_hash_table_insert (hash, g_strdup (key), app);
+                       }
                        g_hash_table_add (kept_apps, app);
                        continue;
                }
@@ -813,24 +844,22 @@ gs_app_list_filter_duplicates (GsAppList *list, GsAppListFilterFlags flags)
                /* better? */
                if (flags != GS_APP_LIST_FILTER_FLAG_NONE) {
                        if (gs_app_list_filter_app_is_better (app, found, flags)) {
-                               g_debug ("using better %s (priority %u > %u)",
-                                        key->str,
+                               g_debug ("using better (priority %u > %u)",
                                         gs_app_get_priority (app),
                                         gs_app_get_priority (found));
-                               g_hash_table_insert (hash,
-                                                    g_strdup (key->str),
-                                                    app);
+                               for (guint j = 0; j < keys->len; j++) {
+                                       const gchar *key = g_ptr_array_index (keys, j);
+                                       g_hash_table_insert (hash, g_strdup (key), app);
+                               }
                                g_hash_table_remove (kept_apps, found);
                                g_hash_table_add (kept_apps, app);
                                continue;
                        }
-                       g_debug ("ignoring worse duplicate %s (priority %u > %u)",
-                                key->str,
+                       g_debug ("ignoring worse duplicate (priority %u > %u)",
                                 gs_app_get_priority (app),
                                 gs_app_get_priority (found));
                        continue;
                }
-               g_debug ("ignoring duplicate %s", key->str);
                continue;
        }
 
diff --git a/lib/gs-self-test.c b/lib/gs-self-test.c
index fb44124a..b60e0491 100644
--- a/lib/gs-self-test.c
+++ b/lib/gs-self-test.c
@@ -271,6 +271,7 @@ gs_plugin_func (void)
        GsAppList *list_dup;
        GsAppList *list_remove;
        GsApp *app;
+       g_autoptr(AsProvide) prov = as_provide_new ();
 
        /* check enums converted */
        for (guint i = 0; i < GS_PLUGIN_ACTION_LAST; i++) {
@@ -436,12 +437,33 @@ gs_plugin_func (void)
        gs_app_list_add (list, app);
        g_object_unref (app);
        gs_app_list_filter_duplicates (list,
-                                      GS_APP_LIST_FILTER_FLAG_KEY_ID|
+                                      GS_APP_LIST_FILTER_FLAG_KEY_ID |
                                       GS_APP_LIST_FILTER_FLAG_PREFER_INSTALLED);
        g_assert_cmpint (gs_app_list_length (list), ==, 1);
        g_assert_cmpstr (gs_app_get_unique_id (gs_app_list_index (list, 0)), ==, "user/foo/*/*/e/*");
        g_object_unref (list);
 
+       /* use the provides ID to dedupe */
+       list = gs_app_list_new ();
+       app = gs_app_new ("gimp.desktop");
+       gs_app_set_unique_id (app, "user/fedora/*/*/gimp.desktop/*");
+       gs_app_set_priority (app, 0);
+       gs_app_list_add (list, app);
+       g_object_unref (app);
+       app = gs_app_new ("org.gimp.GIMP");
+       as_provide_set_kind (prov, AS_PROVIDE_KIND_ID);
+       as_provide_set_value (prov, "gimp.desktop");
+       gs_app_add_provide (app, prov);
+       gs_app_set_unique_id (app, "user/flathub/*/*/org.gimp.GIMP/*");
+       gs_app_set_priority (app, 100);
+       gs_app_list_add (list, app);
+       g_object_unref (app);
+       gs_app_list_filter_duplicates (list, GS_APP_LIST_FILTER_FLAG_KEY_ID_PROVIDES);
+       g_assert_cmpint (gs_app_list_length (list), ==, 1);
+       g_assert_cmpstr (gs_app_get_unique_id (gs_app_list_index (list, 0)), ==,
+                        "user/flathub/*/*/org.gimp.GIMP/*");
+       g_object_unref (list);
+
        /* use globs when adding */
        list = gs_app_list_new ();
        app = gs_app_new ("b");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]