Software /
code /
prosody
Comparison
core/configmanager.lua @ 13626:ac60c21015c7
core.configmanager: Add ways to read config values from files
Inspired by something MattJ said
Allows retrieving config values from files which are expected to be
relative to the config directory, extending on the ENV_ method of
retrieving config values from outside the config file.
- FileLine retrieves the first line, stripping any trailing newline
- FileContents reads the whole file
- FileLines reads lines into an array
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 16 Jan 2025 15:05:00 +0100 |
parent | 13391:5c783cf58ae7 |
child | 13627:2db7b3b65363 |
comparison
equal
deleted
inserted
replaced
13625:ff13dd315e68 | 13626:ac60c21015c7 |
---|---|
159 | 159 |
160 error("Invalid syntax - missing '=' perhaps?", 2); | 160 error("Invalid syntax - missing '=' perhaps?", 2); |
161 end; | 161 end; |
162 }; | 162 }; |
163 | 163 |
164 -- For reading config values out of files. | |
165 local function filereader(basepath, defaultmode) | |
166 return function(filename, mode) | |
167 local f, err = io.open(resolve_relative_path(basepath, filename)); | |
168 if not f then error(err, 2); end | |
169 local content, err = f:read(mode or defaultmode); | |
170 f:close(); | |
171 if not content then error(err, 2); end | |
172 return content; | |
173 end | |
174 end | |
175 | |
176 -- Collect lines into an array | |
177 local function linereader(basepath) | |
178 return function(filename) | |
179 local ret = {}; | |
180 for line in io.lines(resolve_relative_path(basepath, filename)) do | |
181 t_insert(ret, line); | |
182 end | |
183 return ret; | |
184 end | |
185 end | |
186 | |
164 parser = {}; | 187 parser = {}; |
165 function parser.load(data, config_file, config_table) | 188 function parser.load(data, config_file, config_table) |
166 local set_options = {}; -- set_options[host.."/"..option_name] = true (when the option has been set already in this file) | 189 local set_options = {}; -- set_options[host.."/"..option_name] = true (when the option has been set already in this file) |
167 local warnings = {}; | 190 local warnings = {}; |
168 local env; | 191 local env; |
192 local config_path = config_file:gsub("[^"..path_sep.."]+$", ""); | |
193 | |
169 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below | 194 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below |
170 env = setmetatable({ | 195 env = setmetatable({ |
171 Host = true, host = true, VirtualHost = true, | 196 Host = true, host = true, VirtualHost = true, |
172 Component = true, component = true, | 197 Component = true, component = true, |
198 FileContents = true, | |
199 FileLine = true, | |
200 FileLines = true, | |
173 Include = true, include = true, RunScript = true }, { | 201 Include = true, include = true, RunScript = true }, { |
174 __index = function (_, k) | 202 __index = function (_, k) |
175 if k:match("^ENV_") then | 203 if k:match("^ENV_") then |
176 return os.getenv(k:sub(5)); | 204 return os.getenv(k:sub(5)); |
177 end | 205 end |
291 if not lfs then | 319 if not lfs then |
292 error(format("Error expanding wildcard pattern in Include %q - LuaFileSystem not available", file)); | 320 error(format("Error expanding wildcard pattern in Include %q - LuaFileSystem not available", file)); |
293 end | 321 end |
294 local path_pos, glob = file:match("()([^"..path_sep.."]+)$"); | 322 local path_pos, glob = file:match("()([^"..path_sep.."]+)$"); |
295 local path = file:sub(1, math_max(path_pos-2,0)); | 323 local path = file:sub(1, math_max(path_pos-2,0)); |
296 local config_path = config_file:gsub("[^"..path_sep.."]+$", ""); | |
297 if #path > 0 then | 324 if #path > 0 then |
298 path = resolve_relative_path(config_path, path); | 325 path = resolve_relative_path(config_path, path); |
299 else | 326 else |
300 path = config_path; | 327 path = config_path; |
301 end | 328 end |
306 end | 333 end |
307 end | 334 end |
308 return; | 335 return; |
309 end | 336 end |
310 -- Not a wildcard, so resolve (potentially) relative path and run through config parser | 337 -- Not a wildcard, so resolve (potentially) relative path and run through config parser |
311 file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file); | 338 file = resolve_relative_path(config_path, file); |
312 local f, err = io.open(file); | 339 local f, err = io.open(file); |
313 if f then | 340 if f then |
314 local ret, err = parser.load(f:read("*a"), file, config_table); | 341 local ret, err = parser.load(f:read("*a"), file, config_table); |
315 if not ret then error(err:gsub("%[string.-%]", file), 0); end | 342 if not ret then error(err:gsub("%[string.-%]", file), 0); end |
316 if err then | 343 if err then |
323 return f, err; | 350 return f, err; |
324 end | 351 end |
325 env.include = env.Include; | 352 env.include = env.Include; |
326 | 353 |
327 function env.RunScript(file) | 354 function env.RunScript(file) |
328 return dofile(resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file)); | 355 return dofile(resolve_relative_path(config_path, file)); |
329 end | 356 end |
357 | |
358 env.FileContents = filereader(config_path, "*a"); | |
359 env.FileLine = filereader(config_path, "*l"); | |
360 env.FileLines = linereader(config_path); | |
330 | 361 |
331 local chunk, err = envload(data, "@"..config_file, env); | 362 local chunk, err = envload(data, "@"..config_file, env); |
332 | 363 |
333 if not chunk then | 364 if not chunk then |
334 return nil, err; | 365 return nil, err; |