diff src/plugin.c @ 12926:2c4f20ff387c

[gaim-migrate @ 15279] SF Patch #1403656 from Nick Hebner "This patch makes plugin unloading take into account plugins that depend on the plugin being unloaded. All plugins dependent on the plugin in question are unloaded before this plugin is, so there are not problems with missing dependencies." committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Wed, 18 Jan 2006 18:21:59 +0000
parents 69713c02a702
children 92ae94619e2c
line wrap: on
line diff
--- a/src/plugin.c	Wed Jan 18 03:44:18 2006 +0000
+++ b/src/plugin.c	Wed Jan 18 18:21:59 2006 +0000
@@ -504,16 +504,16 @@
 
 		if (dep_plugin == NULL)
 		{
-			char buf[BUFSIZ];
+			char *tmp;
 
-			g_snprintf(buf, sizeof(buf),
-					   _("The required plugin %s was not found. "
-						 "Please install this plugin and try again."),
-					   dep_name);
+			tmp = g_strdup_printf(
+			                      _("The required plugin %s was not found. "
+			                        "Please install this plugin and try again."),
+			                      dep_name);
 
 			gaim_notify_error(NULL, NULL,
-							  _("Gaim was unable to load your plugin."),
-							  buf);
+			                  _("Gaim encountered errors loading the plugin."), tmp);
+			g_free(tmp);
 
 			if (dep_list != NULL)
 				g_list_free(dep_list);
@@ -533,15 +533,14 @@
 		{
 			if (!gaim_plugin_load(dep_plugin))
 			{
-				char buf[BUFSIZ];
+				char *tmp;
 
-				g_snprintf(buf, sizeof(buf),
-						   _("The required plugin %s was unable to load."),
-						   plugin->info->name);
+				tmp = g_strdup_printf(_("The required plugin %s was unable to load."),
+				                      plugin->info->name);
 
 				gaim_notify_error(NULL, NULL,
-								  _("Gaim was unable to load your plugin."),
-								  buf);
+				                 _("Gaim was unable to load your plugin."), tmp);
+				g_free(tmp);
 
 				if (dep_list != NULL)
 					g_list_free(dep_list);
@@ -551,6 +550,14 @@
 		}
 	}
 
+	/* Third pass: note that other plugins are dependencies of this plugin.
+	 * This is done separately in case we had to bail out earlier. */
+	for (l = dep_list; l != NULL; l = l->next)
+	{
+		GaimPlugin *dep_plugin = (GaimPlugin *)l->data;
+		dep_plugin->dependent_plugins = g_list_prepend(dep_plugin->dependent_plugins, plugin->info->id);
+	}
+
 	if (dep_list != NULL)
 		g_list_free(dep_list);
 
@@ -601,6 +608,8 @@
 gaim_plugin_unload(GaimPlugin *plugin)
 {
 #ifdef GAIM_PLUGINS
+	GList *l;
+	
 	g_return_val_if_fail(plugin != NULL, FALSE);
 
 	loaded_plugins = g_list_remove(loaded_plugins, plugin);
@@ -617,6 +626,43 @@
 
 	plugin->loaded = FALSE;
 
+	/* Unload all plugins that depend on this plugin. */
+	for (l = plugin->dependent_plugins; l != NULL; l = l->next)
+	{
+		const char * dep_name = (const char *)l->data;
+		GaimPlugin *dep_plugin;
+
+		dep_plugin = gaim_plugins_find_with_id(dep_name);
+
+		if (dep_plugin != NULL && gaim_plugin_is_loaded(dep_plugin))
+		{
+			if (!gaim_plugin_unload(dep_plugin))
+			{
+				char *translated_name = g_strdup(_(dep_plugin->info->name));
+				char *tmp;
+
+				tmp = g_strdup_printf(_("The dependent plugin %s failed to unload."),
+				                      translated_name);
+				g_free(translated_name);
+
+				gaim_notify_error(NULL, NULL,
+				                  _("Gaim encountered errors unloading the plugin."), tmp);
+				g_free(tmp);
+			}
+		}
+	}
+
+	/* Remove this plugin from each dependency's dependent_plugins list. */
+	for (l = plugin->info->dependencies; l != NULL; l = l->next)
+	{
+		const char *dep_name = (const char *)l->data;
+		GaimPlugin *dependency;
+
+		dependency = gaim_plugins_find_with_id(dep_name);
+
+		dependency->dependent_plugins = g_list_remove(dependency->dependent_plugins, plugin->info->id);
+	}
+
 	if (plugin->native_plugin) {
 		if (plugin->info->unload != NULL)
 			plugin->info->unload(plugin);