--- 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 @@
- const gchar * const *dependencies = NULL;
- /* 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;
- 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)) {
- /* 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);
- /* now iterate the matches and check if we need to check their
- for(m = matches; m; m = m->next) {
- GPluginPlugin *dplugin = GPLUGIN_PLUGIN(g_object_ref(G_OBJECT(m->data)));
+ dependencies = gplugin_manager_get_plugin_dependencies(plugin, &ourerror); + g_propagate_error(error, ourerror);
- /* 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;
- 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));
- /* dver is greather than over */
- if(g_strcmp0(oop, ">") == 0)
- /* dver is equal to over */
- if(g_strcmp0(oop, ">=") == 0 ||
- g_strcmp0(oop, "<=") == 0 ||
- g_strcmp0(oop, "=") == 0 ||
- g_strcmp0(oop, "==") == 0)
- if(g_strcmp0(oop, "<") == 0)
- 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;
+ loaded = gplugin_manager_load_plugin(dependency, error);
+ gplugin_manager_free_plugin_list(dependencies); @@ -733,7 +641,7 @@
GPluginPluginInfo *info = NULL;
const gchar * const *dependencies = NULL;
info = gplugin_plugin_get_info(plugin);
dependencies = gplugin_plugin_info_get_dependencies(info);
@@ -742,26 +650,64 @@
- 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; + 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)) { + /* 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)) {
- "failed to find plugin dependency '%s'",
+ /* now look for a plugin matching the id */ + matches = gplugin_manager_find_plugins_with_version(oid, oop, + /* 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); - g_slist_free_full(ret, g_object_unref);
+ g_set_error(error, GPLUGIN_DOMAIN, 0, + _("failed to find dependency %s for %s"), + dependencies[i], gplugin_plugin_info_get_id(info));
+ gplugin_manager_free_plugin_list(ret); + g_object_unref(G_OBJECT(info)); - ret = g_slist_prepend(ret, dep);
+ g_object_unref(G_OBJECT(info)); @@ -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 + * 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 +gplugin_manager_find_plugins_with_version(const gchar *id, const gchar *op, + 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. + for(l = plugins; l; l = l->next) { + GPluginPlugin *plugin = GPLUGIN_PLUGIN(l->data); + GPluginPluginInfo *info = NULL; + const gchar *found_version = NULL; + /* 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); + g_warning("failed to compare versions for %s: %s", + error->message ? error->message : _("unknown error")); + /* 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); + 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) {
- 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. Call #gplugin_manager_free_plugin_list on + * the returned value when you're done with it. 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);