changeset 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 fd734d1fb2f4
children 3cc18baeaca3
files plugins/ChangeLog.API src/plugin.c src/plugin.h
diffstat 3 files changed, 61 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/ChangeLog.API	Wed Jan 18 03:44:18 2006 +0000
+++ b/plugins/ChangeLog.API	Wed Jan 18 18:21:59 2006 +0000
@@ -93,6 +93,7 @@
 	  FALSE.  Previously they were set to TRUE or left alone.  Also, you
 	  may now pass NULL if you're not interested in a specific formatting.
 	* Smiley Themes: Backslashes must be backslash-escaped.
+	* Plugins: Depedencies are now honored when unloading plugins.
 
 	Removed:
 	* gaim_gtk_sound_{get,set}_mute() (replaced by the /gaim/gtk/sound/mute
--- 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);
--- a/src/plugin.h	Wed Jan 18 03:44:18 2006 +0000
+++ b/src/plugin.h	Wed Jan 18 18:21:59 2006 +0000
@@ -126,6 +126,7 @@
 	void *ipc_data;                        /**< IPC data.                 */
 	void *extra;                           /**< Plugin-specific data.     */
 	gboolean unloadable;                   /**< Unloadable                */
+	GList *dependent_plugins;              /**< Plugins depending on this */
 };
 
 #define GAIM_PLUGIN_LOADER_INFO(plugin) \