[gnome-software: 5/11] snap: Port gs_plugin_add_alternates() vfunc to GsPluginJobListApps




commit cdaa11b6fe08567ade638992289b45cc9efda681
Author: Philip Withnall <pwithnall endlessos org>
Date:   Wed Jul 6 15:22:12 2022 +0100

    snap: Port gs_plugin_add_alternates() vfunc to GsPluginJobListApps
    
    This is a bit complex and has not been tested at runtime (only
    compile-tested), as I don’t have a snap setup.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>

 plugins/snap/gs-plugin-snap.c | 235 +++++++++++++++++++++++++++++++++---------
 1 file changed, 184 insertions(+), 51 deletions(-)
---
diff --git a/plugins/snap/gs-plugin-snap.c b/plugins/snap/gs-plugin-snap.c
index a36dbb4b0..e6b1e3c6a 100644
--- a/plugins/snap/gs-plugin-snap.c
+++ b/plugins/snap/gs-plugin-snap.c
@@ -238,6 +238,20 @@ static void get_system_information_cb (GObject      *source_object,
                                        GAsyncResult *result,
                                        gpointer      user_data);
 
+static void get_store_snap_async (GsPluginSnap        *self,
+                                  SnapdClient         *client,
+                                  const gchar         *name,
+                                  gboolean             need_details,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  callback,
+                                  gpointer             user_data);
+static SnapdSnap *get_store_snap_finish (GsPluginSnap  *self,
+                                         GAsyncResult  *result,
+                                         GError       **error);
+static void add_channels (GsPluginSnap *self,
+                          SnapdSnap    *snap,
+                          GsAppList    *list);
+
 static void
 gs_plugin_snap_setup_async (GsPlugin            *plugin,
                             GCancellable        *cancellable,
@@ -555,6 +569,15 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ListAppsData, list_apps_data_free)
 static void list_installed_apps_cb (GObject      *source_object,
                                     GAsyncResult *result,
                                     gpointer      user_data);
+static void list_alternate_apps_snap_cb (GObject      *source_object,
+                                         GAsyncResult *result,
+                                         gpointer      user_data);
+static void list_alternate_apps_nonsnap_cb (GObject      *source_object,
+                                            GAsyncResult *result,
+                                            gpointer      user_data);
+static void list_alternative_apps_nonsnap_get_store_snap_cb (GObject      *source_object,
+                                                             GAsyncResult *result,
+                                                             gpointer      user_data);
 static void list_apps_cb (GObject      *source_object,
                           GAsyncResult *result,
                           gpointer      user_data);
@@ -579,6 +602,7 @@ gs_plugin_snap_list_apps_async (GsPlugin              *plugin,
        GsCategory *category = NULL;
        GsAppQueryTristate is_installed = GS_APP_QUERY_TRISTATE_UNSET;
        const gchar * const *keywords = NULL;
+       GsApp *alternate_of = NULL;
        const gchar * const *sections = NULL;
        const gchar * const curated_sections[] = { "featured", NULL };
        g_autoptr(GError) local_error = NULL;
@@ -599,6 +623,7 @@ gs_plugin_snap_list_apps_async (GsPlugin              *plugin,
                category = gs_app_query_get_category (query);
                is_installed = gs_app_query_get_is_installed (query);
                keywords = gs_app_query_get_keywords (query);
+               alternate_of = gs_app_query_get_alternate_of (query);
        }
 
        /* Currently only support a subset of query properties, and only one set at once.
@@ -606,7 +631,8 @@ gs_plugin_snap_list_apps_async (GsPlugin              *plugin,
        if ((is_curated == GS_APP_QUERY_TRISTATE_UNSET &&
             category == NULL &&
             is_installed == GS_APP_QUERY_TRISTATE_UNSET &&
-            keywords == NULL) ||
+            keywords == NULL &&
+            alternate_of == NULL) ||
            is_curated == GS_APP_QUERY_TRISTATE_FALSE ||
            is_installed == GS_APP_QUERY_TRISTATE_FALSE ||
            gs_app_query_get_n_properties_set (query) != 1) {
@@ -626,6 +652,28 @@ gs_plugin_snap_list_apps_async (GsPlugin              *plugin,
                return;
        }
 
+       /* Listing alternates also requires special handling. */
+       if (alternate_of != NULL) {
+               /* If it is a snap, find the channels that snap provides, otherwise find snaps that match on 
common id */
+               if (gs_app_has_management_plugin (alternate_of, plugin)) {
+                       const gchar *snap_name;
+
+                       snap_name = gs_app_get_metadata_item (alternate_of, "snap::name");
+
+                       data->n_pending_ops++;
+                       get_store_snap_async (self, client, snap_name, TRUE, cancellable, 
list_alternate_apps_snap_cb, g_steal_pointer (&task));
+               } else {
+                       data->n_pending_ops++;
+                       snapd_client_find_section_async (client,
+                                                        SNAPD_FIND_FLAGS_SCOPE_WIDE | 
SNAPD_FIND_FLAGS_MATCH_COMMON_ID,
+                                                        NULL, gs_app_get_id (alternate_of),
+                                                        cancellable,
+                                                        list_alternate_apps_nonsnap_cb, g_steal_pointer 
(&task));
+               }
+
+               return;
+       }
+
        /* Querying with keywords also requires calling the method differently.
         * snapd will tokenise and stem @query internally. */
        if (keywords != NULL) {
@@ -719,6 +767,78 @@ list_installed_apps_cb (GObject      *source_object,
        finish_list_apps_op (task, g_steal_pointer (&local_error));
 }
 
+static void
+list_alternate_apps_snap_cb (GObject      *source_object,
+                             GAsyncResult *result,
+                             gpointer      user_data)
+{
+       GsPluginSnap *self = GS_PLUGIN_SNAP (source_object);
+       g_autoptr(GTask) task = G_TASK (user_data);
+       ListAppsData *data = g_task_get_task_data (task);
+       g_autoptr(SnapdSnap) snap = NULL;
+       g_autoptr(GError) local_error = NULL;
+
+       snap = get_store_snap_finish (self, result, &local_error);
+
+       if (snap != NULL)
+               add_channels (self, snap, data->results_list);
+
+       finish_list_apps_op (task, g_steal_pointer (&local_error));
+}
+
+static void
+list_alternate_apps_nonsnap_cb (GObject      *source_object,
+                                GAsyncResult *result,
+                                gpointer      user_data)
+{
+       SnapdClient *client = SNAPD_CLIENT (source_object);
+       g_autoptr(GTask) task = G_TASK (user_data);
+       GsPluginSnap *self = g_task_get_source_object (task);
+       GCancellable *cancellable = g_task_get_cancellable (task);
+       ListAppsData *data = g_task_get_task_data (task);
+       g_autoptr(GPtrArray) snaps = NULL;
+       g_autoptr(GError) local_error = NULL;
+
+       snaps = snapd_client_find_section_finish (client, result, NULL, &local_error);
+
+       if (snaps == NULL) {
+               snapd_error_convert (&local_error);
+               finish_list_apps_op (task, g_steal_pointer (&local_error));
+               return;
+       }
+
+       store_snap_cache_update (self, snaps, FALSE);
+
+       for (guint i = 0; snaps != NULL && i < snaps->len; i++) {
+               SnapdSnap *snap = g_ptr_array_index (snaps, i);
+
+               data->n_pending_ops++;
+               get_store_snap_async (self, client, snapd_snap_get_name (snap),
+                                     TRUE, cancellable, list_alternative_apps_nonsnap_get_store_snap_cb, 
g_object_ref (task));
+       }
+
+       finish_list_apps_op (task, NULL);
+}
+
+static void
+list_alternative_apps_nonsnap_get_store_snap_cb (GObject      *source_object,
+                                                 GAsyncResult *result,
+                                                 gpointer      user_data)
+{
+       GsPluginSnap *self = GS_PLUGIN_SNAP (source_object);
+       g_autoptr(GTask) task = G_TASK (user_data);
+       ListAppsData *data = g_task_get_task_data (task);
+       g_autoptr(SnapdSnap) store_snap = NULL;
+       g_autoptr(GError) local_error = NULL;
+
+       store_snap = get_store_snap_finish (self, result, &local_error);
+
+       if (store_snap != NULL)
+               add_channels (self, store_snap, data->results_list);
+
+       finish_list_apps_op (task, g_steal_pointer (&local_error));
+}
+
 static void
 list_apps_cb (GObject      *source_object,
               GAsyncResult *result,
@@ -812,6 +932,69 @@ get_store_snap (GsPluginSnap  *self,
        return g_object_ref (g_ptr_array_index (snaps, 0));
 }
 
+static void get_store_snap_cb (GObject      *source_object,
+                               GAsyncResult *result,
+                               gpointer      user_data);
+
+static void
+get_store_snap_async (GsPluginSnap        *self,
+                      SnapdClient         *client,
+                      const gchar         *name,
+                      gboolean             need_details,
+                      GCancellable        *cancellable,
+                      GAsyncReadyCallback  callback,
+                      gpointer             user_data)
+{
+       g_autoptr(GTask) task = NULL;
+       SnapdSnap *snap = NULL;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+       g_task_set_source_tag (task, get_store_snap_async);
+
+       /* use cached version if available */
+       snap = store_snap_cache_lookup (self, name, need_details);
+       if (snap != NULL) {
+               g_task_return_pointer (task, g_object_ref (snap), (GDestroyNotify) g_object_unref);
+               return;
+       }
+
+       snapd_client_find_section_async (client,
+                                        SNAPD_FIND_FLAGS_SCOPE_WIDE | SNAPD_FIND_FLAGS_MATCH_NAME,
+                                        NULL, name,
+                                        cancellable,
+                                        get_store_snap_cb, g_steal_pointer (&task));
+}
+
+static void
+get_store_snap_cb (GObject      *source_object,
+                   GAsyncResult *result,
+                   gpointer      user_data)
+{
+       SnapdClient *client = SNAPD_CLIENT (source_object);
+       g_autoptr(GTask) task = g_steal_pointer (&user_data);
+       GsPluginSnap *self = g_task_get_source_object (task);
+       g_autoptr(GPtrArray) snaps = NULL;
+       g_autoptr(GError) local_error = NULL;
+
+       snaps = snapd_client_find_section_finish (client, result, NULL, &local_error);
+
+       if (snaps == NULL || snaps->len < 1) {
+               snapd_error_convert (&local_error);
+               g_task_return_error (task, g_steal_pointer (&local_error));
+       } else {
+               store_snap_cache_update (self, snaps, TRUE);
+               g_task_return_pointer (task, g_object_ref (g_ptr_array_index (snaps, 0)), (GDestroyNotify) 
g_object_unref);
+       }
+}
+
+static SnapdSnap *
+get_store_snap_finish (GsPluginSnap  *self,
+                       GAsyncResult  *result,
+                       GError       **error)
+{
+       return g_task_propagate_pointer (G_TASK (result), error);
+}
+
 static int
 track_value (const gchar *track, GStrv tracks)
 {
@@ -907,56 +1090,6 @@ add_channels (GsPluginSnap *self, SnapdSnap *snap, GsAppList *list)
        }
 }
 
-gboolean
-gs_plugin_add_alternates (GsPlugin *plugin,
-                         GsApp *app,
-                         GsAppList *list,
-                         GCancellable *cancellable,
-                         GError **error)
-{
-       GsPluginSnap *self = GS_PLUGIN_SNAP (plugin);
-       g_autoptr(SnapdClient) client = NULL;
-       gboolean interactive = gs_plugin_has_flags (plugin, GS_PLUGIN_FLAGS_INTERACTIVE);
-
-       client = get_client (self, interactive, error);
-       if (client == NULL)
-               return FALSE;
-
-       /* If it is a snap, find the channels that snap provides, otherwise find snaps that match on common 
id */
-       if (gs_app_has_management_plugin (app, plugin)) {
-               const gchar *snap_name;
-               g_autoptr(SnapdSnap) snap = NULL;
-
-               snap_name = gs_app_get_metadata_item (app, "snap::name");
-
-               snap = get_store_snap (self, client, snap_name, TRUE, cancellable, NULL);
-               if (snap == NULL) {
-                       g_warning ("Failed to get store snap %s", snap_name);
-                       return TRUE;
-               }
-
-               add_channels (self, snap, list);
-       } else {
-               g_autoptr(GPtrArray) snaps = NULL;
-               guint i;
-
-               snaps = find_snaps (self, client,
-                                   SNAPD_FIND_FLAGS_SCOPE_WIDE | SNAPD_FIND_FLAGS_MATCH_COMMON_ID,
-                                   NULL, gs_app_get_id (app), cancellable, NULL);
-               for (i = 0; snaps != NULL && i < snaps->len; i++) {
-                       SnapdSnap *snap = g_ptr_array_index (snaps, i);
-                       SnapdSnap *store_snap;
-
-                       store_snap = get_store_snap (self, client, snapd_snap_get_name (snap),
-                                                    TRUE, cancellable, NULL);
-                       add_channels (self, store_snap, list);
-               }
-               return TRUE;
-       }
-
-       return TRUE;
-}
-
 static gboolean
 app_name_matches_snap_name (SnapdSnap *snap, SnapdApp *app)
 {


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