chore: move addon into VanillaGuide/ + add standard .gitignore/.gitattributes
Matches the Exiles fork-layout convention (each addon in its own folder).
This commit is contained in:
@@ -0,0 +1,751 @@
|
||||
--[[
|
||||
Name: AceLibrary
|
||||
Revision: $Rev: 14130 $
|
||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
||||
Inspired By: Iriel (iriel@vigilance-committee.org)
|
||||
Tekkub (tekkub@gmail.com)
|
||||
Revision: $Rev: 14130 $
|
||||
Website: http://www.wowace.com/
|
||||
Documentation: http://www.wowace.com/index.php/AceLibrary
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary
|
||||
Description: Versioning library to handle other library instances, upgrading,
|
||||
and proper access.
|
||||
It also provides a base for libraries to work off of, providing
|
||||
proper error tools. It is handy because all the errors occur in the
|
||||
file that called it, not in the library file itself.
|
||||
Dependencies: None
|
||||
]]
|
||||
|
||||
local ACELIBRARY_MAJOR = "AceLibrary"
|
||||
local ACELIBRARY_MINOR = "$Revision: 14130 $"
|
||||
|
||||
local table_setn
|
||||
do
|
||||
local version = GetBuildInfo()
|
||||
if string.find(version, "^2%.") then
|
||||
-- 2.0.0
|
||||
table_setn = function() end
|
||||
else
|
||||
table_setn = table.setn
|
||||
end
|
||||
end
|
||||
|
||||
local string_gfind = string.gmatch or string.gfind
|
||||
|
||||
local _G = getfenv(0)
|
||||
local previous = _G[ACELIBRARY_MAJOR]
|
||||
if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end
|
||||
|
||||
-- @table AceLibrary
|
||||
-- @brief System to handle all versioning of libraries.
|
||||
local AceLibrary = {}
|
||||
local AceLibrary_mt = {}
|
||||
setmetatable(AceLibrary, AceLibrary_mt)
|
||||
|
||||
local tmp
|
||||
local function error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if type(self) ~= "table" then
|
||||
_G.error(string.format("Bad argument #1 to `error' (table expected, got %s)", type(self)), 2)
|
||||
end
|
||||
if not tmp then
|
||||
tmp = {}
|
||||
else
|
||||
for k in pairs(tmp) do tmp[k] = nil end
|
||||
table_setn(tmp, 0)
|
||||
end
|
||||
|
||||
table.insert(tmp, a1)
|
||||
table.insert(tmp, a2)
|
||||
table.insert(tmp, a3)
|
||||
table.insert(tmp, a4)
|
||||
table.insert(tmp, a5)
|
||||
table.insert(tmp, a6)
|
||||
table.insert(tmp, a7)
|
||||
table.insert(tmp, a8)
|
||||
table.insert(tmp, a9)
|
||||
table.insert(tmp, a10)
|
||||
table.insert(tmp, a11)
|
||||
table.insert(tmp, a12)
|
||||
table.insert(tmp, a13)
|
||||
table.insert(tmp, a14)
|
||||
table.insert(tmp, a15)
|
||||
table.insert(tmp, a16)
|
||||
table.insert(tmp, a17)
|
||||
table.insert(tmp, a18)
|
||||
table.insert(tmp, a19)
|
||||
table.insert(tmp, a20)
|
||||
|
||||
local stack = debugstack()
|
||||
if not message then
|
||||
local _,_,second = string.find(stack, "\n(.-)\n")
|
||||
message = "error raised! " .. second
|
||||
else
|
||||
for i = 1,table.getn(tmp) do
|
||||
tmp[i] = tostring(tmp[i])
|
||||
end
|
||||
for i = 1,10 do
|
||||
table.insert(tmp, "nil")
|
||||
end
|
||||
message = string.format(message, unpack(tmp))
|
||||
end
|
||||
|
||||
if getmetatable(self) and getmetatable(self).__tostring then
|
||||
message = string.format("%s: %s", tostring(self), message)
|
||||
elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then
|
||||
message = string.format("%s: %s", self:GetLibraryVersion(), message)
|
||||
elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then
|
||||
message = string.format("%s: %s", self.class:GetLibraryVersion(), message)
|
||||
end
|
||||
|
||||
local first = string.gsub(stack, "\n.*", "")
|
||||
local file = string.gsub(first, ".*\\(.*).lua:%d+: .*", "%1")
|
||||
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
||||
|
||||
local i = 0
|
||||
for s in string_gfind(stack, "\n([^\n]*)") do
|
||||
i = i + 1
|
||||
if not string.find(s, file .. "%.lua:%d+:") then
|
||||
file = string.gsub(s, "^.*\\(.*).lua:%d+: .*", "%1")
|
||||
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
||||
break
|
||||
end
|
||||
end
|
||||
local j = 0
|
||||
for s in string_gfind(stack, "\n([^\n]*)") do
|
||||
j = j + 1
|
||||
if j > i and not string.find(s, file .. "%.lua:%d+:") then
|
||||
_G.error(message, j + 1)
|
||||
return
|
||||
end
|
||||
end
|
||||
_G.error(message, 2)
|
||||
return
|
||||
end
|
||||
|
||||
local function assert(self, condition, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not condition then
|
||||
if not message then
|
||||
local stack = debugstack()
|
||||
local _,_,second = string.find(stack, "\n(.-)\n")
|
||||
message = "assertion failed! " .. second
|
||||
end
|
||||
error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
return
|
||||
end
|
||||
return condition
|
||||
end
|
||||
|
||||
local function argCheck(self, arg, num, kind, kind2, kind3, kind4, kind5)
|
||||
if type(num) ~= "number" then
|
||||
error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num))
|
||||
elseif type(kind) ~= "string" then
|
||||
error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind))
|
||||
end
|
||||
local errored = false
|
||||
arg = type(arg)
|
||||
if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then
|
||||
local _,_,func = string.find(debugstack(), "`argCheck'.-([`<].-['>])")
|
||||
if not func then
|
||||
_,_,func = string.find(debugstack(), "([`<].-['>])")
|
||||
end
|
||||
if kind5 then
|
||||
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)
|
||||
elseif kind4 then
|
||||
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)
|
||||
elseif kind3 then
|
||||
error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg)
|
||||
elseif kind2 then
|
||||
error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg)
|
||||
else
|
||||
error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function pcall(self, func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = _G.pcall(func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not a1 then
|
||||
error(self, string.gsub(a2, ".-%.lua:%d-: ", ""))
|
||||
else
|
||||
return a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
|
||||
end
|
||||
end
|
||||
|
||||
local recurse = {}
|
||||
local function addToPositions(t, major)
|
||||
if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then
|
||||
rawset(t, recurse, true)
|
||||
AceLibrary.positions[t] = major
|
||||
for k,v in pairs(t) do
|
||||
if type(v) == "table" and not rawget(v, recurse) then
|
||||
addToPositions(v, major)
|
||||
end
|
||||
if type(k) == "table" and not rawget(k, recurse) then
|
||||
addToPositions(k, major)
|
||||
end
|
||||
end
|
||||
local mt = getmetatable(t)
|
||||
if mt and not rawget(mt, recurse) then
|
||||
addToPositions(mt, major)
|
||||
end
|
||||
rawset(t, recurse, nil)
|
||||
end
|
||||
end
|
||||
|
||||
local function svnRevisionToNumber(text)
|
||||
if type(text) == "string" then
|
||||
if string.find(text, "^%$Revision: (%d+) %$$") then
|
||||
return tonumber((string.gsub(text, "^%$Revision: (%d+) %$$", "%1")))
|
||||
elseif string.find(text, "^%$Rev: (%d+) %$$") then
|
||||
return tonumber((string.gsub(text, "^%$Rev: (%d+) %$$", "%1")))
|
||||
elseif string.find(text, "^%$LastChangedRevision: (%d+) %$$") then
|
||||
return tonumber((string.gsub(text, "^%$LastChangedRevision: (%d+) %$$", "%1")))
|
||||
end
|
||||
elseif type(text) == "number" then
|
||||
return text
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local crawlReplace
|
||||
do
|
||||
local recurse = {}
|
||||
local function func(t, to, from)
|
||||
if recurse[t] then
|
||||
return
|
||||
end
|
||||
recurse[t] = true
|
||||
local mt = getmetatable(t)
|
||||
setmetatable(t, nil)
|
||||
rawset(t, to, rawget(t, from))
|
||||
rawset(t, from, nil)
|
||||
for k,v in pairs(t) do
|
||||
if v == from then
|
||||
t[k] = to
|
||||
elseif type(v) == "table" then
|
||||
if not recurse[v] then
|
||||
func(v, to, from)
|
||||
end
|
||||
end
|
||||
|
||||
if type(k) == "table" then
|
||||
if not recurse[k] then
|
||||
func(k, to, from)
|
||||
end
|
||||
end
|
||||
end
|
||||
setmetatable(t, mt)
|
||||
if mt then
|
||||
if mt == from then
|
||||
setmetatable(t, to)
|
||||
elseif not recurse[mt] then
|
||||
func(mt, to, from)
|
||||
end
|
||||
end
|
||||
end
|
||||
function crawlReplace(t, to, from)
|
||||
func(t, to, from)
|
||||
for k in pairs(recurse) do
|
||||
recurse[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- @function destroyTable
|
||||
-- @brief remove all the contents of a table
|
||||
-- @param t table to destroy
|
||||
local function destroyTable(t)
|
||||
setmetatable(t, nil)
|
||||
for k,v in pairs(t) do t[k] = nil end
|
||||
table_setn(t, 0)
|
||||
end
|
||||
|
||||
local function isFrame(frame)
|
||||
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"
|
||||
end
|
||||
|
||||
local new, del
|
||||
do
|
||||
local tables = setmetatable({}, {__mode = "k"})
|
||||
|
||||
function new()
|
||||
local t = next(tables)
|
||||
if t then
|
||||
tables[t] = nil
|
||||
return t
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
function del(t, depth)
|
||||
if depth and depth > 0 then
|
||||
for k,v in pairs(t) do
|
||||
if type(v) == "table" and not isFrame(v) then
|
||||
del(v, depth - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
destroyTable(t)
|
||||
tables[t] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- @function copyTable
|
||||
-- @brief Create a shallow copy of a table and return it.
|
||||
-- @param from The table to copy from
|
||||
-- @return A shallow copy of the table
|
||||
local function copyTable(from)
|
||||
local to = new()
|
||||
for k,v in pairs(from) do to[k] = v end
|
||||
table_setn(to, table.getn(from))
|
||||
setmetatable(to, getmetatable(from))
|
||||
return to
|
||||
end
|
||||
|
||||
-- @function deepTransfer
|
||||
-- @brief Fully transfer all data, keeping proper previous table
|
||||
-- backreferences stable.
|
||||
-- @param to The table with which data is to be injected into
|
||||
-- @param from The table whose data will be injected into the first
|
||||
-- @param saveFields If available, a shallow copy of the basic data is saved
|
||||
-- in here.
|
||||
-- @param list The account of table references
|
||||
-- @param list2 The current status on which tables have been traversed.
|
||||
local deepTransfer
|
||||
do
|
||||
-- @function examine
|
||||
-- @brief Take account of all the table references to be shared
|
||||
-- between the to and from tables.
|
||||
-- @param to The table with which data is to be injected into
|
||||
-- @param from The table whose data will be injected into the first
|
||||
-- @param list An account of the table references
|
||||
local function examine(to, from, list, major)
|
||||
list[from] = to
|
||||
for k,v in pairs(from) do
|
||||
if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then
|
||||
if from[k] == to[k] then
|
||||
list[from[k]] = to[k]
|
||||
elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then
|
||||
list[from[k]] = from[k]
|
||||
elseif not list[from[k]] then
|
||||
examine(to[k], from[k], list, major)
|
||||
end
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
function deepTransfer(to, from, saveFields, major, list, list2)
|
||||
setmetatable(to, nil)
|
||||
local createdList
|
||||
if not list then
|
||||
createdList = true
|
||||
list = new()
|
||||
list2 = new()
|
||||
examine(to, from, list, major)
|
||||
end
|
||||
list2[to] = to
|
||||
for k,v in pairs(to) do
|
||||
if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then
|
||||
if saveFields then
|
||||
saveFields[k] = v
|
||||
end
|
||||
to[k] = nil
|
||||
elseif v ~= _G then
|
||||
if saveFields then
|
||||
saveFields[k] = copyTable(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
for k in pairs(from) do
|
||||
if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then
|
||||
if not list2[to[k]] then
|
||||
deepTransfer(to[k], from[k], nil, major, list, list2)
|
||||
end
|
||||
to[k] = list[to[k]] or list2[to[k]]
|
||||
else
|
||||
rawset(to, k, from[k])
|
||||
end
|
||||
end
|
||||
table_setn(to, table.getn(from))
|
||||
setmetatable(to, getmetatable(from))
|
||||
local mt = getmetatable(to)
|
||||
if mt then
|
||||
if list[mt] then
|
||||
setmetatable(to, list[mt])
|
||||
elseif mt.__index and list[mt.__index] then
|
||||
mt.__index = list[mt.__index]
|
||||
end
|
||||
end
|
||||
destroyTable(from)
|
||||
if createdList then
|
||||
del(list)
|
||||
del(list2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- @method TryToLoadStandalone
|
||||
-- @brief Attempt to find and load a standalone version of the requested library
|
||||
-- @param major A string representing the major version
|
||||
-- @return If library is found, return values from the call to LoadAddOn are returned
|
||||
-- If the library has been requested previously, nil is returned.
|
||||
local function TryToLoadStandalone(major)
|
||||
if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end
|
||||
if AceLibrary.scannedlibs[major] then return end
|
||||
|
||||
AceLibrary.scannedlibs[major] = true
|
||||
|
||||
local name, _, _, enabled, loadable = GetAddOnInfo(major)
|
||||
if loadable then
|
||||
return LoadAddOn(name)
|
||||
end
|
||||
|
||||
for i=1,GetNumAddOns() do
|
||||
if GetAddOnMetadata(i, "X-AceLibrary-"..major) then
|
||||
local name, _, _, enabled, loadable = GetAddOnInfo(i)
|
||||
if loadable then
|
||||
return LoadAddOn(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- @method IsNewVersion
|
||||
-- @brief Obtain whether the supplied version would be an upgrade to the
|
||||
-- current version. This allows for bypass code in library
|
||||
-- declaration.
|
||||
-- @param major A string representing the major version
|
||||
-- @param minor An integer or an svn revision string representing the minor version
|
||||
-- @return whether the supplied version would be newer than what is
|
||||
-- currently available.
|
||||
function AceLibrary:IsNewVersion(major, minor)
|
||||
argCheck(self, major, 2, "string")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 3, "number")
|
||||
local data = self.libs[major]
|
||||
if not data then
|
||||
return true
|
||||
end
|
||||
return data.minor < minor
|
||||
end
|
||||
|
||||
-- @method HasInstance
|
||||
-- @brief Returns whether an instance exists. This allows for optional support of a library.
|
||||
-- @param major A string representing the major version.
|
||||
-- @param minor (optional) An integer or an svn revision string representing the minor version.
|
||||
-- @return Whether an instance exists.
|
||||
function AceLibrary:HasInstance(major, minor)
|
||||
argCheck(self, major, 2, "string")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
if minor then
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 3, "number")
|
||||
if not self.libs[major] then
|
||||
return
|
||||
end
|
||||
return self.libs[major].minor == minor
|
||||
end
|
||||
return self.libs[major] and true
|
||||
end
|
||||
|
||||
-- @method GetInstance
|
||||
-- @brief Returns the library with the given major/minor version.
|
||||
-- @param major A string representing the major version.
|
||||
-- @param minor (optional) An integer or an svn revision string representing the minor version.
|
||||
-- @return The library with the given major/minor version.
|
||||
function AceLibrary:GetInstance(major, minor)
|
||||
argCheck(self, major, 2, "string")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
local data = self.libs[major]
|
||||
if not data then
|
||||
_G.error(string.format("Cannot find a library instance of %s.", major), 2)
|
||||
return
|
||||
end
|
||||
if minor then
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 2, "number")
|
||||
if data.minor ~= minor then
|
||||
_G.error(string.format("Cannot find a library instance of %s, minor version %d.", major, minor), 2)
|
||||
return
|
||||
end
|
||||
end
|
||||
return data.instance
|
||||
end
|
||||
|
||||
-- Syntax sugar. AceLibrary("FooBar-1.0")
|
||||
AceLibrary_mt.__call = AceLibrary.GetInstance
|
||||
|
||||
local donothing
|
||||
|
||||
local AceEvent
|
||||
|
||||
-- @method Register
|
||||
-- @brief Registers a new version of a given library.
|
||||
-- @param newInstance the library to register
|
||||
-- @param major the major version of the library
|
||||
-- @param minor the minor version of the library
|
||||
-- @param activateFunc (optional) A function to be called when the library is
|
||||
-- fully activated. Takes the arguments
|
||||
-- (newInstance [, oldInstance, oldDeactivateFunc]). If
|
||||
-- oldInstance is given, you should probably call
|
||||
-- oldDeactivateFunc(oldInstance).
|
||||
-- @param deactivateFunc (optional) A function to be called by a newer library's
|
||||
-- activateFunc.
|
||||
-- @param externalFunc (optional) A function to be called whenever a new
|
||||
-- library is registered.
|
||||
function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc)
|
||||
argCheck(self, newInstance, 2, "table")
|
||||
argCheck(self, major, 3, "string")
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 4, "number")
|
||||
if math.floor(minor) ~= minor or minor < 0 then
|
||||
error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor)
|
||||
end
|
||||
argCheck(self, activateFunc, 5, "function", "nil")
|
||||
argCheck(self, deactivateFunc, 6, "function", "nil")
|
||||
argCheck(self, externalFunc, 7, "function", "nil")
|
||||
if not deactivateFunc then
|
||||
if not donothing then
|
||||
donothing = function() end
|
||||
end
|
||||
deactivateFunc = donothing
|
||||
end
|
||||
local data = self.libs[major]
|
||||
if not data then
|
||||
-- This is new
|
||||
local instance = copyTable(newInstance)
|
||||
crawlReplace(instance, instance, newInstance)
|
||||
destroyTable(newInstance)
|
||||
if AceLibrary == newInstance then
|
||||
self = instance
|
||||
AceLibrary = instance
|
||||
end
|
||||
self.libs[major] = {
|
||||
instance = instance,
|
||||
minor = minor,
|
||||
deactivateFunc = deactivateFunc,
|
||||
externalFunc = externalFunc,
|
||||
}
|
||||
rawset(instance, 'GetLibraryVersion', function(self)
|
||||
return major, minor
|
||||
end)
|
||||
if not rawget(instance, 'error') then
|
||||
rawset(instance, 'error', error)
|
||||
end
|
||||
if not rawget(instance, 'assert') then
|
||||
rawset(instance, 'assert', assert)
|
||||
end
|
||||
if not rawget(instance, 'argCheck') then
|
||||
rawset(instance, 'argCheck', argCheck)
|
||||
end
|
||||
if not rawget(instance, 'pcall') then
|
||||
rawset(instance, 'pcall', pcall)
|
||||
end
|
||||
addToPositions(instance, major)
|
||||
if activateFunc then
|
||||
activateFunc(instance, nil, nil) -- no old version, so explicit nil
|
||||
end
|
||||
|
||||
if externalFunc then
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major then
|
||||
externalFunc(instance, k, data.instance)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major and data.externalFunc then
|
||||
data.externalFunc(data.instance, major, instance)
|
||||
end
|
||||
end
|
||||
if major == "AceEvent-2.0" then
|
||||
AceEvent = instance
|
||||
end
|
||||
if AceEvent then
|
||||
AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance)
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
local instance = data.instance
|
||||
if minor <= data.minor then
|
||||
-- This one is already obsolete, raise an error.
|
||||
_G.error(string.format("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", major, data.minor, minor, major, minor), 2)
|
||||
return
|
||||
end
|
||||
-- This is an update
|
||||
local oldInstance = new()
|
||||
|
||||
addToPositions(newInstance, major)
|
||||
local isAceLibrary = (AceLibrary == newInstance)
|
||||
local old_error, old_assert, old_argCheck, old_pcall
|
||||
if isAceLibrary then
|
||||
self = instance
|
||||
AceLibrary = instance
|
||||
|
||||
old_error = instance.error
|
||||
old_assert = instance.assert
|
||||
old_argCheck = instance.argCheck
|
||||
old_pcall = instance.pcall
|
||||
|
||||
self.error = error
|
||||
self.assert = assert
|
||||
self.argCheck = argCheck
|
||||
self.pcall = pcall
|
||||
end
|
||||
deepTransfer(instance, newInstance, oldInstance, major)
|
||||
crawlReplace(instance, instance, newInstance)
|
||||
local oldDeactivateFunc = data.deactivateFunc
|
||||
data.minor = minor
|
||||
data.deactivateFunc = deactivateFunc
|
||||
data.externalFunc = externalFunc
|
||||
rawset(instance, 'GetLibraryVersion', function(self)
|
||||
return major, minor
|
||||
end)
|
||||
if not rawget(instance, 'error') then
|
||||
rawset(instance, 'error', error)
|
||||
end
|
||||
if not rawget(instance, 'assert') then
|
||||
rawset(instance, 'assert', assert)
|
||||
end
|
||||
if not rawget(instance, 'argCheck') then
|
||||
rawset(instance, 'argCheck', argCheck)
|
||||
end
|
||||
if not rawget(instance, 'pcall') then
|
||||
rawset(instance, 'pcall', pcall)
|
||||
end
|
||||
if isAceLibrary then
|
||||
for _,v in pairs(self.libs) do
|
||||
local i = type(v) == "table" and v.instance
|
||||
if type(i) == "table" then
|
||||
if not rawget(i, 'error') or i.error == old_error then
|
||||
rawset(i, 'error', error)
|
||||
end
|
||||
if not rawget(i, 'assert') or i.assert == old_assert then
|
||||
rawset(i, 'assert', assert)
|
||||
end
|
||||
if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then
|
||||
rawset(i, 'argCheck', argCheck)
|
||||
end
|
||||
if not rawget(i, 'pcall') or i.pcall == old_pcall then
|
||||
rawset(i, 'pcall', pcall)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if activateFunc then
|
||||
activateFunc(instance, oldInstance, oldDeactivateFunc)
|
||||
else
|
||||
oldDeactivateFunc(oldInstance)
|
||||
end
|
||||
del(oldInstance)
|
||||
|
||||
if externalFunc then
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major then
|
||||
externalFunc(instance, k, data.instance)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
local iter
|
||||
function AceLibrary:IterateLibraries()
|
||||
if not iter then
|
||||
local function iter(t, k)
|
||||
k = next(t, k)
|
||||
if not k then
|
||||
return nil
|
||||
else
|
||||
return k, t[k].instance
|
||||
end
|
||||
end
|
||||
end
|
||||
return iter, self.libs, nil
|
||||
end
|
||||
|
||||
-- @function Activate
|
||||
-- @brief The activateFunc for AceLibrary itself. Called when
|
||||
-- AceLibrary properly registers.
|
||||
-- @param self Reference to AceLibrary
|
||||
-- @param oldLib (optional) Reference to an old version of AceLibrary
|
||||
-- @param oldDeactivate (optional) Function to deactivate the old lib
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
if not self.libs then
|
||||
if oldLib then
|
||||
self.libs = oldLib.libs
|
||||
self.scannedlibs = oldLib.scannedlibs
|
||||
end
|
||||
if not self.libs then
|
||||
self.libs = {}
|
||||
end
|
||||
if not self.scannedlibs then
|
||||
self.scannedlibs = {}
|
||||
end
|
||||
end
|
||||
if not self.positions then
|
||||
if oldLib then
|
||||
self.positions = oldLib.positions
|
||||
end
|
||||
if not self.positions then
|
||||
self.positions = setmetatable({}, { __mode = "k" })
|
||||
end
|
||||
end
|
||||
|
||||
-- Expose the library in the global environment
|
||||
_G[ACELIBRARY_MAJOR] = self
|
||||
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
if not previous then
|
||||
previous = AceLibrary
|
||||
end
|
||||
if not previous.libs then
|
||||
previous.libs = {}
|
||||
end
|
||||
AceLibrary.libs = previous.libs
|
||||
if not previous.positions then
|
||||
previous.positions = setmetatable({}, { __mode = "k" })
|
||||
end
|
||||
AceLibrary.positions = previous.positions
|
||||
AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate)
|
||||
Reference in New Issue
Block a user