Software / code / prosody
Comparison
core/modulemanager.lua @ 12254:5b0c8e499288
modulemanager: Add plugin load filter that reads module metadata from source
Metadata in modules is added using lines formatted as:
--% key: value
Where key is a valid identifier string, and value is also a string (leading
and trailing whitespace are trimmed during parsing).
The initial supported keys are:
--% requires_core_features: feature1, feature2, ...
--% conflicts_core_features: feature1, feature2. ...
These 'features' map to features reported by the new core.features module.
A benefit of this load-time metadata approach compared to e.g. something like
module:requires()/module:conflicts() is that we can continue to look in module
search paths for a suitable module. Aborting an already-loaded module due to
a version conflict would be too late.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 04 Feb 2022 14:20:00 +0000 |
| parent | 12253:57d35fcde488 |
| child | 12257:7adfd5d29576 |
comparison
equal
deleted
inserted
replaced
| 12253:57d35fcde488 | 12254:5b0c8e499288 |
|---|---|
| 4 -- | 4 -- |
| 5 -- This project is MIT/X11 licensed. Please see the | 5 -- This project is MIT/X11 licensed. Please see the |
| 6 -- COPYING file in the source package for more information. | 6 -- COPYING file in the source package for more information. |
| 7 -- | 7 -- |
| 8 | 8 |
| 9 local array = require "util.array"; | |
| 9 local logger = require "util.logger"; | 10 local logger = require "util.logger"; |
| 10 local log = logger.init("modulemanager"); | 11 local log = logger.init("modulemanager"); |
| 11 local config = require "core.configmanager"; | 12 local config = require "core.configmanager"; |
| 12 local pluginloader = require "util.pluginloader"; | 13 local pluginloader = require "util.pluginloader"; |
| 13 local envload = require "util.envload"; | 14 local envload = require "util.envload"; |
| 14 local set = require "util.set"; | 15 local set = require "util.set"; |
| 16 | |
| 17 local core_features = require "core.features".available; | |
| 15 | 18 |
| 16 local new_multitable = require "util.multitable".new; | 19 local new_multitable = require "util.multitable".new; |
| 17 local api = require "core.moduleapi"; -- Module API container | 20 local api = require "core.moduleapi"; -- Module API container |
| 18 | 21 |
| 19 local prosody = prosody; | 22 local prosody = prosody; |
| 51 | 54 |
| 52 local _ENV = nil; | 55 local _ENV = nil; |
| 53 -- luacheck: std none | 56 -- luacheck: std none |
| 54 | 57 |
| 55 local loader = pluginloader.init({ | 58 local loader = pluginloader.init({ |
| 59 load_filter_cb = function (path, content) | |
| 60 local metadata = {}; | |
| 61 for line in content:gmatch("([^\r\n]+)\r?\n") do | |
| 62 local key, value = line:match("^%-%-%% *([%w_]+): *(.+)$"); | |
| 63 if key then | |
| 64 value = value:gsub("%s+$", ""); | |
| 65 metadata[key] = value; | |
| 66 end | |
| 67 end | |
| 68 | |
| 69 if metadata.conflicts_core_features then | |
| 70 local conflicts_core_features = set.new(array.collect(metadata.conflicts_core_features:gmatch("[^, ]+"))); | |
| 71 local conflicted_features = set.intersection(conflicts_core_features, core_features); | |
| 72 if not conflicted_features:empty() then | |
| 73 log("warn", "Not loading module, due to conflicting features '%s': %s", conflicted_features, path); | |
| 74 return; -- Don't load this module | |
| 75 end | |
| 76 end | |
| 77 if metadata.requires_core_features then | |
| 78 local required_features = set.new(array.collect(metadata.requires_core_features:gmatch("[^, ]+"))); | |
| 79 local missing_features = required_features - core_features; | |
| 80 if not missing_features:empty() then | |
| 81 log("warn", "Not loading module, due to missing features '%s': %s", missing_features, path); | |
| 82 return; -- Don't load this module | |
| 83 end | |
| 84 end | |
| 85 | |
| 86 return path, content, metadata; | |
| 87 end; | |
| 56 }); | 88 }); |
| 57 | 89 |
| 58 local load_modules_for_host, load, unload, reload, get_module, get_items; | 90 local load_modules_for_host, load, unload, reload, get_module, get_items; |
| 59 local get_modules, is_loaded, module_has_method, call_module_method; | 91 local get_modules, is_loaded, module_has_method, call_module_method; |
| 60 | 92 |