qulogic/gplugin

5c879fef9d53
Merged in feature/dependency-cleanup (pull request #49)

Feature/dependency cleanup

Approved-by: Elliott Sales de Andrade
--- a/gplugin/gplugin-manager.c Wed Feb 19 04:11:26 2020 +0000
+++ b/gplugin/gplugin-manager.c Wed Feb 19 04:22:43 2020 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Gary Kramlich <grim@reaperworld.com>
+ * Copyright (C) 2011-2020 Gary Kramlich <grim@reaperworld.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -605,124 +605,32 @@
GPluginPluginInfo *info,
GError **error)
{
- const gchar * const *dependencies = NULL;
- gint i = 0;
-
- /* now walk through any dependencies the plugin has and load them. If they
- * fail to load we need to fail as well.
- */
- dependencies = gplugin_plugin_info_get_dependencies(info);
- if(dependencies != NULL) {
- gboolean all_found = TRUE;
-
- for(i = 0; dependencies[i]; i++) {
- gboolean found = FALSE;
- gchar **ors = NULL;
- gint o = 0;
-
- ors = g_strsplit(dependencies[i], "|", 0);
- for(o = 0; ors[o]; o++) {
- GMatchInfo *match = NULL;
- GSList *matches = NULL, *m = NULL;
- gchar *oid = NULL, *oop = NULL, *over = NULL;
+ GSList *dependencies = NULL, *l = NULL;
+ GError *ourerror = NULL;
+ gboolean all_loaded = TRUE;
- if(!g_regex_match(dependency_regex, ors[o], 0, &match)) {
- continue;
- }
-
- /* grab the or'd id, op, and version */
- oid = g_match_info_fetch_named(match, "id");
- oop = g_match_info_fetch_named(match, "op");
- over = g_match_info_fetch_named(match, "version");
-
- /* free the match info */
- g_match_info_free(match);
-
- /* now look for a plugin matching the id */
- matches = gplugin_manager_find_plugins(oid);
- if(matches == NULL) {
- g_free(oid);
- g_free(oop);
- g_free(over);
- continue;
- }
-
- /* now iterate the matches and check if we need to check their
- * version.
- */
- for(m = matches; m; m = m->next) {
- GPluginPlugin *dplugin = GPLUGIN_PLUGIN(g_object_ref(G_OBJECT(m->data)));
- gboolean ret = FALSE;
+ dependencies = gplugin_manager_get_plugin_dependencies(plugin, &ourerror);
+ if(ourerror != NULL) {
+ g_propagate_error(error, ourerror);
- if(oop && over) {
- /* we need to check the version, so grab the info to
- * get the version and check it.
- */
- GPluginPluginInfo *dinfo = NULL;
- const gchar *dver = NULL;
- gboolean satisfied = FALSE;
- gint res = 0;
-
- dinfo = gplugin_plugin_get_info(dplugin);
- dver = gplugin_plugin_info_get_version(dinfo);
-
- res = gplugin_version_compare(dver, over, error);
- g_object_unref(G_OBJECT(dinfo));
-
- if(res < 0) {
- /* dver is greather than over */
- if(g_strcmp0(oop, ">") == 0)
- satisfied = TRUE;
- } else if(res == 0) {
- /* dver is equal to over */
- if(g_strcmp0(oop, ">=") == 0 ||
- g_strcmp0(oop, "<=") == 0 ||
- g_strcmp0(oop, "=") == 0 ||
- g_strcmp0(oop, "==") == 0)
- {
- satisfied = TRUE;
- }
- } else if(res > 0) {
- if(g_strcmp0(oop, "<") == 0)
- satisfied = TRUE;
- }
+ return FALSE;
+ }
- if(satisfied)
- found = TRUE;
- }
-
- ret = gplugin_manager_load_plugin(dplugin, error);
-
-# warning need to figure out dependencies
-// gplugin_plugin_add_dependent_plugin(dplugin, plugin);
-
- g_object_unref(G_OBJECT(dplugin));
+ for(l = dependencies; l != NULL; l = l->next) {
+ GPluginPlugin *dependency = GPLUGIN_PLUGIN(l->data);
+ gboolean loaded = FALSE;
- if(ret) {
- found = TRUE;
- break;
- }
- }
-
- g_free(oid);
- g_free(oop);
- g_free(over);
+ loaded = gplugin_manager_load_plugin(dependency, error);
- if(found)
- break;
- }
- g_strfreev(ors);
-
- if(!found)
- all_found = FALSE;
- }
-
- if(!all_found) {
- return FALSE;
+ if(!loaded) {
+ all_loaded = FALSE;
+ break;
}
}
- return TRUE;
+ gplugin_manager_free_plugin_list(dependencies);
+
+ return all_loaded;
}
static GSList *
@@ -733,7 +641,7 @@
GPluginPluginInfo *info = NULL;
GSList *ret = NULL;
const gchar * const *dependencies = NULL;
- gint idx = 0;
+ gint i = 0;
info = gplugin_plugin_get_info(plugin);
dependencies = gplugin_plugin_info_get_dependencies(info);
@@ -742,26 +650,64 @@
return NULL;
}
- for(idx = 0; dependencies[idx] != NULL; idx++) {
- GPluginPlugin *dep = gplugin_manager_find_plugin(dependencies[idx]);
+ for(i = 0; dependencies[i] != NULL; i++) {
+ gboolean found = FALSE;
+ gchar **ors = NULL;
+ gint o = 0;
+
+ ors = g_strsplit(dependencies[i], "|", 0);
+ for(o = 0; ors[o]; o++) {
+ GMatchInfo *match = NULL;
+ GSList *matches = NULL;
+ gchar *oid = NULL, *oop = NULL, *over = NULL;
+
+ if(!g_regex_match(dependency_regex, ors[o], 0, &match)) {
+ continue;
+ }
+
+ /* grab the or'd id, op, and version */
+ oid = g_match_info_fetch_named(match, "id");
+ oop = g_match_info_fetch_named(match, "op");
+ over = g_match_info_fetch_named(match, "version");
+
+ /* free the match info */
+ g_match_info_free(match);
- if(!GPLUGIN_IS_PLUGIN(dep)) {
- if(error) {
- *error = g_error_new(
- GPLUGIN_DOMAIN,
- 0,
- "failed to find plugin dependency '%s'",
- dependencies[idx]
- );
+ /* now look for a plugin matching the id */
+ matches = gplugin_manager_find_plugins_with_version(oid, oop,
+ over);
+ g_free(oid);
+ g_free(oop);
+ g_free(over);
+
+ if(matches == NULL) {
+ continue;
+ }
+
+ /* prepend the first found match to our return value */
+ ret = g_slist_prepend(ret, g_object_ref(matches->data));
+ gplugin_manager_free_plugin_list(matches);
+
+ found = TRUE;
- g_slist_free_full(ret, g_object_unref);
+ break;
+ }
+ g_strfreev(ors);
+
+ if(!found) {
+ g_set_error(error, GPLUGIN_DOMAIN, 0,
+ _("failed to find dependency %s for %s"),
+ dependencies[i], gplugin_plugin_info_get_id(info));
- return NULL;
- }
+ gplugin_manager_free_plugin_list(ret);
+
+ g_object_unref(G_OBJECT(info));
+
+ return NULL;
}
+ }
- ret = g_slist_prepend(ret, dep);
- }
+ g_object_unref(G_OBJECT(info));
return ret;
}
@@ -1330,8 +1276,98 @@
}
/**
+ * gplugin_manager_find_plugins_with_version:
+ * @id: The ID of the plugin to find.
+ * @op: one of <, <=, =, ==, >=, >.
+ * @version: The version to compare against.
+ *
+ * Similar to gplugin_manager_find_plugins() but only returns plugins whose
+ * versions match @op and @version. This is primarily used for dependency
+ * loading where a plugin may depend on a specific range of versions of another
+ * plugin.
+ *
+ * Returns: (element-type GPlugin.Plugin) (transfer full): A #GSList of
+ * referenced #GPluginPlugin's matching @id. Call
+ * gplugin_manager_free_plugin_list() on the returned value when
+ * you're done with it.
+ */
+GSList *
+gplugin_manager_find_plugins_with_version(const gchar *id, const gchar *op,
+ const gchar *version)
+{
+ GPluginManager *manager = GPLUGIN_MANAGER_INSTANCE;
+ GSList *plugins = NULL, *filtered = NULL, *l = NULL;
+
+ g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), NULL);
+
+ plugins = gplugin_manager_find_plugins(id);
+
+ if(op == NULL && version == NULL) {
+ /* we weren't actually passed an operator and a version so just return
+ * the list we have based on the id.
+ */
+ return plugins;
+ }
+
+ for(l = plugins; l; l = l->next) {
+ GPluginPlugin *plugin = GPLUGIN_PLUGIN(l->data);
+ GPluginPluginInfo *info = NULL;
+ GError *error = NULL;
+ const gchar *found_version = NULL;
+ gint result = 0;
+ gboolean keep = FALSE;
+
+ /* get the plugin's version from it's info */
+ info = gplugin_plugin_get_info(plugin);
+ found_version = gplugin_plugin_info_get_version(info);
+ g_object_unref(G_OBJECT(info));
+
+ /* now compare the version of the plugin to passed in version. This
+ * should be done in this order so it's easier to track the operators.
+ * IE: we want to keep the inequality the same.
+ */
+ result = gplugin_version_compare(found_version, version, &error);
+ if(error != NULL) {
+ g_warning("failed to compare versions for %s: %s",
+ id,
+ error->message ? error->message : _("unknown error"));
+
+ g_clear_error(&error);
+
+ continue;
+ }
+
+ if(result < 0) {
+ /* negative values mean that the first version is larger than the
+ * second, so we need check for > and >=.
+ */
+ keep = (g_strcmp0(op, ">") == 0 || g_strcmp0(op, ">=") == 0);
+ } else if(result == 0) {
+ /* 0 values mean we need to check for = and ==, as well as <= and
+ * >= as they need to match too.
+ */
+ keep = (g_strcmp0(op, "=") == 0 || g_strcmp0(op, "==") == 0 ||
+ g_strcmp0(op, "<=") == 0 || g_strcmp0(op, ">=") == 0);
+ } else if(result > 0) {
+ /* positive values mean that the first version is smaller than the
+ * second, so we need to check for < and <=.
+ */
+ keep = (g_strcmp0(op, "<") == 0 || g_strcmp0(op, "<=") == 0);
+ }
+
+ if(keep) {
+ filtered = g_slist_prepend(filtered, g_object_ref(G_OBJECT(plugin)));
+ }
+ }
+
+ gplugin_manager_free_plugin_list(plugins);
+
+ return g_slist_reverse(filtered);
+}
+
+/**
* gplugin_manager_free_plugin_list:
- * @plugins_list: (element-type GPlugin.Plugin): Returned value from
+ * @plugins_list: (element-type GPlugin.Plugin) (nullable): Returned value from
* #gplugin_manager_find_plugins
*
* Frees the return value of #gplugin_manager_find_plugins.
@@ -1340,8 +1376,6 @@
gplugin_manager_free_plugin_list(GSList *plugins_list) {
GSList *l = NULL;
- g_return_if_fail(plugins_list != NULL);
-
for(l = plugins_list; l; l = l->next) {
GPluginPlugin *plugin = NULL;
@@ -1394,7 +1428,8 @@
*
* Return value: (element-type GPlugin.Plugin) (transfer full): A #GSList of
* #GPluginPlugin's that @plugin depends on, or NULL on error
- * with @error set.
+ * with @error set. Call #gplugin_manager_free_plugin_list on
+ * the returned value when you're done with it.
*/
GSList *
gplugin_manager_get_plugin_dependencies(GPluginPlugin *plugin, GError **error) {
--- a/gplugin/gplugin-manager.h Wed Feb 19 04:11:26 2020 +0000
+++ b/gplugin/gplugin-manager.h Wed Feb 19 04:22:43 2020 +0000
@@ -45,6 +45,7 @@
void gplugin_manager_refresh(void);
GSList *gplugin_manager_find_plugins(const gchar *id);
+GSList *gplugin_manager_find_plugins_with_version(const gchar *id, const gchar *op, const gchar *version);
void gplugin_manager_free_plugin_list(GSList *plugins_list);
GPluginPlugin *gplugin_manager_find_plugin(const gchar *id);