Commit 7ac55cfb authored by Richard Hughes's avatar Richard Hughes

Add depends, requires and conflicts at initialize time

This means we can make plugins much simpler and also do dynamic configuration
in the future.
parent c9d39ba7
......@@ -30,11 +30,10 @@ gcc -shared -o libgs_plugin_example.so gs-plugin-example.c -fPIC \
sudo cp libgs_plugin_example.so `pkg-config gnome-software --variable=plugindir`
*/
const gchar **
gs_plugin_order_before (GsPlugin *plugin)
void
gs_plugin_initialize (GsPlugin *plugin)
{
static const gchar *deps[] = { "appstream", NULL };
return deps;
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_BEFORE, "appstream");
}
gboolean
......
......@@ -3279,10 +3279,11 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
{
GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
const gchar *filename_tmp;
const gchar *plugin_name;
gboolean changes;
GPtrArray *deps;
GsPlugin *dep;
GsPlugin *plugin;
const gchar **deps;
guint dep_loop_check = 0;
guint i;
guint j;
......@@ -3333,15 +3334,14 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
changes = FALSE;
for (i = 0; i < priv->plugins->len; i++) {
plugin = g_ptr_array_index (priv->plugins, i);
deps = gs_plugin_get_order_after (plugin);
if (deps == NULL)
continue;
for (j = 0; deps[j] != NULL && !changes; j++) {
deps = gs_plugin_get_rules (plugin, GS_PLUGIN_RULE_RUN_AFTER);
for (j = 0; j < deps->len && !changes; j++) {
plugin_name = g_ptr_array_index (deps, j);
dep = gs_plugin_loader_find_plugin (plugin_loader,
deps[j]);
plugin_name);
if (dep == NULL) {
g_debug ("cannot find plugin '%s'",
deps[j]);
plugin_name);
continue;
}
if (!gs_plugin_get_enabled (dep))
......@@ -3361,15 +3361,14 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
}
for (i = 0; i < priv->plugins->len; i++) {
plugin = g_ptr_array_index (priv->plugins, i);
deps = gs_plugin_get_order_before (plugin);
if (deps == NULL)
continue;
for (j = 0; deps[j] != NULL && !changes; j++) {
deps = gs_plugin_get_rules (plugin, GS_PLUGIN_RULE_RUN_BEFORE);
for (j = 0; j < deps->len && !changes; j++) {
plugin_name = g_ptr_array_index (deps, j);
dep = gs_plugin_loader_find_plugin (plugin_loader,
deps[j]);
plugin_name);
if (dep == NULL) {
g_debug ("cannot find plugin '%s'",
deps[j]);
plugin_name);
continue;
}
if (!gs_plugin_get_enabled (dep))
......@@ -3403,12 +3402,11 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
plugin = g_ptr_array_index (priv->plugins, i);
if (!gs_plugin_get_enabled (plugin))
continue;
deps = gs_plugin_get_conflicts (plugin);
if (deps == NULL)
continue;
for (j = 0; deps[j] != NULL && !changes; j++) {
deps = gs_plugin_get_rules (plugin, GS_PLUGIN_RULE_CONFLICTS);
for (j = 0; j < deps->len && !changes; j++) {
plugin_name = g_ptr_array_index (deps, j);
dep = gs_plugin_loader_find_plugin (plugin_loader,
deps[j]);
plugin_name);
if (dep == NULL)
continue;
if (!gs_plugin_get_enabled (dep))
......
......@@ -51,10 +51,8 @@ void gs_plugin_set_soup_session (GsPlugin *plugin,
SoupSession *soup_session);
void gs_plugin_set_running_other (GsPlugin *plugin,
gboolean running_other);
const gchar **gs_plugin_get_order_after (GsPlugin *plugin);
const gchar **gs_plugin_get_order_before (GsPlugin *plugin);
const gchar **gs_plugin_get_conflicts (GsPlugin *plugin);
GPtrArray *gs_plugin_get_rules (GsPlugin *plugin,
GsPluginRule rule);
GModule *gs_plugin_get_module (GsPlugin *plugin);
G_END_DECLS
......
......@@ -136,43 +136,6 @@ gboolean gs_plugin_add_search_what_provides (GsPlugin *plugin,
GCancellable *cancellable,
GError **error);
/**
* gs_plugin_order_after:
* @plugin: a #GsPlugin
*
* Any plugin names returned with this method will be ordered after this plugin.
*
* NOTE: If depsolving fails then gnome-software will not start.
*
* Returns: (element-type utf8): A list of deps
**/
const gchar **gs_plugin_order_after (GsPlugin *plugin);
/**
* gs_plugin_order_before:
* @plugin: a #GsPlugin
*
* Any plugin names returned with this method will be ordered before this plugin.
*
* NOTE: If depsolving fails then gnome-software will not start.
*
* Returns: (element-type utf8): A list of deps
**/
const gchar **gs_plugin_order_before (GsPlugin *plugin);
/**
* gs_plugin_get_conflicts:
* @plugin: a #GsPlugin
*
* Any plugin names returned with this method will be disabled if this plugin
* is enabled.
*
* NOTE: The depsolver is iterative and may not solve overly-complicated rules.
*
* Returns: (element-type utf8): A list of deps
**/
const gchar **gs_plugin_get_conflicts (GsPlugin *plugin);
/**
* gs_plugin_setup:
* @plugin: a #GsPlugin
......
......@@ -61,9 +61,7 @@ typedef struct
GsPluginData *data; /* for gs-plugin-{name}.c */
GsPluginFlags flags;
SoupSession *soup_session;
const gchar **conflicts; /* allow-none */
const gchar **order_after; /* allow-none */
const gchar **order_before; /* allow-none */
GPtrArray *rules[GS_PLUGIN_RULE_LAST];
gboolean enabled;
gchar *locale; /* allow-none */
gchar *name;
......@@ -130,9 +128,6 @@ GsPlugin *
gs_plugin_create (const gchar *filename, GError **error)
{
GModule *module;
GsPluginGetDepsFunc order_after = NULL;
GsPluginGetDepsFunc order_before = NULL;
GsPluginGetDepsFunc plugin_conflicts = NULL;
GsPlugin *plugin = NULL;
GsPluginPrivate *priv;
g_autofree gchar *basename = NULL;
......@@ -159,24 +154,10 @@ gs_plugin_create (const gchar *filename, GError **error)
}
g_strdelimit (basename, ".", '\0');
/* get plugins this plugin depends on */
g_module_symbol (module,
"gs_plugin_order_after",
(gpointer *) &order_after);
g_module_symbol (module,
"gs_plugin_order_before",
(gpointer *) &order_before);
g_module_symbol (module,
"gs_plugin_get_conflicts",
(gpointer *) &plugin_conflicts);
/* create new plugin */
plugin = gs_plugin_new ();
priv = gs_plugin_get_instance_private (plugin);
priv->module = module;
priv->order_after = order_after != NULL ? order_after (plugin) : NULL;
priv->order_before = order_before != NULL ? order_before (plugin) : NULL;
priv->conflicts = plugin_conflicts != NULL ? plugin_conflicts (plugin) : NULL;
priv->name = g_strdup (basename + 13);
return plugin;
}
......@@ -189,6 +170,10 @@ gs_plugin_finalize (GObject *object)
{
GsPlugin *plugin = GS_PLUGIN (object);
GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
guint i;
for (i = 0; i < GS_PLUGIN_RULE_LAST; i++)
g_ptr_array_unref (priv->rules[i]);
if (priv->timer_id > 0)
g_source_remove (priv->timer_id);
......@@ -554,48 +539,39 @@ gs_plugin_set_running_other (GsPlugin *plugin, gboolean running_other)
}
/**
* gs_plugin_get_order_after:
* @plugin: a #GsPlugin
*
* Gets the plugin IDs that should be run after this plugin.
*
* Returns: the NULL terminated list of IDs, e.g. ['appstream']
**/
const gchar **
gs_plugin_get_order_after (GsPlugin *plugin)
{
GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
return priv->order_after;
}
/**
* gs_plugin_get_order_before:
* gs_plugin_add_rule:
* @plugin: a #GsPlugin
* @rule: a #GsPluginRule, e.g. %GS_PLUGIN_RULE_CONFLICTS
* @name: a plugin name, e.g. "appstream"
*
* Gets the plugin IDs that should be run before this plugin.
* If the plugin name is found, the rule will be used to sort the plugin list,
* for example the plugin specified by @name will be ordered after this plugin
* when %GS_PLUGIN_RULE_RUN_AFTER is used.
*
* Returns: the NULL terminated list of IDs, e.g. ['appstream']
* NOTE: The depsolver is iterative and may not solve overly-complicated rules;
* If depsolving fails then gnome-software will not start.
**/
const gchar **
gs_plugin_get_order_before (GsPlugin *plugin)
void
gs_plugin_add_rule (GsPlugin *plugin, GsPluginRule rule, const gchar *name)
{
GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
return priv->order_before;
g_ptr_array_add (priv->rules[rule], g_strdup (name));
}
/**
* gs_plugin_get_conflicts:
* gs_plugin_get_rules:
* @plugin: a #GsPlugin
* @rule: a #GsPluginRule, e.g. %GS_PLUGIN_RULE_CONFLICTS
*
* Gets the plugin IDs that should be disabled if this plugin is enabled.
* Gets the plugin IDs that should be run after this plugin.
*
* Returns: the NULL terminated list of IDs, e.g. ['appstream']
* Returns: (element-type utf8) (transfer none): the list of plugin names, e.g. ['appstream']
**/
const gchar **
gs_plugin_get_conflicts (GsPlugin *plugin)
GPtrArray *
gs_plugin_get_rules (GsPlugin *plugin, GsPluginRule rule)
{
GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
return priv->conflicts;
return priv->rules[rule];
}
/**
......@@ -1032,6 +1008,11 @@ static void
gs_plugin_init (GsPlugin *plugin)
{
GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
guint i;
for (i = 0; i < GS_PLUGIN_RULE_LAST; i++)
priv->rules[i] = g_ptr_array_new_with_free_func (g_free);
priv->enabled = TRUE;
priv->priority = 0.f;
priv->scale = 1;
......
......@@ -197,6 +197,23 @@ typedef enum {
GS_PLUGIN_REFRESH_FLAGS_LAST
} GsPluginRefreshFlags;
/**
* GsPluginRule:
* @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
*
* The rules used for ordering plugins.
* Plugins are expected to add rules in gs_plugin_initialize().
**/
typedef enum {
GS_PLUGIN_RULE_CONFLICTS,
GS_PLUGIN_RULE_RUN_AFTER,
GS_PLUGIN_RULE_RUN_BEFORE,
/*< private >*/
GS_PLUGIN_RULE_LAST
} GsPluginRule;
/* helpers */
#define GS_PLUGIN_ERROR 1
......@@ -214,6 +231,9 @@ guint gs_plugin_get_scale (GsPlugin *plugin);
const gchar *gs_plugin_get_locale (GsPlugin *plugin);
AsProfile *gs_plugin_get_profile (GsPlugin *plugin);
SoupSession *gs_plugin_get_soup_session (GsPlugin *plugin);
void gs_plugin_add_rule (GsPlugin *plugin,
GsPluginRule rule,
const gchar *name);
/* helpers */
GBytes *gs_plugin_download_data (GsPlugin *plugin,
......
......@@ -65,19 +65,10 @@ gs_plugin_initialize (GsPlugin *plugin)
as_store_set_watch_flags (priv->store,
AS_STORE_WATCH_FLAG_ADDED |
AS_STORE_WATCH_FLAG_REMOVED);
}
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"menu-spec-categories", /* need category list */
"dpkg", /* need package name */
NULL };
return deps;
/* need category list and package name */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "menu-spec-categories");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "dpkg");
}
/**
......
......@@ -32,17 +32,6 @@ struct GsPluginData {
guint quirk_id;
};
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = { "appstream",
NULL };
return deps;
}
/**
* gs_plugin_initialize:
*/
......@@ -55,6 +44,9 @@ gs_plugin_initialize (GsPlugin *plugin)
gs_plugin_get_name (plugin));
gs_plugin_set_enabled (plugin, FALSE);
}
/* need help from appstream */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
}
/**
......
......@@ -33,18 +33,6 @@
* If the epiphany binary is not present then it self-disables.
*/
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream",
NULL };
return deps;
}
/**
* gs_plugin_initialize:
*/
......@@ -60,6 +48,9 @@ gs_plugin_initialize (GsPlugin *plugin)
g_debug ("disabling '%s' as epiphany does not exist",
gs_plugin_get_name (plugin));
}
/* need help from appstream */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
}
/**
......
......@@ -58,18 +58,9 @@ gs_plugin_initialize (GsPlugin *plugin)
g_debug ("disabling '%s' as we're not Fedora", gs_plugin_get_name (plugin));
return;
}
}
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"packagekit", /* after the install/remove has succeeded */
NULL };
return deps;
/* after the install/remove has succeeded */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "packagekit");
}
/**
......
......@@ -43,30 +43,6 @@ struct GsPluginData {
GFileMonitor *monitor;
};
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream",
NULL };
return deps;
}
/**
* gs_plugin_get_conflicts:
*/
const gchar **
gs_plugin_get_conflicts (GsPlugin *plugin)
{
static const gchar *deps[] = {
"xdg-app",
NULL };
return deps;
}
/**
* gs_plugin_initialize:
*/
......@@ -74,6 +50,12 @@ void
gs_plugin_initialize (GsPlugin *plugin)
{
gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
/* getting app properties from appstream is quicker */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
/* this is the old name */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "xdg-app");
}
/**
......
......@@ -30,15 +30,13 @@
*/
/**
* gs_plugin_order_after:
* gs_plugin_initialize:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
void
gs_plugin_initialize (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream", /* need ID */
NULL };
return deps;
/* need ID */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
}
/**
......
......@@ -50,6 +50,10 @@ gs_plugin_initialize (GsPlugin *plugin)
priv->icon_theme = gtk_icon_theme_new ();
priv->icon_theme_paths = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_mutex_init (&priv->icon_theme_lock);
/* needs remote icons downloaded */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "epiphany");
}
/**
......@@ -64,19 +68,6 @@ gs_plugin_destroy (GsPlugin *plugin)
g_mutex_clear (&priv->icon_theme_lock);
}
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream", /* needs remote icons downloaded */
"epiphany", /* "" */
NULL };
return deps;
}
/**
* gs_plugin_icons_download:
*/
......
......@@ -24,15 +24,13 @@
#include <gnome-software.h>
/**
* gs_plugin_order_after:
* gs_plugin_initialize:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
void
gs_plugin_initialize (GsPlugin *plugin)
{
static const gchar *deps[] = {
"icons", /* need icon */
NULL };
return deps;
/* need icon */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "icons");
}
typedef struct {
......
......@@ -34,18 +34,6 @@ struct GsPluginData {
LiManager *mgr;
};
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = { "appstream",
"packagekit",
NULL };
return deps;
}
/**
* gs_plugin_initialize:
*/
......@@ -54,6 +42,10 @@ gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
priv->mgr = li_manager_new ();
/* need help from appstream */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "packagekit");
}
/**
......
......@@ -33,16 +33,14 @@
*/
/**
* gs_plugin_order_after:
* gs_plugin_initialize:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
void
gs_plugin_initialize (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream", /* need GsApp category data */
"menu-spec-categories", /* need menu-spec data */
NULL };
return deps;
/* need category and menu-spec data */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "menu-spec-categories");
}
/**
......
......@@ -72,21 +72,11 @@ gs_plugin_initialize (GsPlugin *plugin)
g_warning ("failed to get distro name");
priv->distro = g_strdup ("Unknown");
}
}
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream", /* need application IDs */
"xdg-app", /* need version */
"flatpak", /* need version */
NULL };
return deps;
/* need application IDs and version */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "xdg-app");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "flatpak");
}
/**
......
......@@ -44,25 +44,16 @@ gs_plugin_initialize (GsPlugin *plugin)
gs_plugin_set_enabled (plugin, FALSE);
return;
}
}
/**
* gs_plugin_get_conflicts:
*/
const gchar **
gs_plugin_get_conflicts (GsPlugin *plugin)
{
static const gchar *deps[] = {
"packagekit",
"packagekit-history",
"packagekit-offline",
"packagekit-origin",
"packagekit-proxy",
"packagekit-refine",
"packagekit-refresh",
"systemd-updates",
NULL };
return deps;
/* ostree can't install packages live */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-history");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-offline");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-origin");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-proxy");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-refine");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "packagekit-refresh");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "systemd-updates");
}
/**
......
......@@ -44,19 +44,10 @@ void
gs_plugin_initialize (GsPlugin *plugin)
{
gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
}
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream", /* need pkgname */
"packagekit-refine", /* need pkgname */
NULL };
return deps;
/* need pkgname */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "packagekit-refine");
}
/**
......
......@@ -56,18 +56,9 @@ gs_plugin_initialize (GsPlugin *plugin)
g_str_equal,
g_free,
g_free);
}
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"packagekit-refine", /* need origin */
NULL };
return deps;
/* need origin */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "packagekit-refine");
}
/**
......
......@@ -44,18 +44,6 @@ struct GsPluginData {
AsProfileTask *ptask;
};
/**
* gs_plugin_get_conflicts:
*/
const gchar **
gs_plugin_get_conflicts (GsPlugin *plugin)
{
static const gchar *deps[] = {
"rpm",
NULL };
return deps;
}
/**
* gs_plugin_initialize:
*/
......@@ -81,19 +69,13 @@ gs_plugin_initialize (GsPlugin *plugin)
pk_client_set_background (priv->client, FALSE);
pk_client_set_interactive (priv->client, FALSE);
pk_client_set_cache_age (priv->client, G_MAXUINT);
}
/**
* gs_plugin_order_after:
*/
const gchar **
gs_plugin_order_after (GsPlugin *plugin)
{
static const gchar *deps[] = {
"appstream", /* need pkgname */
"packagekit", /* need package_id */
NULL };
return deps;
/* we can get better results than the RPM plugin */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "rpm");
/* need pkgname and ID */
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "packagekit");
}