[gnome-software/wip/hughsie/gs_app_set_priority] Add gs_app_set_priority() to allow plugins be better than others



commit 8f38b2fc44464305176c8a50d985b1a973514225
Author: Richard Hughes <richard hughsie com>
Date:   Wed Jun 8 21:11:53 2016 +0100

    Add gs_app_set_priority() to allow plugins be better than others

 src/gs-app-private.h                   |    4 +
 src/gs-app.c                           |   33 ++++++++++
 src/gs-plugin-loader.c                 |  104 ++++++++++++++++++++++++++------
 src/gs-plugin-private.h                |    3 +
 src/gs-plugin.c                        |   32 ++++++++++
 src/gs-plugin.h                        |    2 +
 src/plugins/gs-plugin-flatpak-system.c |    3 +
 src/plugins/gs-plugin-flatpak-user.c   |    3 +
 8 files changed, 165 insertions(+), 19 deletions(-)
---
diff --git a/src/gs-app-private.h b/src/gs-app-private.h
index 6d41284..53e168c 100644
--- a/src/gs-app-private.h
+++ b/src/gs-app-private.h
@@ -29,6 +29,10 @@ G_BEGIN_DECLS
 GError         *gs_app_get_last_error          (GsApp          *app);
 void            gs_app_set_last_error          (GsApp          *app,
                                                 GError         *error);
+void            gs_app_set_priority            (GsApp          *app,
+                                                guint           priority);
+guint           gs_app_get_priority            (GsApp          *app);
+
 G_END_DECLS
 
 #endif /* __GS_APP_PRIVATE_H */
diff --git a/src/gs-app.c b/src/gs-app.c
index e2ba06f..4f5eeed 100644
--- a/src/gs-app.c
+++ b/src/gs-app.c
@@ -89,6 +89,7 @@ struct _GsApp
        AsUrgencyKind            update_urgency;
        gchar                   *management_plugin;
        guint                    match_value;
+       guint                    priority;
        gint                     rating;
        GArray                  *review_ratings;
        GPtrArray               *reviews; /* of GsReview */
@@ -309,6 +310,8 @@ gs_app_to_string (GsApp *app)
        }
        if (app->match_value != 0)
                gs_app_kv_printf (str, "match-value", "%05x", app->match_value);
+       if (app->priority != 0)
+               gs_app_kv_printf (str, "priority", "%i", app->priority);
        if (app->version != NULL)
                gs_app_kv_lpad (str, "version", app->version);
        if (app->version_ui != NULL)
@@ -2608,6 +2611,36 @@ gs_app_get_match_value (GsApp *app)
 }
 
 /**
+ * gs_app_set_priority:
+ * @app: a #GsApp
+ * @priority: a value
+ *
+ * Set a priority value.
+ **/
+void
+gs_app_set_priority (GsApp *app, guint priority)
+{
+       g_return_if_fail (GS_IS_APP (app));
+       app->priority = priority;
+}
+
+/**
+ * gs_app_get_priority:
+ * @app: a #GsApp
+ *
+ * Get a priority value, where higher values will be chosen where
+ * multiple #GsApp's match a specific rule.
+ *
+ * Returns: a value, where higher is better
+ **/
+guint
+gs_app_get_priority (GsApp *app)
+{
+       g_return_val_if_fail (GS_IS_APP (app), 0);
+       return app->priority;
+}
+
+/**
  * gs_app_get_last_error:
  * @app: a #GsApp
  *
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 28e384e..8789625 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -169,6 +169,22 @@ gs_plugin_loader_app_sort_cb (GsApp *app1, GsApp *app2, gpointer user_data)
                          gs_app_get_name (app2));
 }
 
+static GsPlugin *
+gs_plugin_loader_find_plugin (GsPluginLoader *plugin_loader,
+                             const gchar *plugin_name)
+{
+       GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
+       GsPlugin *plugin;
+       guint i;
+
+       for (i = 0; i < priv->plugins->len; i++) {
+               plugin = g_ptr_array_index (priv->plugins, i);
+               if (g_strcmp0 (gs_plugin_get_name (plugin), plugin_name) == 0)
+                       return plugin;
+       }
+       return NULL;
+}
+
 /**
  * gs_plugin_loader_action_start:
  **/
@@ -622,6 +638,24 @@ gs_plugin_loader_get_app_str (GsApp *app)
        return "<invalid>";
 }
 
+static gboolean
+gs_plugin_loader_app_set_prio (GsApp *app, gpointer user_data)
+{
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (user_data);
+       GsPlugin *plugin;
+       const gchar *tmp;
+
+       /* if set, copy the priority */
+       tmp = gs_app_get_management_plugin (app);
+       if (tmp == NULL)
+               return TRUE;
+       plugin = gs_plugin_loader_find_plugin (plugin_loader, tmp);
+       if (plugin == NULL)
+               return TRUE;
+       gs_app_set_priority (app, gs_plugin_get_priority (plugin));
+       return TRUE;
+}
+
 /**
  * gs_plugin_loader_app_is_valid_installed:
  **/
@@ -1011,6 +1045,7 @@ gs_plugin_loader_get_updates_thread_cb (GTask *task,
        /* remove any packages that are not proper applications or
         * OS updates */
        gs_app_list_filter (state->list, gs_plugin_loader_app_is_valid, state);
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
 
        /* success */
        g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1348,6 +1383,7 @@ gs_plugin_loader_get_installed_thread_cb (GTask *task,
        /* filter package 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_valid_installed, state);
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
 
        /* success */
        g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1463,6 +1499,7 @@ 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);
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
 
        /* success */
        g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1557,6 +1594,7 @@ 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);
        }
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
 
        /* success */
        g_task_return_pointer (task, g_object_ref (state->list), (GDestroyNotify) g_object_unref);
@@ -1778,6 +1816,7 @@ gs_plugin_loader_search_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);
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
        if (gs_app_list_length (state->list) > 500) {
                g_task_return_new_error (task,
                                         GS_PLUGIN_ERROR,
@@ -1941,6 +1980,7 @@ gs_plugin_loader_search_files_thread_cb (GTask *task,
        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);
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
        if (gs_app_list_length (state->list) > 500) {
                g_task_return_new_error (task,
                                         GS_PLUGIN_ERROR,
@@ -2104,6 +2144,7 @@ gs_plugin_loader_search_what_provides_thread_cb (GTask *task,
        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);
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
        if (gs_app_list_length (state->list) > 500) {
                g_task_return_new_error (task,
                                         GS_PLUGIN_ERROR,
@@ -2446,6 +2487,7 @@ gs_plugin_loader_get_category_apps_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);
+       gs_app_list_filter (state->list, gs_plugin_loader_app_set_prio, plugin_loader);
 
        /* sort, just in case the UI doesn't do this */
        gs_app_list_sort (state->list, gs_plugin_loader_app_sort_cb, NULL);
@@ -3150,25 +3192,6 @@ gs_plugin_loader_run (GsPluginLoader *plugin_loader, const gchar *function_name)
 }
 
 /**
- * gs_plugin_loader_find_plugin:
- */
-static GsPlugin *
-gs_plugin_loader_find_plugin (GsPluginLoader *plugin_loader,
-                             const gchar *plugin_name)
-{
-       GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
-       GsPlugin *plugin;
-       guint i;
-
-       for (i = 0; i < priv->plugins->len; i++) {
-               plugin = g_ptr_array_index (priv->plugins, i);
-               if (g_strcmp0 (gs_plugin_get_name (plugin), plugin_name) == 0)
-                       return plugin;
-       }
-       return NULL;
-}
-
-/**
  * gs_plugin_loader_get_enabled:
  */
 gboolean
@@ -3527,6 +3550,49 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
        g_ptr_array_sort (priv->plugins,
                          gs_plugin_loader_plugin_sort_fn);
 
+       /* assign priority values */
+       do {
+               changes = FALSE;
+               for (i = 0; i < priv->plugins->len; i++) {
+                       plugin = g_ptr_array_index (priv->plugins, i);
+                       deps = gs_plugin_get_rules (plugin, GS_PLUGIN_RULE_BETTER_THAN);
+                       for (j = 0; j < deps->len && !changes; j++) {
+                               plugin_name = g_ptr_array_index (deps, j);
+                               dep = gs_plugin_loader_find_plugin (plugin_loader,
+                                                                   plugin_name);
+                               if (dep == NULL) {
+                                       g_debug ("cannot find plugin '%s' "
+                                                "requested by '%s'",
+                                                plugin_name,
+                                                gs_plugin_get_name (plugin));
+                                       continue;
+                               }
+                               if (!gs_plugin_get_enabled (dep))
+                                       continue;
+                               if (gs_plugin_get_priority (plugin) <= gs_plugin_get_priority (dep)) {
+                                       g_debug ("%s [%i] is better than %s [%i] "
+                                                "so promoting to [%i]",
+                                                gs_plugin_get_name (plugin),
+                                                gs_plugin_get_priority (plugin),
+                                                gs_plugin_get_name (dep),
+                                                gs_plugin_get_priority (dep),
+                                                gs_plugin_get_priority (dep) + 1);
+                                       gs_plugin_set_priority (plugin, gs_plugin_get_priority (dep) + 1);
+                                       changes = TRUE;
+                               }
+                       }
+               }
+
+               /* check we're not stuck */
+               if (dep_loop_check++ > 100) {
+                       g_set_error (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "got stuck in priority loop");
+                       return FALSE;
+               }
+       } while (changes);
+
        /* run setup */
        for (i = 0; i < priv->plugins->len; i++) {
                GsPluginSetupFunc plugin_func = NULL;
diff --git a/src/gs-plugin-private.h b/src/gs-plugin-private.h
index ea318f2..ec66ef0 100644
--- a/src/gs-plugin-private.h
+++ b/src/gs-plugin-private.h
@@ -43,6 +43,9 @@ void           gs_plugin_set_scale                    (GsPlugin       *plugin,
 guint           gs_plugin_get_order                    (GsPlugin       *plugin);
 void            gs_plugin_set_order                    (GsPlugin       *plugin,
                                                         guint           order);
+guint           gs_plugin_get_priority                 (GsPlugin       *plugin);
+void            gs_plugin_set_priority                 (GsPlugin       *plugin,
+                                                        guint           priority);
 void            gs_plugin_set_locale                   (GsPlugin       *plugin,
                                                         const gchar    *locale);
 void            gs_plugin_set_profile                  (GsPlugin       *plugin,
diff --git a/src/gs-plugin.c b/src/gs-plugin.c
index 4a19832..e456e9a 100644
--- a/src/gs-plugin.c
+++ b/src/gs-plugin.c
@@ -68,6 +68,7 @@ typedef struct
        gchar                   *name;
        gint                     scale;
        guint                    order;
+       guint                    priority;
        guint                    timer_id;
        GMutex                   timer_mutex;
 } GsPluginPrivate;
@@ -422,6 +423,37 @@ gs_plugin_set_order (GsPlugin *plugin, guint order)
 }
 
 /**
+ * gs_plugin_get_priority:
+ * @plugin: a #GsPlugin
+ *
+ * Gets the plugin priority, where higher values will be chosen where
+ * multiple #GsApp's match a specific rule.
+ *
+ * Returns: the integer value
+ **/
+guint
+gs_plugin_get_priority (GsPlugin *plugin)
+{
+       GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
+       return priv->priority;
+}
+
+/**
+ * gs_plugin_set_priority:
+ * @plugin: a #GsPlugin
+ * @priority: a integer value
+ *
+ * Sets the plugin priority, where higher values will be chosen where
+ * multiple #GsApp's match a specific rule.
+ **/
+void
+gs_plugin_set_priority (GsPlugin *plugin, guint priority)
+{
+       GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
+       priv->priority = priority;
+}
+
+/**
  * gs_plugin_get_locale:
  * @plugin: a #GsPlugin
  *
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index 230c4a1..bb9626c 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -204,6 +204,7 @@ typedef enum {
  * @GS_PLUGIN_RULE_CONFLICTS:          The plugin conflicts with another
  * @GS_PLUGIN_RULE_RUN_AFTER:          Order the plugin after another
  * @GS_PLUGIN_RULE_RUN_BEFORE:         Order the plugin before another
+ * @GS_PLUGIN_RULE_BETTER_THAN:                Results are better than another
  *
  * The rules used for ordering plugins.
  * Plugins are expected to add rules in gs_plugin_initialize().
@@ -212,6 +213,7 @@ typedef enum {
        GS_PLUGIN_RULE_CONFLICTS,
        GS_PLUGIN_RULE_RUN_AFTER,
        GS_PLUGIN_RULE_RUN_BEFORE,
+       GS_PLUGIN_RULE_BETTER_THAN,
        /*< private >*/
        GS_PLUGIN_RULE_LAST
 } GsPluginRule;
diff --git a/src/plugins/gs-plugin-flatpak-system.c b/src/plugins/gs-plugin-flatpak-system.c
index 7fe08ca..715eb44 100644
--- a/src/plugins/gs-plugin-flatpak-system.c
+++ b/src/plugins/gs-plugin-flatpak-system.c
@@ -48,6 +48,9 @@ gs_plugin_initialize (GsPlugin *plugin)
 
        /* getting app properties from appstream is quicker */
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
+
+       /* prioritize over packages */
+       gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_BETTER_THAN, "packagekit");
 }
 
 void
diff --git a/src/plugins/gs-plugin-flatpak-user.c b/src/plugins/gs-plugin-flatpak-user.c
index 0700918..7334373 100644
--- a/src/plugins/gs-plugin-flatpak-user.c
+++ b/src/plugins/gs-plugin-flatpak-user.c
@@ -48,6 +48,9 @@ gs_plugin_initialize (GsPlugin *plugin)
 
        /* getting app properties from appstream is quicker */
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
+
+       /* prioritize over packages */
+       gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_BETTER_THAN, "packagekit");
 }
 
 void


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