[gnome-software: 1/2] gs-details-page: Deduplicate the origin list




commit 7e8959f7f2fd065113b94037b61f9665d09cccab
Author: Philip Withnall <pwithnall endlessos org>
Date:   Fri Mar 26 13:18:22 2021 +0000

    gs-details-page: Deduplicate the origin list
    
    If an app has been renamed, or provides the same `.desktop` file as
    another app, and has the same origin as the original app, that origin
    will appear twice in the origin list.
    
    Avoid that by deduplicating the list on the fields which are presented
    in UI.
    
    This situation won’t happen often (it’s an unlikely set of metadata to
    have, although possible). It’s reproducible with
    Chromium/UngoogledChromium though.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #1192

 src/gs-details-page.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
---
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 8723987b7..8f72f2304 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -785,6 +785,47 @@ gs_details_page_refresh_size (GsDetailsPage *self)
        }
 }
 
+static gboolean
+app_origin_equal (GsApp *a,
+                  GsApp *b)
+{
+       g_autofree gchar *a_origin_ui = NULL, *b_origin_ui = NULL;
+       GFile *a_local_file, *b_local_file;
+
+       a_origin_ui = gs_app_get_origin_ui (a);
+       b_origin_ui = gs_app_get_origin_ui (b);
+
+       a_local_file = gs_app_get_local_file (a);
+       b_local_file = gs_app_get_local_file (b);
+
+       /* Compare all the fields used in GsOriginPopoverRow. */
+       if (g_strcmp0 (a_origin_ui, b_origin_ui) != 0)
+               return FALSE;
+
+       if (!((a_local_file == NULL && b_local_file == NULL) ||
+             (a_local_file != NULL && b_local_file != NULL &&
+              g_file_equal (a_local_file, b_local_file))))
+               return FALSE;
+
+       if (g_strcmp0 (gs_app_get_origin_hostname (a),
+                      gs_app_get_origin_hostname (b)) != 0)
+               return FALSE;
+
+       if (gs_app_get_bundle_kind (a) != gs_app_get_bundle_kind (b))
+               return FALSE;
+
+       if (gs_app_get_scope (a) != gs_app_get_scope (b))
+               return FALSE;
+
+       if (g_strcmp0 (gs_app_get_branch (a), gs_app_get_branch (b)) != 0)
+               return FALSE;
+
+       if (g_strcmp0 (gs_app_get_version (a), gs_app_get_version (b)) != 0)
+               return FALSE;
+
+       return TRUE;
+}
+
 static void
 gs_details_page_get_alternates_cb (GObject *source_object,
                                    GAsyncResult *res,
@@ -822,6 +863,27 @@ gs_details_page_get_alternates_cb (GObject *source_object,
                return;
        }
 
+       /* deduplicate the list; duplicates can get in the list if
+        * get_alternates() returns the old/new version of a renamed app, which
+        * happens to come from the same origin; see
+        * https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1192
+        *
+        * This nested loop is OK as the origin list is normally only 2 or 3
+        * items long. */
+       for (guint i = 0; i < gs_app_list_length (list); i++) {
+               GsApp *i_app = gs_app_list_index (list, i);
+
+               for (guint j = i + 1; j < gs_app_list_length (list);) {
+                       GsApp *j_app = gs_app_list_index (list, j);
+
+                       if (app_origin_equal (i_app, j_app)) {
+                               gs_app_list_remove (list, j_app);
+                       } else {
+                               j++;
+                       }
+               }
+       }
+
        /* add the local file to the list so that we can carry it over when
         * switching between alternates */
        if (self->app_local_file != NULL)


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