flickerstreak@28
|
1 --[[
|
flickerstreak@28
|
2 Name: AceLibrary
|
flickerstreak@28
|
3 Revision: $Rev: 49421 $
|
flickerstreak@28
|
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
flickerstreak@28
|
5 Inspired By: Iriel (iriel@vigilance-committee.org)
|
flickerstreak@28
|
6 Tekkub (tekkub@gmail.com)
|
flickerstreak@28
|
7 Revision: $Rev: 49421 $
|
flickerstreak@28
|
8 Website: http://www.wowace.com/
|
flickerstreak@28
|
9 Documentation: http://www.wowace.com/index.php/AceLibrary
|
flickerstreak@28
|
10 SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary
|
flickerstreak@28
|
11 Description: Versioning library to handle other library instances, upgrading,
|
flickerstreak@28
|
12 and proper access.
|
flickerstreak@28
|
13 It also provides a base for libraries to work off of, providing
|
flickerstreak@28
|
14 proper error tools. It is handy because all the errors occur in the
|
flickerstreak@28
|
15 file that called it, not in the library file itself.
|
flickerstreak@28
|
16 Dependencies: None
|
flickerstreak@28
|
17 License: LGPL v2.1
|
flickerstreak@28
|
18 ]]
|
flickerstreak@28
|
19
|
flickerstreak@28
|
20 local ACELIBRARY_MAJOR = "AceLibrary"
|
flickerstreak@28
|
21 local ACELIBRARY_MINOR = "$Revision: 49421 $"
|
flickerstreak@28
|
22
|
flickerstreak@28
|
23 local _G = getfenv(0)
|
flickerstreak@28
|
24 local previous = _G[ACELIBRARY_MAJOR]
|
flickerstreak@28
|
25 if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end
|
flickerstreak@28
|
26
|
flickerstreak@28
|
27 do
|
flickerstreak@28
|
28 -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
|
flickerstreak@28
|
29 -- LibStub is hereby placed in the Public Domain -- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
|
flickerstreak@28
|
30 local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
|
flickerstreak@28
|
31 local LibStub = _G[LIBSTUB_MAJOR]
|
flickerstreak@28
|
32
|
flickerstreak@28
|
33 if not LibStub or LibStub.minor < LIBSTUB_MINOR then
|
flickerstreak@28
|
34 LibStub = LibStub or {libs = {}, minors = {} }
|
flickerstreak@28
|
35 _G[LIBSTUB_MAJOR] = LibStub
|
flickerstreak@28
|
36 LibStub.minor = LIBSTUB_MINOR
|
flickerstreak@28
|
37
|
flickerstreak@28
|
38 function LibStub:NewLibrary(major, minor)
|
flickerstreak@28
|
39 assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
|
flickerstreak@28
|
40 minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
|
flickerstreak@28
|
41 local oldminor = self.minors[major]
|
flickerstreak@28
|
42 if oldminor and oldminor >= minor then return nil end
|
flickerstreak@28
|
43 self.minors[major], self.libs[major] = minor, self.libs[major] or {}
|
flickerstreak@28
|
44 return self.libs[major], oldminor
|
flickerstreak@28
|
45 end
|
flickerstreak@28
|
46
|
flickerstreak@28
|
47 function LibStub:GetLibrary(major, silent)
|
flickerstreak@28
|
48 if not self.libs[major] and not silent then
|
flickerstreak@28
|
49 error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
|
flickerstreak@28
|
50 end
|
flickerstreak@28
|
51 return self.libs[major], self.minors[major]
|
flickerstreak@28
|
52 end
|
flickerstreak@28
|
53
|
flickerstreak@28
|
54 function LibStub:IterateLibraries() return pairs(self.libs) end
|
flickerstreak@28
|
55 setmetatable(LibStub, { __call = LibStub.GetLibrary })
|
flickerstreak@28
|
56 end
|
flickerstreak@28
|
57 end
|
flickerstreak@28
|
58 local LibStub = _G.LibStub
|
flickerstreak@28
|
59
|
flickerstreak@28
|
60 -- If you don't want AceLibrary to enable libraries that are LoadOnDemand but
|
flickerstreak@28
|
61 -- disabled in the addon screen, set this to true.
|
flickerstreak@28
|
62 local DONT_ENABLE_LIBRARIES = nil
|
flickerstreak@28
|
63
|
flickerstreak@28
|
64 local function safecall(func,...)
|
flickerstreak@28
|
65 local success, err = pcall(func,...)
|
flickerstreak@28
|
66 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end
|
flickerstreak@28
|
67 end
|
flickerstreak@28
|
68
|
flickerstreak@28
|
69 local WoW22 = false
|
flickerstreak@28
|
70 if type(GetBuildInfo) == "function" then
|
flickerstreak@28
|
71 local success, buildinfo = pcall(GetBuildInfo)
|
flickerstreak@28
|
72 if success and type(buildinfo) == "string" then
|
flickerstreak@28
|
73 local num = tonumber(buildinfo:match("^(%d+%.%d+)"))
|
flickerstreak@28
|
74 if num and num >= 2.2 then
|
flickerstreak@28
|
75 WoW22 = true
|
flickerstreak@28
|
76 end
|
flickerstreak@28
|
77 end
|
flickerstreak@28
|
78 end
|
flickerstreak@28
|
79
|
flickerstreak@28
|
80 -- @table AceLibrary
|
flickerstreak@28
|
81 -- @brief System to handle all versioning of libraries.
|
flickerstreak@28
|
82 local AceLibrary = {}
|
flickerstreak@28
|
83 local AceLibrary_mt = {}
|
flickerstreak@28
|
84 setmetatable(AceLibrary, AceLibrary_mt)
|
flickerstreak@28
|
85
|
flickerstreak@28
|
86 local function error(self, message, ...)
|
flickerstreak@28
|
87 if type(self) ~= "table" then
|
flickerstreak@28
|
88 return _G.error(("Bad argument #1 to `error' (table expected, got %s)"):format(type(self)), 2)
|
flickerstreak@28
|
89 end
|
flickerstreak@28
|
90
|
flickerstreak@28
|
91 local stack = debugstack()
|
flickerstreak@28
|
92 if not message then
|
flickerstreak@28
|
93 local second = stack:match("\n(.-)\n")
|
flickerstreak@28
|
94 message = "error raised! " .. second
|
flickerstreak@28
|
95 else
|
flickerstreak@28
|
96 local arg = { ... } -- not worried about table creation, as errors don't happen often
|
flickerstreak@28
|
97
|
flickerstreak@28
|
98 for i = 1, #arg do
|
flickerstreak@28
|
99 arg[i] = tostring(arg[i])
|
flickerstreak@28
|
100 end
|
flickerstreak@28
|
101 for i = 1, 10 do
|
flickerstreak@28
|
102 table.insert(arg, "nil")
|
flickerstreak@28
|
103 end
|
flickerstreak@28
|
104 message = message:format(unpack(arg))
|
flickerstreak@28
|
105 end
|
flickerstreak@28
|
106
|
flickerstreak@28
|
107 if getmetatable(self) and getmetatable(self).__tostring then
|
flickerstreak@28
|
108 message = ("%s: %s"):format(tostring(self), message)
|
flickerstreak@28
|
109 elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then
|
flickerstreak@28
|
110 message = ("%s: %s"):format(self:GetLibraryVersion(), message)
|
flickerstreak@28
|
111 elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then
|
flickerstreak@28
|
112 message = ("%s: %s"):format(self.class:GetLibraryVersion(), message)
|
flickerstreak@28
|
113 end
|
flickerstreak@28
|
114
|
flickerstreak@28
|
115 local first = stack:gsub("\n.*", "")
|
flickerstreak@28
|
116 local file = first:gsub(".*\\(.*).lua:%d+: .*", "%1")
|
flickerstreak@28
|
117 file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
flickerstreak@28
|
118
|
flickerstreak@28
|
119
|
flickerstreak@28
|
120 local i = 0
|
flickerstreak@28
|
121 for s in stack:gmatch("\n([^\n]*)") do
|
flickerstreak@28
|
122 i = i + 1
|
flickerstreak@28
|
123 if not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then
|
flickerstreak@28
|
124 file = s:gsub("^.*\\(.*).lua:%d+: .*", "%1")
|
flickerstreak@28
|
125 file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
flickerstreak@28
|
126 break
|
flickerstreak@28
|
127 end
|
flickerstreak@28
|
128 end
|
flickerstreak@28
|
129 local j = 0
|
flickerstreak@28
|
130 for s in stack:gmatch("\n([^\n]*)") do
|
flickerstreak@28
|
131 j = j + 1
|
flickerstreak@28
|
132 if j > i and not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then
|
flickerstreak@28
|
133 return _G.error(message, j+1)
|
flickerstreak@28
|
134 end
|
flickerstreak@28
|
135 end
|
flickerstreak@28
|
136 return _G.error(message, 2)
|
flickerstreak@28
|
137 end
|
flickerstreak@28
|
138
|
flickerstreak@28
|
139 local assert
|
flickerstreak@28
|
140 if not WoW22 then
|
flickerstreak@28
|
141 function assert(self, condition, message, ...)
|
flickerstreak@28
|
142 if not condition then
|
flickerstreak@28
|
143 if not message then
|
flickerstreak@28
|
144 local stack = debugstack()
|
flickerstreak@28
|
145 local second = stack:match("\n(.-)\n")
|
flickerstreak@28
|
146 message = "assertion failed! " .. second
|
flickerstreak@28
|
147 end
|
flickerstreak@28
|
148 return error(self, message, ...)
|
flickerstreak@28
|
149 end
|
flickerstreak@28
|
150 return condition
|
flickerstreak@28
|
151 end
|
flickerstreak@28
|
152 end
|
flickerstreak@28
|
153
|
flickerstreak@28
|
154 local type = type
|
flickerstreak@28
|
155 local function argCheck(self, arg, num, kind, kind2, kind3, kind4, kind5)
|
flickerstreak@28
|
156 if type(num) ~= "number" then
|
flickerstreak@28
|
157 return error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num))
|
flickerstreak@28
|
158 elseif type(kind) ~= "string" then
|
flickerstreak@28
|
159 return error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind))
|
flickerstreak@28
|
160 end
|
flickerstreak@28
|
161 arg = type(arg)
|
flickerstreak@28
|
162 if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then
|
flickerstreak@28
|
163 local stack = debugstack()
|
flickerstreak@28
|
164 local func = stack:match("`argCheck'.-([`<].-['>])")
|
flickerstreak@28
|
165 if not func then
|
flickerstreak@28
|
166 func = stack:match("([`<].-['>])")
|
flickerstreak@28
|
167 end
|
flickerstreak@28
|
168 if kind5 then
|
flickerstreak@28
|
169 return error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg)
|
flickerstreak@28
|
170 elseif kind4 then
|
flickerstreak@28
|
171 return error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg)
|
flickerstreak@28
|
172 elseif kind3 then
|
flickerstreak@28
|
173 return error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg)
|
flickerstreak@28
|
174 elseif kind2 then
|
flickerstreak@28
|
175 return error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg)
|
flickerstreak@28
|
176 else
|
flickerstreak@28
|
177 return error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg)
|
flickerstreak@28
|
178 end
|
flickerstreak@28
|
179 end
|
flickerstreak@28
|
180 end
|
flickerstreak@28
|
181
|
flickerstreak@28
|
182 local pcall
|
flickerstreak@28
|
183 do
|
flickerstreak@28
|
184 local function check(self, ret, ...)
|
flickerstreak@28
|
185 if not ret then
|
flickerstreak@28
|
186 local s = ...
|
flickerstreak@28
|
187 return error(self, (s:gsub(".-%.lua:%d-: ", "")))
|
flickerstreak@28
|
188 else
|
flickerstreak@28
|
189 return ...
|
flickerstreak@28
|
190 end
|
flickerstreak@28
|
191 end
|
flickerstreak@28
|
192
|
flickerstreak@28
|
193 function pcall(self, func, ...)
|
flickerstreak@28
|
194 return check(self, _G.pcall(func, ...))
|
flickerstreak@28
|
195 end
|
flickerstreak@28
|
196 end
|
flickerstreak@28
|
197
|
flickerstreak@28
|
198 local recurse = {}
|
flickerstreak@28
|
199 local function addToPositions(t, major)
|
flickerstreak@28
|
200 if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then
|
flickerstreak@28
|
201 rawset(t, recurse, true)
|
flickerstreak@28
|
202 AceLibrary.positions[t] = major
|
flickerstreak@28
|
203 for k,v in pairs(t) do
|
flickerstreak@28
|
204 if type(v) == "table" and not rawget(v, recurse) then
|
flickerstreak@28
|
205 addToPositions(v, major)
|
flickerstreak@28
|
206 end
|
flickerstreak@28
|
207 if type(k) == "table" and not rawget(k, recurse) then
|
flickerstreak@28
|
208 addToPositions(k, major)
|
flickerstreak@28
|
209 end
|
flickerstreak@28
|
210 end
|
flickerstreak@28
|
211 local mt = getmetatable(t)
|
flickerstreak@28
|
212 if mt and not rawget(mt, recurse) then
|
flickerstreak@28
|
213 addToPositions(mt, major)
|
flickerstreak@28
|
214 end
|
flickerstreak@28
|
215 rawset(t, recurse, nil)
|
flickerstreak@28
|
216 end
|
flickerstreak@28
|
217 end
|
flickerstreak@28
|
218
|
flickerstreak@28
|
219 local function svnRevisionToNumber(text)
|
flickerstreak@28
|
220 local kind = type(text)
|
flickerstreak@28
|
221 if kind == "number" or tonumber(text) then
|
flickerstreak@28
|
222 return tonumber(text)
|
flickerstreak@28
|
223 elseif kind == "string" then
|
flickerstreak@28
|
224 if text:find("^%$Revision: (%d+) %$$") then
|
flickerstreak@28
|
225 return tonumber((text:match("^%$Revision: (%d+) %$$")))
|
flickerstreak@28
|
226 elseif text:find("^%$Rev: (%d+) %$$") then
|
flickerstreak@28
|
227 return tonumber((text:match("^%$Rev: (%d+) %$$")))
|
flickerstreak@28
|
228 elseif text:find("^%$LastChangedRevision: (%d+) %$$") then
|
flickerstreak@28
|
229 return tonumber((text:match("^%$LastChangedRevision: (%d+) %$$")))
|
flickerstreak@28
|
230 end
|
flickerstreak@28
|
231 end
|
flickerstreak@28
|
232 return nil
|
flickerstreak@28
|
233 end
|
flickerstreak@28
|
234
|
flickerstreak@28
|
235 local crawlReplace
|
flickerstreak@28
|
236 do
|
flickerstreak@28
|
237 local recurse = {}
|
flickerstreak@28
|
238 local function func(t, to, from)
|
flickerstreak@28
|
239 if recurse[t] then
|
flickerstreak@28
|
240 return
|
flickerstreak@28
|
241 end
|
flickerstreak@28
|
242 recurse[t] = true
|
flickerstreak@28
|
243 local mt = getmetatable(t)
|
flickerstreak@28
|
244 setmetatable(t, nil)
|
flickerstreak@28
|
245 rawset(t, to, rawget(t, from))
|
flickerstreak@28
|
246 rawset(t, from, nil)
|
flickerstreak@28
|
247 for k,v in pairs(t) do
|
flickerstreak@28
|
248 if v == from then
|
flickerstreak@28
|
249 t[k] = to
|
flickerstreak@28
|
250 elseif type(v) == "table" then
|
flickerstreak@28
|
251 if not recurse[v] then
|
flickerstreak@28
|
252 func(v, to, from)
|
flickerstreak@28
|
253 end
|
flickerstreak@28
|
254 end
|
flickerstreak@28
|
255
|
flickerstreak@28
|
256 if type(k) == "table" then
|
flickerstreak@28
|
257 if not recurse[k] then
|
flickerstreak@28
|
258 func(k, to, from)
|
flickerstreak@28
|
259 end
|
flickerstreak@28
|
260 end
|
flickerstreak@28
|
261 end
|
flickerstreak@28
|
262 setmetatable(t, mt)
|
flickerstreak@28
|
263 if mt then
|
flickerstreak@28
|
264 if mt == from then
|
flickerstreak@28
|
265 setmetatable(t, to)
|
flickerstreak@28
|
266 elseif not recurse[mt] then
|
flickerstreak@28
|
267 func(mt, to, from)
|
flickerstreak@28
|
268 end
|
flickerstreak@28
|
269 end
|
flickerstreak@28
|
270 end
|
flickerstreak@28
|
271 function crawlReplace(t, to, from)
|
flickerstreak@28
|
272 func(t, to, from)
|
flickerstreak@28
|
273 for k in pairs(recurse) do
|
flickerstreak@28
|
274 recurse[k] = nil
|
flickerstreak@28
|
275 end
|
flickerstreak@28
|
276 end
|
flickerstreak@28
|
277 end
|
flickerstreak@28
|
278
|
flickerstreak@28
|
279 -- @function destroyTable
|
flickerstreak@28
|
280 -- @brief remove all the contents of a table
|
flickerstreak@28
|
281 -- @param t table to destroy
|
flickerstreak@28
|
282 local function destroyTable(t)
|
flickerstreak@28
|
283 setmetatable(t, nil)
|
flickerstreak@28
|
284 for k,v in pairs(t) do
|
flickerstreak@28
|
285 t[k] = nil
|
flickerstreak@28
|
286 end
|
flickerstreak@28
|
287 end
|
flickerstreak@28
|
288
|
flickerstreak@28
|
289 local function isFrame(frame)
|
flickerstreak@28
|
290 return type(frame) == "table" and type(rawget(frame, 0)) == "userdata" and type(rawget(frame, 'IsFrameType')) == "function" and getmetatable(frame) and type(rawget(getmetatable(frame), '__index')) == "function"
|
flickerstreak@28
|
291 end
|
flickerstreak@28
|
292
|
flickerstreak@28
|
293 -- @function copyTable
|
flickerstreak@28
|
294 -- @brief Create a shallow copy of a table and return it.
|
flickerstreak@28
|
295 -- @param from The table to copy from
|
flickerstreak@28
|
296 -- @return A shallow copy of the table
|
flickerstreak@28
|
297 local function copyTable(from, to)
|
flickerstreak@28
|
298 if not to then
|
flickerstreak@28
|
299 to = {}
|
flickerstreak@28
|
300 end
|
flickerstreak@28
|
301 for k,v in pairs(from) do
|
flickerstreak@28
|
302 to[k] = v
|
flickerstreak@28
|
303 end
|
flickerstreak@28
|
304 setmetatable(to, getmetatable(from))
|
flickerstreak@28
|
305 return to
|
flickerstreak@28
|
306 end
|
flickerstreak@28
|
307
|
flickerstreak@28
|
308 -- @function deepTransfer
|
flickerstreak@28
|
309 -- @brief Fully transfer all data, keeping proper previous table
|
flickerstreak@28
|
310 -- backreferences stable.
|
flickerstreak@28
|
311 -- @param to The table with which data is to be injected into
|
flickerstreak@28
|
312 -- @param from The table whose data will be injected into the first
|
flickerstreak@28
|
313 -- @param saveFields If available, a shallow copy of the basic data is saved
|
flickerstreak@28
|
314 -- in here.
|
flickerstreak@28
|
315 -- @param list The account of table references
|
flickerstreak@28
|
316 -- @param list2 The current status on which tables have been traversed.
|
flickerstreak@28
|
317 local deepTransfer
|
flickerstreak@28
|
318 do
|
flickerstreak@28
|
319 -- @function examine
|
flickerstreak@28
|
320 -- @brief Take account of all the table references to be shared
|
flickerstreak@28
|
321 -- between the to and from tables.
|
flickerstreak@28
|
322 -- @param to The table with which data is to be injected into
|
flickerstreak@28
|
323 -- @param from The table whose data will be injected into the first
|
flickerstreak@28
|
324 -- @param list An account of the table references
|
flickerstreak@28
|
325 local function examine(to, from, list, major)
|
flickerstreak@28
|
326 list[from] = to
|
flickerstreak@28
|
327 for k,v in pairs(from) do
|
flickerstreak@28
|
328 if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then
|
flickerstreak@28
|
329 if from[k] == to[k] then
|
flickerstreak@28
|
330 list[from[k]] = to[k]
|
flickerstreak@28
|
331 elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then
|
flickerstreak@28
|
332 list[from[k]] = from[k]
|
flickerstreak@28
|
333 elseif not list[from[k]] then
|
flickerstreak@28
|
334 examine(to[k], from[k], list, major)
|
flickerstreak@28
|
335 end
|
flickerstreak@28
|
336 end
|
flickerstreak@28
|
337 end
|
flickerstreak@28
|
338 return list
|
flickerstreak@28
|
339 end
|
flickerstreak@28
|
340
|
flickerstreak@28
|
341 function deepTransfer(to, from, saveFields, major, list, list2)
|
flickerstreak@28
|
342 setmetatable(to, nil)
|
flickerstreak@28
|
343 if not list then
|
flickerstreak@28
|
344 list = {}
|
flickerstreak@28
|
345 list2 = {}
|
flickerstreak@28
|
346 examine(to, from, list, major)
|
flickerstreak@28
|
347 end
|
flickerstreak@28
|
348 list2[to] = to
|
flickerstreak@28
|
349 for k,v in pairs(to) do
|
flickerstreak@28
|
350 if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then
|
flickerstreak@28
|
351 if saveFields then
|
flickerstreak@28
|
352 saveFields[k] = v
|
flickerstreak@28
|
353 end
|
flickerstreak@28
|
354 to[k] = nil
|
flickerstreak@28
|
355 elseif v ~= _G then
|
flickerstreak@28
|
356 if saveFields then
|
flickerstreak@28
|
357 saveFields[k] = copyTable(v)
|
flickerstreak@28
|
358 end
|
flickerstreak@28
|
359 end
|
flickerstreak@28
|
360 end
|
flickerstreak@28
|
361 for k in pairs(from) do
|
flickerstreak@28
|
362 if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then
|
flickerstreak@28
|
363 if not list2[to[k]] then
|
flickerstreak@28
|
364 deepTransfer(to[k], from[k], nil, major, list, list2)
|
flickerstreak@28
|
365 end
|
flickerstreak@28
|
366 to[k] = list[to[k]] or list2[to[k]]
|
flickerstreak@28
|
367 else
|
flickerstreak@28
|
368 rawset(to, k, from[k])
|
flickerstreak@28
|
369 end
|
flickerstreak@28
|
370 end
|
flickerstreak@28
|
371 setmetatable(to, getmetatable(from))
|
flickerstreak@28
|
372 local mt = getmetatable(to)
|
flickerstreak@28
|
373 if mt then
|
flickerstreak@28
|
374 if list[mt] then
|
flickerstreak@28
|
375 setmetatable(to, list[mt])
|
flickerstreak@28
|
376 elseif mt.__index and list[mt.__index] then
|
flickerstreak@28
|
377 mt.__index = list[mt.__index]
|
flickerstreak@28
|
378 end
|
flickerstreak@28
|
379 end
|
flickerstreak@28
|
380 destroyTable(from)
|
flickerstreak@28
|
381 end
|
flickerstreak@28
|
382 end
|
flickerstreak@28
|
383
|
flickerstreak@28
|
384 local function TryToEnable(addon)
|
flickerstreak@28
|
385 if DONT_ENABLE_LIBRARIES then return end
|
flickerstreak@28
|
386 local isondemand = IsAddOnLoadOnDemand(addon)
|
flickerstreak@28
|
387 if isondemand then
|
flickerstreak@28
|
388 local _, _, _, enabled = GetAddOnInfo(addon)
|
flickerstreak@28
|
389 EnableAddOn(addon)
|
flickerstreak@28
|
390 local _, _, _, _, loadable = GetAddOnInfo(addon)
|
flickerstreak@28
|
391 if not loadable and not enabled then
|
flickerstreak@28
|
392 DisableAddOn(addon)
|
flickerstreak@28
|
393 end
|
flickerstreak@28
|
394
|
flickerstreak@28
|
395 return loadable
|
flickerstreak@28
|
396 end
|
flickerstreak@28
|
397 end
|
flickerstreak@28
|
398
|
flickerstreak@28
|
399 -- @method TryToLoadStandalone
|
flickerstreak@28
|
400 -- @brief Attempt to find and load a standalone version of the requested library
|
flickerstreak@28
|
401 -- @param major A string representing the major version
|
flickerstreak@28
|
402 -- @return If library is found and loaded, true is return. If not loadable, false is returned.
|
flickerstreak@28
|
403 -- If the library has been requested previously, nil is returned.
|
flickerstreak@28
|
404 local function TryToLoadStandalone(major)
|
flickerstreak@28
|
405 if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end
|
flickerstreak@28
|
406 if AceLibrary.scannedlibs[major] then return end
|
flickerstreak@28
|
407
|
flickerstreak@28
|
408 AceLibrary.scannedlibs[major] = true
|
flickerstreak@28
|
409
|
flickerstreak@28
|
410 local name, _, _, enabled, loadable = GetAddOnInfo(major)
|
flickerstreak@28
|
411
|
flickerstreak@28
|
412 loadable = (enabled and loadable) or TryToEnable(name)
|
flickerstreak@28
|
413
|
flickerstreak@28
|
414 local loaded = false
|
flickerstreak@28
|
415 if loadable then
|
flickerstreak@28
|
416 loaded = true
|
flickerstreak@28
|
417 LoadAddOn(name)
|
flickerstreak@28
|
418 end
|
flickerstreak@28
|
419
|
flickerstreak@28
|
420 local field = "X-AceLibrary-" .. major
|
flickerstreak@28
|
421 for i = 1, GetNumAddOns() do
|
flickerstreak@28
|
422 if GetAddOnMetadata(i, field) then
|
flickerstreak@28
|
423 name, _, _, enabled, loadable = GetAddOnInfo(i)
|
flickerstreak@28
|
424
|
flickerstreak@28
|
425 loadable = (enabled and loadable) or TryToEnable(name)
|
flickerstreak@28
|
426 if loadable then
|
flickerstreak@28
|
427 loaded = true
|
flickerstreak@28
|
428 LoadAddOn(name)
|
flickerstreak@28
|
429 end
|
flickerstreak@28
|
430 end
|
flickerstreak@28
|
431 end
|
flickerstreak@28
|
432 return loaded
|
flickerstreak@28
|
433 end
|
flickerstreak@28
|
434
|
flickerstreak@28
|
435 -- @method IsNewVersion
|
flickerstreak@28
|
436 -- @brief Obtain whether the supplied version would be an upgrade to the
|
flickerstreak@28
|
437 -- current version. This allows for bypass code in library
|
flickerstreak@28
|
438 -- declaration.
|
flickerstreak@28
|
439 -- @param major A string representing the major version
|
flickerstreak@28
|
440 -- @param minor An integer or an svn revision string representing the minor version
|
flickerstreak@28
|
441 -- @return whether the supplied version would be newer than what is
|
flickerstreak@28
|
442 -- currently available.
|
flickerstreak@28
|
443 function AceLibrary:IsNewVersion(major, minor)
|
flickerstreak@28
|
444 argCheck(self, major, 2, "string")
|
flickerstreak@28
|
445 TryToLoadStandalone(major)
|
flickerstreak@28
|
446
|
flickerstreak@28
|
447 if type(minor) == "string" then
|
flickerstreak@28
|
448 local m = svnRevisionToNumber(minor)
|
flickerstreak@28
|
449 if m then
|
flickerstreak@28
|
450 minor = m
|
flickerstreak@28
|
451 else
|
flickerstreak@28
|
452 _G.error(("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2)
|
flickerstreak@28
|
453 end
|
flickerstreak@28
|
454 end
|
flickerstreak@28
|
455 argCheck(self, minor, 3, "number")
|
flickerstreak@28
|
456 local lib, oldMinor = LibStub:GetLibrary(major, true)
|
flickerstreak@28
|
457 if lib then
|
flickerstreak@28
|
458 return oldMinor < minor
|
flickerstreak@28
|
459 end
|
flickerstreak@28
|
460 local data = self.libs[major]
|
flickerstreak@28
|
461 if not data then
|
flickerstreak@28
|
462 return true
|
flickerstreak@28
|
463 end
|
flickerstreak@28
|
464 return data.minor < minor
|
flickerstreak@28
|
465 end
|
flickerstreak@28
|
466
|
flickerstreak@28
|
467 -- @method HasInstance
|
flickerstreak@28
|
468 -- @brief Returns whether an instance exists. This allows for optional support of a library.
|
flickerstreak@28
|
469 -- @param major A string representing the major version.
|
flickerstreak@28
|
470 -- @param minor (optional) An integer or an svn revision string representing the minor version.
|
flickerstreak@28
|
471 -- @return Whether an instance exists.
|
flickerstreak@28
|
472 function AceLibrary:HasInstance(major, minor)
|
flickerstreak@28
|
473 argCheck(self, major, 2, "string")
|
flickerstreak@28
|
474 if minor ~= false then
|
flickerstreak@28
|
475 TryToLoadStandalone(major)
|
flickerstreak@28
|
476 end
|
flickerstreak@28
|
477
|
flickerstreak@28
|
478 local lib, ver = LibStub:GetLibrary(major, true)
|
flickerstreak@28
|
479 if not lib and self.libs[major] then
|
flickerstreak@28
|
480 lib, ver = self.libs[major].instance, self.libs[major].minor
|
flickerstreak@28
|
481 end
|
flickerstreak@28
|
482 if minor then
|
flickerstreak@28
|
483 if type(minor) == "string" then
|
flickerstreak@28
|
484 local m = svnRevisionToNumber(minor)
|
flickerstreak@28
|
485 if m then
|
flickerstreak@28
|
486 minor = m
|
flickerstreak@28
|
487 else
|
flickerstreak@28
|
488 _G.error(("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2)
|
flickerstreak@28
|
489 end
|
flickerstreak@28
|
490 end
|
flickerstreak@28
|
491 argCheck(self, minor, 3, "number")
|
flickerstreak@28
|
492 if not lib then
|
flickerstreak@28
|
493 return false
|
flickerstreak@28
|
494 end
|
flickerstreak@28
|
495 return ver == minor
|
flickerstreak@28
|
496 end
|
flickerstreak@28
|
497 return not not lib
|
flickerstreak@28
|
498 end
|
flickerstreak@28
|
499
|
flickerstreak@28
|
500 -- @method GetInstance
|
flickerstreak@28
|
501 -- @brief Returns the library with the given major/minor version.
|
flickerstreak@28
|
502 -- @param major A string representing the major version.
|
flickerstreak@28
|
503 -- @param minor (optional) An integer or an svn revision string representing the minor version.
|
flickerstreak@28
|
504 -- @return The library with the given major/minor version.
|
flickerstreak@28
|
505 function AceLibrary:GetInstance(major, minor)
|
flickerstreak@28
|
506 argCheck(self, major, 2, "string")
|
flickerstreak@28
|
507 if minor ~= false then
|
flickerstreak@28
|
508 TryToLoadStandalone(major)
|
flickerstreak@28
|
509 end
|
flickerstreak@28
|
510
|
flickerstreak@28
|
511 local data, ver = LibStub:GetLibrary(major, true)
|
flickerstreak@28
|
512 if not data then
|
flickerstreak@28
|
513 if self.libs[major] then
|
flickerstreak@28
|
514 data, ver = self.libs[major].instance, self.libs[major].minor
|
flickerstreak@28
|
515 else
|
flickerstreak@28
|
516 _G.error(("Cannot find a library instance of %s."):format(major), 2)
|
flickerstreak@28
|
517 return
|
flickerstreak@28
|
518 end
|
flickerstreak@28
|
519 end
|
flickerstreak@28
|
520 if minor then
|
flickerstreak@28
|
521 if type(minor) == "string" then
|
flickerstreak@28
|
522 local m = svnRevisionToNumber(minor)
|
flickerstreak@28
|
523 if m then
|
flickerstreak@28
|
524 minor = m
|
flickerstreak@28
|
525 else
|
flickerstreak@28
|
526 _G.error(("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2)
|
flickerstreak@28
|
527 end
|
flickerstreak@28
|
528 end
|
flickerstreak@28
|
529 argCheck(self, minor, 2, "number")
|
flickerstreak@28
|
530 if ver ~= minor then
|
flickerstreak@28
|
531 _G.error(("Cannot find a library instance of %s, minor version %d."):format(major, minor), 2)
|
flickerstreak@28
|
532 end
|
flickerstreak@28
|
533 end
|
flickerstreak@28
|
534 return data
|
flickerstreak@28
|
535 end
|
flickerstreak@28
|
536
|
flickerstreak@28
|
537 -- Syntax sugar. AceLibrary("FooBar-1.0")
|
flickerstreak@28
|
538 AceLibrary_mt.__call = AceLibrary.GetInstance
|
flickerstreak@28
|
539
|
flickerstreak@28
|
540 local donothing = function() end
|
flickerstreak@28
|
541
|
flickerstreak@28
|
542 local AceEvent
|
flickerstreak@28
|
543
|
flickerstreak@28
|
544 local tmp = {}
|
flickerstreak@28
|
545
|
flickerstreak@28
|
546 -- @method Register
|
flickerstreak@28
|
547 -- @brief Registers a new version of a given library.
|
flickerstreak@28
|
548 -- @param newInstance the library to register
|
flickerstreak@28
|
549 -- @param major the major version of the library
|
flickerstreak@28
|
550 -- @param minor the minor version of the library
|
flickerstreak@28
|
551 -- @param activateFunc (optional) A function to be called when the library is
|
flickerstreak@28
|
552 -- fully activated. Takes the arguments
|
flickerstreak@28
|
553 -- (newInstance [, oldInstance, oldDeactivateFunc]). If
|
flickerstreak@28
|
554 -- oldInstance is given, you should probably call
|
flickerstreak@28
|
555 -- oldDeactivateFunc(oldInstance).
|
flickerstreak@28
|
556 -- @param deactivateFunc (optional) A function to be called by a newer library's
|
flickerstreak@28
|
557 -- activateFunc.
|
flickerstreak@28
|
558 -- @param externalFunc (optional) A function to be called whenever a new
|
flickerstreak@28
|
559 -- library is registered.
|
flickerstreak@28
|
560 function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc)
|
flickerstreak@28
|
561 argCheck(self, newInstance, 2, "table")
|
flickerstreak@28
|
562 argCheck(self, major, 3, "string")
|
flickerstreak@28
|
563 if major ~= ACELIBRARY_MAJOR then
|
flickerstreak@28
|
564 for k,v in pairs(_G) do
|
flickerstreak@28
|
565 if v == newInstance then
|
flickerstreak@28
|
566 geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k))
|
flickerstreak@28
|
567 end
|
flickerstreak@28
|
568 end
|
flickerstreak@28
|
569 end
|
flickerstreak@28
|
570 if major ~= ACELIBRARY_MAJOR and not major:find("^[%a%-][%a%d%-]*%-%d+%.%d+$") then
|
flickerstreak@28
|
571 _G.error(string.format("Bad argument #3 to `Register'. Must be in the form of \"Name-1.0\". %q is not appropriate", major), 2)
|
flickerstreak@28
|
572 end
|
flickerstreak@28
|
573 if type(minor) == "string" then
|
flickerstreak@28
|
574 local m = svnRevisionToNumber(minor)
|
flickerstreak@28
|
575 if m then
|
flickerstreak@28
|
576 minor = m
|
flickerstreak@28
|
577 else
|
flickerstreak@28
|
578 _G.error(("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2)
|
flickerstreak@28
|
579 end
|
flickerstreak@28
|
580 end
|
flickerstreak@28
|
581 argCheck(self, minor, 4, "number")
|
flickerstreak@28
|
582 if math.floor(minor) ~= minor or minor < 0 then
|
flickerstreak@28
|
583 error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor)
|
flickerstreak@28
|
584 end
|
flickerstreak@28
|
585 argCheck(self, activateFunc, 5, "function", "nil")
|
flickerstreak@28
|
586 argCheck(self, deactivateFunc, 6, "function", "nil")
|
flickerstreak@28
|
587 argCheck(self, externalFunc, 7, "function", "nil")
|
flickerstreak@28
|
588 if not deactivateFunc then
|
flickerstreak@28
|
589 deactivateFunc = donothing
|
flickerstreak@28
|
590 end
|
flickerstreak@28
|
591 local data = self.libs[major]
|
flickerstreak@28
|
592 if not data then
|
flickerstreak@28
|
593 -- This is new
|
flickerstreak@28
|
594 if LibStub:GetLibrary(major, true) then
|
flickerstreak@28
|
595 error(self, "Cannot register library %q. It is already registered with LibStub.", major)
|
flickerstreak@28
|
596 end
|
flickerstreak@28
|
597 local instance = LibStub:NewLibrary(major, minor)
|
flickerstreak@28
|
598 copyTable(newInstance, instance)
|
flickerstreak@28
|
599 crawlReplace(instance, instance, newInstance)
|
flickerstreak@28
|
600 destroyTable(newInstance)
|
flickerstreak@28
|
601 if AceLibrary == newInstance then
|
flickerstreak@28
|
602 self = instance
|
flickerstreak@28
|
603 AceLibrary = instance
|
flickerstreak@28
|
604 end
|
flickerstreak@28
|
605 self.libs[major] = {
|
flickerstreak@28
|
606 instance = instance,
|
flickerstreak@28
|
607 minor = minor,
|
flickerstreak@28
|
608 deactivateFunc = deactivateFunc,
|
flickerstreak@28
|
609 externalFunc = externalFunc,
|
flickerstreak@28
|
610 }
|
flickerstreak@28
|
611 rawset(instance, 'GetLibraryVersion', function(self)
|
flickerstreak@28
|
612 return major, minor
|
flickerstreak@28
|
613 end)
|
flickerstreak@28
|
614 if not rawget(instance, 'error') then
|
flickerstreak@28
|
615 rawset(instance, 'error', error)
|
flickerstreak@28
|
616 end
|
flickerstreak@28
|
617 if not WoW22 and not rawget(instance, 'assert') then
|
flickerstreak@28
|
618 rawset(instance, 'assert', assert)
|
flickerstreak@28
|
619 end
|
flickerstreak@28
|
620 if not rawget(instance, 'argCheck') then
|
flickerstreak@28
|
621 rawset(instance, 'argCheck', argCheck)
|
flickerstreak@28
|
622 end
|
flickerstreak@28
|
623 if not rawget(instance, 'pcall') then
|
flickerstreak@28
|
624 rawset(instance, 'pcall', pcall)
|
flickerstreak@28
|
625 end
|
flickerstreak@28
|
626 addToPositions(instance, major)
|
flickerstreak@28
|
627 if activateFunc then
|
flickerstreak@28
|
628 safecall(activateFunc, instance, nil, nil) -- no old version, so explicit nil
|
flickerstreak@28
|
629
|
flickerstreak@28
|
630 --[[ if major ~= ACELIBRARY_MAJOR then
|
flickerstreak@28
|
631 for k,v in pairs(_G) do
|
flickerstreak@28
|
632 if v == instance then
|
flickerstreak@28
|
633 geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k))
|
flickerstreak@28
|
634 end
|
flickerstreak@28
|
635 end
|
flickerstreak@28
|
636 end]]
|
flickerstreak@28
|
637 end
|
flickerstreak@28
|
638
|
flickerstreak@28
|
639 if externalFunc then
|
flickerstreak@28
|
640 for k, data_instance in LibStub:IterateLibraries() do -- all libraries
|
flickerstreak@28
|
641 tmp[k] = data_instance
|
flickerstreak@28
|
642 end
|
flickerstreak@28
|
643 for k, data in pairs(self.libs) do -- Ace libraries which may not have been registered with LibStub
|
flickerstreak@28
|
644 tmp[k] = data.instance
|
flickerstreak@28
|
645 end
|
flickerstreak@28
|
646 for k, data_instance in pairs(tmp) do
|
flickerstreak@28
|
647 if k ~= major then
|
flickerstreak@28
|
648 safecall(externalFunc, instance, k, data_instance)
|
flickerstreak@28
|
649 end
|
flickerstreak@28
|
650 tmp[k] = nil
|
flickerstreak@28
|
651 end
|
flickerstreak@28
|
652 end
|
flickerstreak@28
|
653
|
flickerstreak@28
|
654 for k,data in pairs(self.libs) do -- only Ace libraries
|
flickerstreak@28
|
655 if k ~= major and data.externalFunc then
|
flickerstreak@28
|
656 safecall(data.externalFunc, data.instance, major, instance)
|
flickerstreak@28
|
657 end
|
flickerstreak@28
|
658 end
|
flickerstreak@28
|
659 if major == "AceEvent-2.0" then
|
flickerstreak@28
|
660 AceEvent = instance
|
flickerstreak@28
|
661 end
|
flickerstreak@28
|
662 if AceEvent then
|
flickerstreak@28
|
663 AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance)
|
flickerstreak@28
|
664 end
|
flickerstreak@28
|
665
|
flickerstreak@28
|
666 return instance
|
flickerstreak@28
|
667 end
|
flickerstreak@28
|
668 if minor <= data.minor then
|
flickerstreak@28
|
669 -- This one is already obsolete, raise an error.
|
flickerstreak@28
|
670 _G.error(("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end"):format(major, data.minor, minor, major, minor), 2)
|
flickerstreak@28
|
671 return
|
flickerstreak@28
|
672 end
|
flickerstreak@28
|
673 local instance = data.instance
|
flickerstreak@28
|
674 -- This is an update
|
flickerstreak@28
|
675 local oldInstance = {}
|
flickerstreak@28
|
676
|
flickerstreak@28
|
677 local libStubInstance = LibStub:GetLibrary(major, true)
|
flickerstreak@28
|
678 if not libStubInstance then -- non-LibStub AceLibrary registered the library
|
flickerstreak@28
|
679 -- pass
|
flickerstreak@28
|
680 elseif libStubInstance ~= instance then
|
flickerstreak@28
|
681 error(self, "Cannot register library %q. It is already registered with LibStub.", major)
|
flickerstreak@28
|
682 else
|
flickerstreak@28
|
683 LibStub:NewLibrary(major, minor) -- upgrade the minor version
|
flickerstreak@28
|
684 end
|
flickerstreak@28
|
685
|
flickerstreak@28
|
686 addToPositions(newInstance, major)
|
flickerstreak@28
|
687 local isAceLibrary = (AceLibrary == newInstance)
|
flickerstreak@28
|
688 local old_error, old_assert, old_argCheck, old_pcall
|
flickerstreak@28
|
689 if isAceLibrary then
|
flickerstreak@28
|
690 self = instance
|
flickerstreak@28
|
691 AceLibrary = instance
|
flickerstreak@28
|
692
|
flickerstreak@28
|
693 old_error = instance.error
|
flickerstreak@28
|
694 if not WoW22 then
|
flickerstreak@28
|
695 old_assert = instance.assert
|
flickerstreak@28
|
696 end
|
flickerstreak@28
|
697 old_argCheck = instance.argCheck
|
flickerstreak@28
|
698 old_pcall = instance.pcall
|
flickerstreak@28
|
699
|
flickerstreak@28
|
700 self.error = error
|
flickerstreak@28
|
701 if not WoW22 then
|
flickerstreak@28
|
702 self.assert = assert
|
flickerstreak@28
|
703 end
|
flickerstreak@28
|
704 self.argCheck = argCheck
|
flickerstreak@28
|
705 self.pcall = pcall
|
flickerstreak@28
|
706 end
|
flickerstreak@28
|
707 deepTransfer(instance, newInstance, oldInstance, major)
|
flickerstreak@28
|
708 crawlReplace(instance, instance, newInstance)
|
flickerstreak@28
|
709 local oldDeactivateFunc = data.deactivateFunc
|
flickerstreak@28
|
710 data.minor = minor
|
flickerstreak@28
|
711 data.deactivateFunc = deactivateFunc
|
flickerstreak@28
|
712 data.externalFunc = externalFunc
|
flickerstreak@28
|
713 rawset(instance, 'GetLibraryVersion', function()
|
flickerstreak@28
|
714 return major, minor
|
flickerstreak@28
|
715 end)
|
flickerstreak@28
|
716 if not rawget(instance, 'error') then
|
flickerstreak@28
|
717 rawset(instance, 'error', error)
|
flickerstreak@28
|
718 end
|
flickerstreak@28
|
719 if not WoW22 and not rawget(instance, 'assert') then
|
flickerstreak@28
|
720 rawset(instance, 'assert', assert)
|
flickerstreak@28
|
721 end
|
flickerstreak@28
|
722 if not rawget(instance, 'argCheck') then
|
flickerstreak@28
|
723 rawset(instance, 'argCheck', argCheck)
|
flickerstreak@28
|
724 end
|
flickerstreak@28
|
725 if not rawget(instance, 'pcall') then
|
flickerstreak@28
|
726 rawset(instance, 'pcall', pcall)
|
flickerstreak@28
|
727 end
|
flickerstreak@28
|
728 if isAceLibrary then
|
flickerstreak@28
|
729 for _,v in pairs(self.libs) do
|
flickerstreak@28
|
730 local i = type(v) == "table" and v.instance
|
flickerstreak@28
|
731 if type(i) == "table" then
|
flickerstreak@28
|
732 if not rawget(i, 'error') or i.error == old_error then
|
flickerstreak@28
|
733 rawset(i, 'error', error)
|
flickerstreak@28
|
734 end
|
flickerstreak@28
|
735 if not WoW22 and (not rawget(i, 'assert') or i.assert == old_assert) then
|
flickerstreak@28
|
736 rawset(i, 'assert', assert)
|
flickerstreak@28
|
737 end
|
flickerstreak@28
|
738 if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then
|
flickerstreak@28
|
739 rawset(i, 'argCheck', argCheck)
|
flickerstreak@28
|
740 end
|
flickerstreak@28
|
741 if not rawget(i, 'pcall') or i.pcall == old_pcall then
|
flickerstreak@28
|
742 rawset(i, 'pcall', pcall)
|
flickerstreak@28
|
743 end
|
flickerstreak@28
|
744 end
|
flickerstreak@28
|
745 end
|
flickerstreak@28
|
746 end
|
flickerstreak@28
|
747 if activateFunc then
|
flickerstreak@28
|
748 safecall(activateFunc, instance, oldInstance, oldDeactivateFunc)
|
flickerstreak@28
|
749
|
flickerstreak@28
|
750 --[[ if major ~= ACELIBRARY_MAJOR then
|
flickerstreak@28
|
751 for k,v in pairs(_G) do
|
flickerstreak@28
|
752 if v == instance then
|
flickerstreak@28
|
753 geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k))
|
flickerstreak@28
|
754 end
|
flickerstreak@28
|
755 end
|
flickerstreak@28
|
756 end]]
|
flickerstreak@28
|
757 else
|
flickerstreak@28
|
758 safecall(oldDeactivateFunc, oldInstance)
|
flickerstreak@28
|
759 end
|
flickerstreak@28
|
760 oldInstance = nil
|
flickerstreak@28
|
761
|
flickerstreak@28
|
762 if externalFunc then
|
flickerstreak@28
|
763 for k, data_instance in LibStub:IterateLibraries() do -- all libraries
|
flickerstreak@28
|
764 tmp[k] = data_instance
|
flickerstreak@28
|
765 end
|
flickerstreak@28
|
766 for k, data in pairs(self.libs) do -- Ace libraries which may not have been registered with LibStub
|
flickerstreak@28
|
767 tmp[k] = data.instance
|
flickerstreak@28
|
768 end
|
flickerstreak@28
|
769 for k, data_instance in pairs(tmp) do
|
flickerstreak@28
|
770 if k ~= major then
|
flickerstreak@28
|
771 safecall(externalFunc, instance, k, data_instance)
|
flickerstreak@28
|
772 end
|
flickerstreak@28
|
773 tmp[k] = nil
|
flickerstreak@28
|
774 end
|
flickerstreak@28
|
775 end
|
flickerstreak@28
|
776
|
flickerstreak@28
|
777 return instance
|
flickerstreak@28
|
778 end
|
flickerstreak@28
|
779
|
flickerstreak@28
|
780 function AceLibrary:IterateLibraries()
|
flickerstreak@28
|
781 local t = {}
|
flickerstreak@28
|
782 for major, instance in LibStub:IterateLibraries() do
|
flickerstreak@28
|
783 t[major] = instance
|
flickerstreak@28
|
784 end
|
flickerstreak@28
|
785 for major, data in pairs(self.libs) do
|
flickerstreak@28
|
786 t[major] = data.instance
|
flickerstreak@28
|
787 end
|
flickerstreak@28
|
788 return pairs(t)
|
flickerstreak@28
|
789 end
|
flickerstreak@28
|
790
|
flickerstreak@28
|
791 local function manuallyFinalize(major, instance)
|
flickerstreak@28
|
792 if AceLibrary.libs[major] then
|
flickerstreak@28
|
793 -- don't work on Ace libraries
|
flickerstreak@28
|
794 return
|
flickerstreak@28
|
795 end
|
flickerstreak@28
|
796 local finalizedExternalLibs = AceLibrary.finalizedExternalLibs
|
flickerstreak@28
|
797 if finalizedExternalLibs[major] then
|
flickerstreak@28
|
798 return
|
flickerstreak@28
|
799 end
|
flickerstreak@28
|
800 finalizedExternalLibs[major] = true
|
flickerstreak@28
|
801
|
flickerstreak@28
|
802 for k,data in pairs(AceLibrary.libs) do -- only Ace libraries
|
flickerstreak@28
|
803 if k ~= major and data.externalFunc then
|
flickerstreak@28
|
804 safecall(data.externalFunc, data.instance, major, instance)
|
flickerstreak@28
|
805 end
|
flickerstreak@28
|
806 end
|
flickerstreak@28
|
807 end
|
flickerstreak@28
|
808
|
flickerstreak@28
|
809 -- @function Activate
|
flickerstreak@28
|
810 -- @brief The activateFunc for AceLibrary itself. Called when
|
flickerstreak@28
|
811 -- AceLibrary properly registers.
|
flickerstreak@28
|
812 -- @param self Reference to AceLibrary
|
flickerstreak@28
|
813 -- @param oldLib (optional) Reference to an old version of AceLibrary
|
flickerstreak@28
|
814 -- @param oldDeactivate (optional) Function to deactivate the old lib
|
flickerstreak@28
|
815 local function activate(self, oldLib, oldDeactivate)
|
flickerstreak@28
|
816 AceLibrary = self
|
flickerstreak@28
|
817 if not self.libs then
|
flickerstreak@28
|
818 self.libs = oldLib and oldLib.libs or {}
|
flickerstreak@28
|
819 self.scannedlibs = oldLib and oldLib.scannedlibs or {}
|
flickerstreak@28
|
820 end
|
flickerstreak@28
|
821 if not self.positions then
|
flickerstreak@28
|
822 self.positions = oldLib and oldLib.positions or setmetatable({}, { __mode = "k" })
|
flickerstreak@28
|
823 end
|
flickerstreak@28
|
824 self.finalizedExternalLibs = oldLib and oldLib.finalizedExternalLibs or {}
|
flickerstreak@28
|
825 self.frame = oldLib and oldLib.frame or CreateFrame("Frame")
|
flickerstreak@28
|
826 self.frame:UnregisterAllEvents()
|
flickerstreak@28
|
827 self.frame:RegisterEvent("ADDON_LOADED")
|
flickerstreak@28
|
828 self.frame:SetScript("OnEvent", function()
|
flickerstreak@28
|
829 for major, instance in LibStub:IterateLibraries() do
|
flickerstreak@28
|
830 manuallyFinalize(major, instance)
|
flickerstreak@28
|
831 end
|
flickerstreak@28
|
832 end)
|
flickerstreak@28
|
833 for major, instance in LibStub:IterateLibraries() do
|
flickerstreak@28
|
834 manuallyFinalize(major, instance)
|
flickerstreak@28
|
835 end
|
flickerstreak@28
|
836
|
flickerstreak@28
|
837 -- Expose the library in the global environment
|
flickerstreak@28
|
838 _G[ACELIBRARY_MAJOR] = self
|
flickerstreak@28
|
839
|
flickerstreak@28
|
840 if oldDeactivate then
|
flickerstreak@28
|
841 oldDeactivate(oldLib)
|
flickerstreak@28
|
842 end
|
flickerstreak@28
|
843 end
|
flickerstreak@28
|
844
|
flickerstreak@28
|
845 if not previous then
|
flickerstreak@28
|
846 previous = AceLibrary
|
flickerstreak@28
|
847 end
|
flickerstreak@28
|
848 if not previous.libs then
|
flickerstreak@28
|
849 previous.libs = {}
|
flickerstreak@28
|
850 end
|
flickerstreak@28
|
851 AceLibrary.libs = previous.libs
|
flickerstreak@28
|
852 if not previous.positions then
|
flickerstreak@28
|
853 previous.positions = setmetatable({}, { __mode = "k" })
|
flickerstreak@28
|
854 end
|
flickerstreak@28
|
855 AceLibrary.positions = previous.positions
|
flickerstreak@28
|
856 AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate, nil)
|