Comparison

core/configmanager.lua @ 3905:9222dad9e1e8

configmanager: Support for wildcards in Include directives
author Matthew Wild <mwild1@gmail.com>
date Mon, 20 Dec 2010 14:06:32 +0000
parent 3780:791aede977da
child 3929:7cb03d67101b
comparison
equal deleted inserted replaced
3904:f93163081b3c 3905:9222dad9e1e8
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 _G = _G; 9 local _G = _G;
10 local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, format = 10 local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table =
11 setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, string.format; 11 setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table;
12 12 local format, math_max = string.format, math.max;
13 13
14 local fire_event = prosody and prosody.events.fire_event or function () end; 14 local fire_event = prosody and prosody.events.fire_event or function () end;
15 15
16 local lfs = require "lfs";
16 local path_sep = package.config:sub(1,1); 17 local path_sep = package.config:sub(1,1);
17 18
18 module "configmanager" 19 module "configmanager"
19 20
20 local parsers = {}; 21 local parsers = {};
69 -- Helper function to resolve relative paths (needed by config) 70 -- Helper function to resolve relative paths (needed by config)
70 do 71 do
71 local rel_path_start = ".."..path_sep; 72 local rel_path_start = ".."..path_sep;
72 function resolve_relative_path(parent_path, path) 73 function resolve_relative_path(parent_path, path)
73 if path then 74 if path then
75 -- Some normalization
76 parent_path = parent_path:gsub("%"..path_sep.."+$", "");
77 path = path:gsub("^%.%"..path_sep.."+", "");
78
74 local is_relative; 79 local is_relative;
75 if path_sep == "/" and path:sub(1,1) ~= "/" then 80 if path_sep == "/" and path:sub(1,1) ~= "/" then
76 is_relative = true; 81 is_relative = true;
77 elseif path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\") then 82 elseif path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\") then
78 is_relative = true; 83 is_relative = true;
81 return parent_path..path_sep..path; 86 return parent_path..path_sep..path;
82 end 87 end
83 end 88 end
84 return path; 89 return path;
85 end 90 end
91 end
92
93 -- Helper function to convert a glob to a Lua pattern
94 local function glob_to_pattern(glob)
95 return "^"..glob:gsub("[%p*?]", function (c)
96 if c == "*" then
97 return ".*";
98 elseif c == "?" then
99 return ".";
100 else
101 return "%"..c;
102 end
103 end).."$";
86 end 104 end
87 105
88 function load(filename, format) 106 function load(filename, format)
89 format = format or filename:match("%w+$"); 107 format = format or filename:match("%w+$");
90 108
135 -- Built-in Lua parser 153 -- Built-in Lua parser
136 do 154 do
137 local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable; 155 local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable;
138 local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring; 156 local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring;
139 parsers.lua = {}; 157 parsers.lua = {};
140 function parsers.lua.load(data, filename, config) 158 function parsers.lua.load(data, config_file, config)
141 local env; 159 local env;
142 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below 160 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below
143 env = setmetatable({ 161 env = setmetatable({
144 Host = true, host = true, VirtualHost = true, 162 Host = true, host = true, VirtualHost = true,
145 Component = true, component = true, 163 Component = true, component = true,
197 return handle_config_options(module); 215 return handle_config_options(module);
198 end 216 end
199 end 217 end
200 env.component = env.Component; 218 env.component = env.Component;
201 219
202 function env.Include(file) 220 function env.Include(file, wildcard)
203 local f, err = io.open(file); 221 if file:match("[*?]") then
204 if f then 222 local path_pos, glob = file:match("()([^"..path_sep.."]+)$");
205 local data = f:read("*a"); 223 local path = file:sub(1, math_max(path_pos-2,0));
206 local file = resolve_relative_path(filename:gsub("[^"..path_sep.."]+$", ""), file); 224 if #path > 0 then
207 local ret, err = parsers.lua.load(data, file, config); 225 path = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), path);
208 if not ret then error(err:gsub("%[string.-%]", file), 0); end 226 else
209 end 227 path = ".";
210 if not f then error("Error loading included "..file..": "..err, 0); end 228 end
211 return f, err; 229 local patt = glob_to_pattern(glob);
230 for f in lfs.dir(path) do
231 if f:sub(1,1) ~= "." and f:match(patt) then
232 env.Include(path..path_sep..f);
233 end
234 end
235 else
236 local f, err = io.open(file);
237 if f then
238 local data = f:read("*a");
239 local file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file);
240 local ret, err = parsers.lua.load(data, file, config);
241 if not ret then error(err:gsub("%[string.-%]", file), 0); end
242 end
243 if not f then error("Error loading included "..file..": "..err, 0); end
244 return f, err;
245 end
212 end 246 end
213 env.include = env.Include; 247 env.include = env.Include;
214 248
215 function env.RunScript(file) 249 function env.RunScript(file)
216 return dofile(resolve_relative_path(filename:gsub("[^"..path_sep.."]+$", ""), file)); 250 return dofile(resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file));
217 end 251 end
218 252
219 local chunk, err = loadstring(data, "@"..filename); 253 local chunk, err = loadstring(data, "@"..config_file);
220 254
221 if not chunk then 255 if not chunk then
222 return nil, err; 256 return nil, err;
223 end 257 end
224 258