Changeset

13829:dde0ce03049b 13.0

modulemanager, util.pluginloader: Improve error message when load fails but some candidates were filtered
author Matthew Wild <mwild1@gmail.com>
date Wed, 09 Apr 2025 10:53:37 +0100
parents 13828:a071b20ccc0f
children 13830:145b71d1283c
files core/modulemanager.lua util/pluginloader.lua
diffstat 2 files changed, 49 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/core/modulemanager.lua	Fri Apr 04 16:50:25 2025 +0100
+++ b/core/modulemanager.lua	Wed Apr 09 10:53:37 2025 +0100
@@ -54,50 +54,58 @@
 local _ENV = nil;
 -- luacheck: std none
 
-local loader = pluginloader.init({
-	load_filter_cb = function (path, content)
-		local metadata = {};
-		for line in content:gmatch("([^\r\n]+)\r?\n") do
-			local key, value = line:match("^%-%-%% *([%w_]+): *(.+)$");
-			if key then
-				value = value:gsub("%s+$", "");
-				metadata[key] = value;
+local function plugin_load_filter_cb(path, content)
+	local metadata = {};
+	for line in content:gmatch("([^\r\n]+)\r?\n") do
+		local key, value = line:match("^%-%-%% *([%w_]+): *(.+)$");
+		if key then
+			value = value:gsub("%s+$", "");
+			metadata[key] = value;
+		end
+	end
+
+	if metadata.lua then
+		local supported = false;
+		for supported_lua_version in metadata.lua:gmatch("[^, ]+") do
+			if supported_lua_version == lua_version then
+				supported = true;
+				break;
 			end
 		end
-
-		if metadata.lua then
-			local supported = false;
-			for supported_lua_version in metadata.lua:gmatch("[^, ]+") do
-				if supported_lua_version == lua_version then
-					supported = true;
-					break;
-				end
+		if not supported then
+			if prosody.process_type ~= "prosodyctl" then
+				log("warn", "Not loading module, we have Lua %s but the module requires one of (%s): %s", lua_version, metadata.lua, path);
 			end
-			if not supported then
-				log("warn", "Not loading module, we have Lua %s but the module requires one of (%s): %s", lua_version, metadata.lua, path);
-				return; -- Don't load this module
-			end
+			return nil, "incompatible with Lua "..lua_version; -- Don't load this module
 		end
+	end
 
-		if metadata.conflicts then
-			local conflicts_features = set.new(array.collect(metadata.conflicts:gmatch("[^, ]+")));
-			local conflicted_features = set.intersection(conflicts_features, core_features);
-			if not conflicted_features:empty() then
-				log("warn", "Not loading module, due to conflicting features '%s': %s", conflicted_features, path);
-				return; -- Don't load this module
+	if metadata.conflicts then
+		local conflicts_features = set.new(array.collect(metadata.conflicts:gmatch("[^, ]+")));
+		local conflicted_features = set.intersection(conflicts_features, core_features);
+		if not conflicted_features:empty() then
+			if prosody.process_type ~= "prosodyctl" then
+				log("warn", "Not loading module, due to conflict with built-in features '%s': %s", conflicted_features, path);
 			end
+			return nil, "conflict with built-in feature"; -- Don't load this module
 		end
-		if metadata.requires then
-			local required_features = set.new(array.collect(metadata.requires:gmatch("[^, ]+")));
-			local missing_features = required_features - core_features;
-			if not missing_features:empty() then
+	end
+	if metadata.requires then
+		local required_features = set.new(array.collect(metadata.requires:gmatch("[^, ]+")));
+		local missing_features = required_features - core_features;
+		if not missing_features:empty() then
+			if prosody.process_type ~= "prosodyctl" then
 				log("warn", "Not loading module, due to missing features '%s': %s", missing_features, path);
-				return; -- Don't load this module
 			end
+			return nil, "Prosody version missing required feature"; -- Don't load this module
 		end
+	end
 
-		return path, content, metadata;
-	end;
+	return path, content, metadata;
+end;
+
+local loader = pluginloader.init({
+	load_filter_cb = plugin_load_filter_cb;
 });
 
 local load_modules_for_host, load, unload, reload, get_module, get_items;
--- a/util/pluginloader.lua	Fri Apr 04 16:50:25 2025 +0100
+++ b/util/pluginloader.lua	Wed Apr 09 10:53:37 2025 +0100
@@ -25,6 +25,7 @@
 function pluginloader_methods:load_file(names)
 	local file, err, path;
 	local load_filter_cb = self._options.load_filter_cb;
+	local last_filter_path, last_filter_err;
 	for i=1,#plugin_dir do
 		for j=1,#names do
 			path = plugin_dir[i]..names[j];
@@ -36,12 +37,18 @@
 				if load_filter_cb then
 					path, content, metadata = load_filter_cb(path, content);
 				end
-				if content and path then
+				if path and content then
 					return content, path, metadata;
+				else
+					last_filter_path = plugin_dir[i]..names[j];
+					last_filter_err = content or "skipped";
 				end
 			end
 		end
 	end
+	if last_filter_err then
+		return nil, err..(" (%s skipped because of %s)"):format(last_filter_path, last_filter_err);
+	end
 	return file, err;
 end