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 |