# HG changeset patch
# User mckenziemc
# Date 1291536777 28800
# Node ID 5362e308c3eb13f6d1088e88055c7f94001b2e6f
# Parent 930871e163bc31ce0f9630a77bd1acdb8d3d0ec1
renamed the old DependencyLoader module to DependencyLoader_Bootstrap
renamed DependencyLoader_Core to DependencyLoader
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/Ace3.xml
--- a/DependencyLoader/Ace3.xml Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/Addon.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader/Addon.lua Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,248 @@
+-- Addon
+-- Represents individual addon modules
+
+
+local addonName, addonTable = ...
+
+
+-- NOTE: I assume that the API addon functions are
+-- slightly quicker with an index than with a number.
+
+-- TODO: modify the dependency stuff to use the Errata module if available
+
+local Addon, addon = addonTable:NewClass("Addon")
+
+
+-- load ability masks
+Addon.loadMasks = {
+ reload = bit.lshift(1, 0), -- can load after reloadui
+ ondemand = bit.lshift(1, 1), -- can load on demand
+ forceafter = bit.lshift(1, 2), -- force load after it would normally be loaded
+ forcebefore = bit.lshift(1, 3), -- force load before it would normally be loaded
+}
+
+
+Addon.addons = {}
+Addon.nameToIndex = {}
+
+
+-- Internal function
+-- Creates a new Addon object
+-- @param id Name or index of the addon.
+function Addon:New(id)
+ local instance = {}
+ setmetatable(instance, self.instanceMetatable)
+
+ if type(id) == "number" then
+ -- TODO: make sure it's in range
+ instance.index = id
+ instance.name = GetAddOnInfo(id)
+ else
+ -- FIXME: allow blizzard addons?
+ local index
+
+ for i=1,GetNumAddOns() do
+ if GetAddOnInfo(i) == id then
+ index = i
+ break
+ end
+ end
+
+ if index then
+ instance.name = GetAddOnInfo(id)
+ instance.index = index
+ else
+ error("Addon not found")
+ end
+ end
+
+ return instance
+end
+
+
+--- Retrieves an Addon object.
+-- @param id Name or index of the addon to retrieve.
+-- @return The Addon object, or nil if not found.
+function Addon:Get(id)
+ if not self:Exists(id) then
+ return nil
+ end
+
+ if type(id) == "number" then
+ if self.addons[id] ~= nil then
+ return self.addons[id]
+ end
+
+ local new = self:New(id)
+ self.addons[new:GetIndex()] = new
+ self.nameToIndex[new:GetName()] = id
+
+ return new
+ elseif type(id) == "string" then
+ if self.nameToIndex[id] then
+ return self.addons[self.nameToIndex[id] ]
+ end
+
+ local new = self:New(id)
+ self.addons[new:GetIndex()] = new
+ self.nameToIndex[id] = new:GetIndex()
+
+ return new
+ end
+end
+
+-- Checks if an addon exists with the specified name.
+-- @param addon Name of the addon.
+-- @return True if the addon is present, false otherwise.
+function Addon:Exists(addon)
+ if type(addon) == "number" then
+ if addon >= 1 and addon <= GetNumAddOns() then
+ return true
+ else
+ return false
+ end
+ elseif type(addon) == "string" then
+ local status = select(6, GetAddOnInfo(addon))
+
+ if status == "MISSING" then
+ return false
+ else
+ return true
+ end
+ else
+ error()
+ end
+end
+
+
+function Addon:GetLoadMasks()
+ return self.masks
+end
+
+
+function addon:GetName()
+ return self.name
+end
+
+
+function addon:GetIndex()
+ return self.index
+end
+
+
+function addon:IsEnabled()
+ -- FIXME: written while tired; review later
+ local status = select(6, GetAddOnInfo(self.index))
+
+ if status == "DISABLED" then
+ return false
+ else
+ return true
+ end
+end
+
+
+function addon:GetLoadBitfield()
+ local bitfield = 0
+
+ if self:CanLoad() then
+ bitfield = bitfield + self.masks.reload
+ end
+
+ if self:CanLoD() then
+ bitfield = bitfield + self.masks.ondemand
+ end
+
+ if self:CanForceLoadAfter() then
+ bitfield = bitfield + self.masks.forceafter
+ end
+
+ if self:CanForceLoadBefore() then
+ bitfield = bitfield + self.masks.forcebefore
+ end
+
+ return bitfield
+end
+
+
+--- Checks if the addon is loadable.
+-- Considers interface issues, missing, etc. (NYI)
+-- Does not check dependencies.
+function addon:CanLoad()
+ -- FIXME: an addon may be present but unloadable if loading out of date addons is disabled.
+ return true
+end
+
+
+function addon:CanLoD()
+ -- FIXME: what will the client say about addons using LoadManagers if the LM was force-loaded?
+ if IsAddOnLoadOnDemand(self.name) then
+ return true
+ else
+ return false
+ end
+end
+
+
+function addon:CanForceLoadAfter()
+ -- TODO: check Errata module
+ return false
+end
+
+
+function addon:CanForceLoadBefore()
+ -- TODO: check Errata module
+ return false -- TODO: check if there's any reason addons can't be forceloaded
+end
+
+
+function addon:Enable()
+ -- FIXME: delay this till after PLAYER_LOGIN or it'll get force-loaded
+ EnableAddOn(self.name)
+end
+
+
+-- NOTE: only call for LoD, not force-loading
+function addon:Load()
+ assert(self:CanLoD())
+
+ EnableAddOn(self.name)
+ LoadAddOn(self.name)
+end
+
+
+function addon:ForceLoad()
+ assert(self:CanForceLoad())
+ -- TODO: make sure force-loading is available at this time
+
+ EnableAddOn(self.name) -- This should cause the game to also load this addon
+end
+
+
+function addon:GetDependencies()
+ -- TODO: consider no-lib embeds as deps?
+ return GetAddOnDependencies(self.index)
+end
+
+
+function addon:GetEmbeds()
+ local embeds = {}
+
+ local embedString = GetAddOnMetadata(self.name, "X-Embeds")
+
+ if embedString then
+ for match in string.gmatch(embedString, "[^,%s]+") do
+ table.insert(embeds, match)
+ end
+ end
+
+ return unpack(embeds)
+end
+
+function addon:IsLoaded()
+ if IsAddOnLoaded(self.index) then
+ return true
+ else
+ return false
+ end
+end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/Core.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader/Core.lua Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,293 @@
+
+
+
+local addonName, addonTable = ...
+
+
+local Core, core = addonTable:NewClass("Core")
+
+
+function Core:New()
+ local instance = {}
+ setmetatable(instance, self.instanceMetatable)
+
+ instance.addons = {}
+ instance.nameToIndex = {}
+
+ for i=1,GetNumAddOns() do
+ local newAddon = Addon:New(i)
+
+ instance.addons[i] = newAddon
+ instance.nameToIndex[newAddon:GetName()] = i
+ end
+
+ -- TODO: enable dependencies for any addons that have already loaded
+
+ return instance
+end
+
+
+-- @param addon Name or index of the addon to retrieve.
+-- @return The addon object, or nil if not found
+function core:GetAddon(addon)
+ if not Addon:Exists(addon) then
+ return nil
+ end
+
+ local index
+
+ if type(addon) == "string" then
+ index = self.nameToIndex[addon]
+ elseif type(addon) == "number" then
+ index = addon
+ end
+
+ return self.addons[index]
+end
+
+
+-- Checks if the tree rooted at the specified addon can be force-loaded.
+-- @param root The name or index of the root addon.
+function core:CanForceLoadTree(root)
+ -- convert root to an Addon object
+ root = self:GetAddon(root)
+ assert(root)
+
+ if root:IsLoaded() then
+ return true
+ end
+
+ -- check if the root itself can be force-loaded
+ if not root:CanForceLoad() then
+ return false
+ end
+
+ -- now check dependencies recursively
+ -- FIXME: prevent infinite recursion
+
+ local dependencies = {root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ local dep = self:GetAddon(depName)
+
+ if dep == nil then
+ return false -- missing dependency
+ end
+
+ -- if it's already loaded then skip to next one
+ if not dep:IsLoaded() then
+ if not self:CanForceLoadTree(depName) then
+ return false
+ end
+ end
+ end
+
+ return true
+end
+
+-- NOTE: any tree that can be loaded on demand is also eligible for force-loading
+-- Checks if the tree rooted at the specified addon can be loaded on demand.
+-- @param root The name or index of the root addon.
+function core:CanLoDTree(root)
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- since this will be used recursively, return true if
+ -- this is already loaded.
+ if root:IsLoaded() then
+ return true
+ end
+
+ -- true if all dependencies are loaded or LoD
+
+ if not root:CanLoD() then
+ return false
+ end
+
+ -- now check dependencies recursively
+ local dependencies = {root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ local dep = self:GetAddon(depName)
+
+ if not dep then
+ return false -- missing
+ end
+
+ if not dep:IsLoaded() then
+ if not self:CanLoDTree(depName) then
+ return false
+ end
+ end
+ end
+
+ return true
+end
+
+
+-- Checks if the tree rooted at the specified addon
+-- can be loaded if all dependencies are enabled
+-- the UI is reloaded.
+-- Basically makes sure all dependencies are installed.
+function core:CanReloadTree(root)
+ -- convert root to an Addon object
+ root = self:GetAddon(root)
+ assert(root)
+
+ if root:IsLoaded() then
+ return true
+ -- FIXME: deps may have been disabled
+ end
+
+ -- TODO: make sure the root isn't incompatible
+
+ -- now check dependencies recursively
+ -- FIXME: prevent infinite recursion
+
+ local dependencies = {root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ local dep = self:GetAddon(depName)
+
+ if dep == nil then
+ return false -- missing dependency
+ end
+
+ -- TODO: make sure it's compatible
+ end
+
+ return true
+end
+
+-- Loads the tree rooted at the specified addon.
+-- FIXME: load the root too or not?
+-- Supports both LoD addons and those that require force-loading.
+function core:LoadTree(addon)
+ -- don't check if the tree can actually be loaded.
+ -- external code should do that itself to check if it
+ -- should even call this at all.
+
+ if self:ForceLoadAvailable() then
+ -- LoD trees can also be force-loaded
+ self:ForceLoadTree(addon)
+ else
+ self:LoadLoDTree(addon)
+ end
+end
+
+
+-- load the root too, since it may actually be a leaf
+function core:ForceLoadTree(root)
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- load dependencies
+ local dependencies = {root:GetDependencies(addon)}
+ for i, depName in pairs(dependencies) do
+ self:ForceLoadTree(depName)
+ end
+
+ -- load embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)}
+ for i, embedName in pairs(embeds) do
+ if Addon:Exists(embedName) then
+ self:ForceLoadTree(embedName)
+ end
+ end
+
+ root:ForceLoad()
+end
+
+
+function core:LoadLoDTree(root)
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- load dependencies
+ local dependencies = {root:GetDependencies(addon)}
+ for i, depName in pairs(dependencies) do
+ self:LoadLoDTree(depName)
+ end
+
+ -- load embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)}
+ for i, embedName in pairs(embeds) do
+ if Addon:Exists(embedName) then
+ self:LoadLoDTree(embedName)
+ end
+ end
+
+ root:LoD()
+end
+
+
+-- I think the problem this solves is a major issue with
+-- migrating to separate libs. think about it more and document
+-- here and in project description
+function core:PrepareLoDTree(root)
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- assume root is LoD
+
+ -- check dependencies
+ local dependencies = {root:GetDependencies(addon)}
+ for i, depName in pairs(dependencies) do
+ local dep = self:GetAddon(depName)
+
+ -- assume external code made sure it exists
+
+ if dep:CanLoD() then
+ -- don't load it now but make sure its dependencies are prepared
+ self:PrepareLoDTree(depName)
+ else
+ -- FIXME: if it's already loaded
+ -- force-load it now so we can load the parent on demand
+ self:ForceLoadTree(depName)
+ end
+ end
+
+ -- prepare embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)} -- FIXME: addon?
+ for i, embedName in pairs(embeds) do
+ local embed = self:GetAddon(embedName)
+
+ if embed then
+ if embed:CanLoD() then
+ -- don't load it now but make sure its dependencies are prepared
+ self:PrepareLoDTree(embedName)
+ else
+ -- FIXME: if it's already loaded
+ -- force-load it now so we can load the parent on demand
+ self:ForceLoadTree(depName)
+ end
+ end
+ end
+end
+
+
+function Core:PrepareReloadTree(addon)
+ root = self:GetAddon(root)
+ assert(root)
+
+ root:Enable()
+
+ -- check dependencies
+ local dependencies = {root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ self:PrepareReloadTree(depName)
+ end
+
+ -- prepare embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)}
+ for i, embedName in pairs(embeds) do
+ local embed = self:GetAddon(embedName)
+
+ if embed then
+ self:PrepareReloadTree(embedName)
+ end
+ end
+end
+
+
+function Core:ForceLoadAvailable()
+ return true
+ -- FIXME: use field and a frame registered for PLAYER_LOGIN
+end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/DependencyLoader.toc
--- a/DependencyLoader/DependencyLoader.toc Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-## Interface: 40000
-
-## Notes: Bootstrap for DependencyLoader_Core
-## Author: mckenziemc
-
-## LoadManagers: !!!LoadFirst, AddonLoader
-## X-LoadFirst: true
-## X-LoadOn-Always: true
-
-
-load.xml
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/DependencyLoader_Core.toc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader/DependencyLoader_Core.toc Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,14 @@
+## Interface: 40000
+
+# TODO: actually explain what DependencyLoader does.
+## Notes: Core module of DependencyLoader
+## Author: mckenziemc
+
+# TODO: figure out some way to allow AddonLoader
+# to work with DependencyLoader
+## Dependencies: DependencyLoader, LibStub, LibPrint-1.0, Ace3
+
+## LoadOnDemand: 1
+
+
+load.xml
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/Tree.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader/Tree.lua Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,287 @@
+-- Tree
+-- Represents a recursive "tree" of addon
+-- dependencies rooted at a specific addon.
+
+
+local addonName, addonTable = ...
+
+
+-- TODO: prevent infinite loops in the recursive functions
+
+
+local Tree, tree = addonTable:NewClass("Tree")
+
+
+Tree.trees = {}
+
+-- internal
+-- Creates a new tree object
+-- @param root Name, index, or Addon object of the root addon.
+function Tree:New(root)
+ if type(root) ~= "table" then
+ root = addonTable.classes.Addon:Get(root)
+ end
+
+ local instance = {}
+ setmetatable(instance, self.instanceMetatable)
+
+ instance.root = root
+
+ return instance
+end
+
+
+--- Retrieves the tree rooted at the specified addon
+-- @param root Name, index, or Addon object of the root.
+function Tree:Get(root)
+ if type(root) ~= "table" then
+ root = addonTable.classes.Addon:Get(root)
+ end
+
+ local tree = self.trees[root]
+
+ if tree then
+ return tree
+ else
+ tree = self:New(root)
+ self.trees[root] = tree
+ return tree
+ end
+end
+
+
+function tree:GetLoadBitfield()
+ local bitfield = self.root:GetLoadBitfield()
+
+ local dependencies = {self.root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ local depTree = Tree:Get(depName)
+
+ if depTree == nil then
+ return 0
+ end
+
+ bitfield = bit.band(bitfield, depTree:GetLoadBitfield())
+ end
+
+ return bitfield
+end
+
+
+-- Checks if the tree rooted at the specified addon can be force-loaded.
+-- @param root The name or index of the root addon.
+function core:CanForceLoadTree(root)
+ -- TODO: if some addons have already loaded, we have to check
+ -- forceafter for those and forcebefore for the others
+ return false
+end
+
+
+-- NOTE: any tree that can be loaded on demand is also eligible for force-loading
+-- Checks if the tree rooted at the specified addon can be loaded on demand.
+-- @param root The name or index of the root addon.
+function core:CanLoDTree(root)
+ local bitfield = self:GetLoadBitfield()
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- since this will be used recursively, return true if
+ -- this is already loaded.
+ if root:IsLoaded() then
+ return true
+ end
+
+ -- true if all dependencies are loaded or LoD
+
+ if not root:CanLoD() then
+ return false
+ end
+
+ -- now check dependencies recursively
+ local dependencies = {root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ local dep = self:GetAddon(depName)
+
+ if not dep then
+ return false -- missing
+ end
+
+ if not dep:IsLoaded() then
+ if not self:CanLoDTree(depName) then
+ return false
+ end
+ end
+ end
+
+ return true
+end
+
+
+-- Checks if the tree rooted at the specified addon
+-- can be loaded if all dependencies are enabled
+-- the UI is reloaded.
+-- Basically makes sure all dependencies are installed.
+function core:CanReloadTree(root)
+ -- convert root to an Addon object
+ root = self:GetAddon(root)
+ assert(root)
+
+ if root:IsLoaded() then
+ return true
+ -- FIXME: deps may have been disabled
+ end
+
+ -- TODO: make sure the root isn't incompatible
+
+ -- now check dependencies recursively
+ -- FIXME: prevent infinite recursion
+
+ local dependencies = {root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ local dep = self:GetAddon(depName)
+
+ if dep == nil then
+ return false -- missing dependency
+ end
+
+ -- TODO: make sure it's compatible
+ end
+
+ return true
+end
+
+-- Loads the tree rooted at the specified addon.
+-- FIXME: load the root too or not?
+-- Supports both LoD addons and those that require force-loading.
+function core:LoadTree(addon)
+ -- don't check if the tree can actually be loaded.
+ -- external code should do that itself to check if it
+ -- should even call this at all.
+
+ if self:ForceLoadAvailable() then
+ -- LoD trees can also be force-loaded
+ self:ForceLoadTree(addon)
+ else
+ self:LoadLoDTree(addon)
+ end
+end
+
+
+-- load the root too, since it may actually be a leaf
+function core:ForceLoadTree(root)
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- load dependencies
+ local dependencies = {root:GetDependencies(addon)}
+ for i, depName in pairs(dependencies) do
+ self:ForceLoadTree(depName)
+ end
+
+ -- load embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)}
+ for i, embedName in pairs(embeds) do
+ if Addon:Exists(embedName) then
+ self:ForceLoadTree(embedName)
+ end
+ end
+
+ root:ForceLoad()
+end
+
+
+function core:LoadLoDTree(root)
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- load dependencies
+ local dependencies = {root:GetDependencies(addon)}
+ for i, depName in pairs(dependencies) do
+ self:LoadLoDTree(depName)
+ end
+
+ -- load embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)}
+ for i, embedName in pairs(embeds) do
+ if Addon:Exists(embedName) then
+ self:LoadLoDTree(embedName)
+ end
+ end
+
+ root:LoD()
+end
+
+
+-- I think the problem this solves is a major issue with
+-- migrating to separate libs. think about it more and document
+-- here and in project description
+function core:PrepareLoDTree(root)
+ root = self:GetAddon(root)
+ assert(root)
+
+ -- assume root is LoD
+
+ -- check dependencies
+ local dependencies = {root:GetDependencies(addon)}
+ for i, depName in pairs(dependencies) do
+ local dep = self:GetAddon(depName)
+
+ -- assume external code made sure it exists
+
+ if dep:CanLoD() then
+ -- don't load it now but make sure its dependencies are prepared
+ self:PrepareLoDTree(depName)
+ else
+ -- FIXME: if it's already loaded
+ -- force-load it now so we can load the parent on demand
+ self:ForceLoadTree(depName)
+ end
+ end
+
+ -- prepare embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)} -- FIXME: addon?
+ for i, embedName in pairs(embeds) do
+ local embed = self:GetAddon(embedName)
+
+ if embed then
+ if embed:CanLoD() then
+ -- don't load it now but make sure its dependencies are prepared
+ self:PrepareLoDTree(embedName)
+ else
+ -- FIXME: if it's already loaded
+ -- force-load it now so we can load the parent on demand
+ self:ForceLoadTree(depName)
+ end
+ end
+ end
+end
+
+
+function Core:PrepareReloadTree(addon)
+ root = self:GetAddon(root)
+ assert(root)
+
+ root:Enable()
+
+ -- check dependencies
+ local dependencies = {root:GetDependencies()}
+ for i, depName in pairs(dependencies) do
+ self:PrepareReloadTree(depName)
+ end
+
+ -- prepare embeds, if they are available separately
+ local embeds = {root:GetEmbeds(addon)}
+ for i, embedName in pairs(embeds) do
+ local embed = self:GetAddon(embedName)
+
+ if embed then
+ self:PrepareReloadTree(embedName)
+ end
+ end
+end
+
+
+function Core:ForceLoadAvailable()
+ return true
+ -- FIXME: use field and a frame registered for PLAYER_LOGIN
+end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/bootstrap.lua
--- a/DependencyLoader/bootstrap.lua Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
--- bootstrap.lua
--- Bootstrap code for DependencyLoader, allowing
--- the user to successfully load it without
--- explicitly enabling its own dependencies.
-
-
-local addonName, addonTable = ...
-
--- TODO: move and use dependency parsing function here?
-local dependencies = {"LibStub", "LibPrint-1.0", "Ace3"}
-
-local canLoad = true
-for _, addon in pairs(dependencies) do
- local reason = select(6, GetAddOnInfo(addon))
-
- if reason ~= nil and reason ~= "DISABLED" then
- canLoad = false
- break
- end
-end
-
-if not canLoad then
- print("Can't load DependencyLoader")
- return
-end
-
-
-print("Loading DependencyLoader")
-
-for _, addon in pairs(dependencies) do
- EnableAddOn(addon)
-end
-
-EnableAddOn("DependencyLoader_Core")
-LoadAddOn("DependencyLoader_Core")
-
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/class.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader/class.lua Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,24 @@
+-- class.lua
+-- Implements a generic class builder.
+
+
+local addonName, addonTable = ...
+
+-- FIXME: prevent duplicate class definitions
+
+print( string.format([[running %s\class.lua]], addonName) )
+
+addonTable.classes = {}
+
+function addonTable:NewClass(name)
+ local class, prototype, metatable = {}, {}, {}
+
+ class.prototype = prototype
+
+ metatable.__index = prototype
+ class.instanceMetatable = metatable
+
+ self.classes[name] = class
+
+ return class, prototype
+end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/embeds.xml
--- a/DependencyLoader/embeds.xml Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/frontend.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader/frontend.lua Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,83 @@
+-- main.lua
+--
+
+local addonName, addonTable = ...
+
+
+local DependencyLoader = LibStub("AceAddon-3.0"):NewAddon(addonName)
+_G[addonName] = DependencyLoader
+
+local libPrint = LibStub("LibPrint-1.0")
+DependencyLoader.printStream = libPrint:NewStream("DependencyLoader", "DpLdr", print)
+DependencyLoader.debugStream = libPrint:NewStream("DependencyLoader", "DpLdr", "mcm")
+
+-- temp
+DependencyLoader.classes = addonTable.classes
+
+function DependencyLoader:Print(...)
+ self.printStream:Print(...)
+end
+
+
+function DependencyLoader:Debug(...)
+ self.debugStream:Print(...)
+end
+
+
+function DependencyLoader:OnInitialize()
+ self:Debug("Initializing and enabling", addonName)
+ self:Enable()
+end
+
+
+function DependencyLoader:OnEnable()
+ self.core = addonTable.classes.Core:New()
+
+ self:Print("Enabled", addonName)
+
+ self:FixCurrentAddons()
+end
+
+function DependencyLoader:OnDisable()
+ self:Print("Disabled", addonName)
+end
+
+
+-- TODO: move this into core?
+
+-- Enables any dependencies needed by the addons
+-- that have already been enabled
+function DependencyLoader:FixCurrentAddons()
+ local core = self.core
+
+ for i=1, GetNumAddOns() do
+ local addon = self.core:GetAddon(i)
+
+ if addon:IsEnabled() then
+ if addon:IsLoaded() then
+ -- TODO: it might still help to enable its embeds
+ else
+ self:Debug("Checking", addon:GetName())
+
+ if addonTable.classes.Core:ForceLoadAvailable() then
+ if core:CanForceLoadTree(addon:GetName()) then
+ core:ForceLoadTree(addon:GetName())
+ else
+ print("Can't force load", addon:GetName())
+ end
+ else
+ if core:CanLoDTree(addon:GetName()) then
+ core:PrepareLoDTree(addon:GetName())
+ else
+ print("Couldn't load", addon:GetName(), "on demand.")
+ end
+ end
+ end
+ end
+ end
+end
+
+
+
+
+
\ No newline at end of file
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/load.xml
--- a/DependencyLoader/load.xml Sat Dec 04 23:05:34 2010 -0800
+++ b/DependencyLoader/load.xml Sun Dec 05 00:12:57 2010 -0800
@@ -1,1 +1,1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader/start.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader/start.lua Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,21 @@
+-- start.lua
+-- Initializes components of DependencyLoader
+
+
+local addonName, addonTable = ...
+
+
+print( string.format([[running %s\start.lua]], addonName) )
+
+-- NOTE: We don't have to check if this module's dependencies
+-- are available: it lists them normally in its .toc file and
+-- the bootstrap module will take care of enabling them first.
+
+-- prepare output functions
+local lp = LibStub("LibPrint-1.0")
+local printStream = lp:NewStream("DependencyLoader", "DepLoader", "DepLdr", print)
+local debugStream = lp:NewStream("DependencyLoader", "DepLoader", "DepLdr", "mcm")
+
+addonTable.print = function(...) printStream:Print(...) end
+addonTable.debug = function(...) debugStream:Print(...) end
+
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Bootstrap/Ace3.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader_Bootstrap/Ace3.xml Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Bootstrap/DependencyLoader.toc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader_Bootstrap/DependencyLoader.toc Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,11 @@
+## Interface: 40000
+
+## Notes: Bootstrap for DependencyLoader_Core
+## Author: mckenziemc
+
+## LoadManagers: !!!LoadFirst, AddonLoader
+## X-LoadFirst: true
+## X-LoadOn-Always: true
+
+
+load.xml
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Bootstrap/bootstrap.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader_Bootstrap/bootstrap.lua Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,36 @@
+-- bootstrap.lua
+-- Bootstrap code for DependencyLoader, allowing
+-- the user to successfully load it without
+-- explicitly enabling its own dependencies.
+
+
+local addonName, addonTable = ...
+
+-- TODO: move and use dependency parsing function here?
+local dependencies = {"LibStub", "LibPrint-1.0", "Ace3"}
+
+local canLoad = true
+for _, addon in pairs(dependencies) do
+ local reason = select(6, GetAddOnInfo(addon))
+
+ if reason ~= nil and reason ~= "DISABLED" then
+ canLoad = false
+ break
+ end
+end
+
+if not canLoad then
+ print("Can't load DependencyLoader")
+ return
+end
+
+
+print("Loading DependencyLoader")
+
+for _, addon in pairs(dependencies) do
+ EnableAddOn(addon)
+end
+
+EnableAddOn("DependencyLoader_Core")
+LoadAddOn("DependencyLoader_Core")
+
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Bootstrap/embeds.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader_Bootstrap/embeds.xml Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Bootstrap/load.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader_Bootstrap/load.xml Sun Dec 05 00:12:57 2010 -0800
@@ -0,0 +1,1 @@
+
\ No newline at end of file
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/Addon.lua
--- a/DependencyLoader_Core/Addon.lua Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,248 +0,0 @@
--- Addon
--- Represents individual addon modules
-
-
-local addonName, addonTable = ...
-
-
--- NOTE: I assume that the API addon functions are
--- slightly quicker with an index than with a number.
-
--- TODO: modify the dependency stuff to use the Errata module if available
-
-local Addon, addon = addonTable:NewClass("Addon")
-
-
--- load ability masks
-Addon.loadMasks = {
- reload = bit.lshift(1, 0), -- can load after reloadui
- ondemand = bit.lshift(1, 1), -- can load on demand
- forceafter = bit.lshift(1, 2), -- force load after it would normally be loaded
- forcebefore = bit.lshift(1, 3), -- force load before it would normally be loaded
-}
-
-
-Addon.addons = {}
-Addon.nameToIndex = {}
-
-
--- Internal function
--- Creates a new Addon object
--- @param id Name or index of the addon.
-function Addon:New(id)
- local instance = {}
- setmetatable(instance, self.instanceMetatable)
-
- if type(id) == "number" then
- -- TODO: make sure it's in range
- instance.index = id
- instance.name = GetAddOnInfo(id)
- else
- -- FIXME: allow blizzard addons?
- local index
-
- for i=1,GetNumAddOns() do
- if GetAddOnInfo(i) == id then
- index = i
- break
- end
- end
-
- if index then
- instance.name = GetAddOnInfo(id)
- instance.index = index
- else
- error("Addon not found")
- end
- end
-
- return instance
-end
-
-
---- Retrieves an Addon object.
--- @param id Name or index of the addon to retrieve.
--- @return The Addon object, or nil if not found.
-function Addon:Get(id)
- if not self:Exists(id) then
- return nil
- end
-
- if type(id) == "number" then
- if self.addons[id] ~= nil then
- return self.addons[id]
- end
-
- local new = self:New(id)
- self.addons[new:GetIndex()] = new
- self.nameToIndex[new:GetName()] = id
-
- return new
- elseif type(id) == "string" then
- if self.nameToIndex[id] then
- return self.addons[self.nameToIndex[id] ]
- end
-
- local new = self:New(id)
- self.addons[new:GetIndex()] = new
- self.nameToIndex[id] = new:GetIndex()
-
- return new
- end
-end
-
--- Checks if an addon exists with the specified name.
--- @param addon Name of the addon.
--- @return True if the addon is present, false otherwise.
-function Addon:Exists(addon)
- if type(addon) == "number" then
- if addon >= 1 and addon <= GetNumAddOns() then
- return true
- else
- return false
- end
- elseif type(addon) == "string" then
- local status = select(6, GetAddOnInfo(addon))
-
- if status == "MISSING" then
- return false
- else
- return true
- end
- else
- error()
- end
-end
-
-
-function Addon:GetLoadMasks()
- return self.masks
-end
-
-
-function addon:GetName()
- return self.name
-end
-
-
-function addon:GetIndex()
- return self.index
-end
-
-
-function addon:IsEnabled()
- -- FIXME: written while tired; review later
- local status = select(6, GetAddOnInfo(self.index))
-
- if status == "DISABLED" then
- return false
- else
- return true
- end
-end
-
-
-function addon:GetLoadBitfield()
- local bitfield = 0
-
- if self:CanLoad() then
- bitfield = bitfield + self.masks.reload
- end
-
- if self:CanLoD() then
- bitfield = bitfield + self.masks.ondemand
- end
-
- if self:CanForceLoadAfter() then
- bitfield = bitfield + self.masks.forceafter
- end
-
- if self:CanForceLoadBefore() then
- bitfield = bitfield + self.masks.forcebefore
- end
-
- return bitfield
-end
-
-
---- Checks if the addon is loadable.
--- Considers interface issues, missing, etc. (NYI)
--- Does not check dependencies.
-function addon:CanLoad()
- -- FIXME: an addon may be present but unloadable if loading out of date addons is disabled.
- return true
-end
-
-
-function addon:CanLoD()
- -- FIXME: what will the client say about addons using LoadManagers if the LM was force-loaded?
- if IsAddOnLoadOnDemand(self.name) then
- return true
- else
- return false
- end
-end
-
-
-function addon:CanForceLoadAfter()
- -- TODO: check Errata module
- return false
-end
-
-
-function addon:CanForceLoadBefore()
- -- TODO: check Errata module
- return false -- TODO: check if there's any reason addons can't be forceloaded
-end
-
-
-function addon:Enable()
- -- FIXME: delay this till after PLAYER_LOGIN or it'll get force-loaded
- EnableAddOn(self.name)
-end
-
-
--- NOTE: only call for LoD, not force-loading
-function addon:Load()
- assert(self:CanLoD())
-
- EnableAddOn(self.name)
- LoadAddOn(self.name)
-end
-
-
-function addon:ForceLoad()
- assert(self:CanForceLoad())
- -- TODO: make sure force-loading is available at this time
-
- EnableAddOn(self.name) -- This should cause the game to also load this addon
-end
-
-
-function addon:GetDependencies()
- -- TODO: consider no-lib embeds as deps?
- return GetAddOnDependencies(self.index)
-end
-
-
-function addon:GetEmbeds()
- local embeds = {}
-
- local embedString = GetAddOnMetadata(self.name, "X-Embeds")
-
- if embedString then
- for match in string.gmatch(embedString, "[^,%s]+") do
- table.insert(embeds, match)
- end
- end
-
- return unpack(embeds)
-end
-
-function addon:IsLoaded()
- if IsAddOnLoaded(self.index) then
- return true
- else
- return false
- end
-end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/Core.lua
--- a/DependencyLoader_Core/Core.lua Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,293 +0,0 @@
-
-
-
-local addonName, addonTable = ...
-
-
-local Core, core = addonTable:NewClass("Core")
-
-
-function Core:New()
- local instance = {}
- setmetatable(instance, self.instanceMetatable)
-
- instance.addons = {}
- instance.nameToIndex = {}
-
- for i=1,GetNumAddOns() do
- local newAddon = Addon:New(i)
-
- instance.addons[i] = newAddon
- instance.nameToIndex[newAddon:GetName()] = i
- end
-
- -- TODO: enable dependencies for any addons that have already loaded
-
- return instance
-end
-
-
--- @param addon Name or index of the addon to retrieve.
--- @return The addon object, or nil if not found
-function core:GetAddon(addon)
- if not Addon:Exists(addon) then
- return nil
- end
-
- local index
-
- if type(addon) == "string" then
- index = self.nameToIndex[addon]
- elseif type(addon) == "number" then
- index = addon
- end
-
- return self.addons[index]
-end
-
-
--- Checks if the tree rooted at the specified addon can be force-loaded.
--- @param root The name or index of the root addon.
-function core:CanForceLoadTree(root)
- -- convert root to an Addon object
- root = self:GetAddon(root)
- assert(root)
-
- if root:IsLoaded() then
- return true
- end
-
- -- check if the root itself can be force-loaded
- if not root:CanForceLoad() then
- return false
- end
-
- -- now check dependencies recursively
- -- FIXME: prevent infinite recursion
-
- local dependencies = {root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- local dep = self:GetAddon(depName)
-
- if dep == nil then
- return false -- missing dependency
- end
-
- -- if it's already loaded then skip to next one
- if not dep:IsLoaded() then
- if not self:CanForceLoadTree(depName) then
- return false
- end
- end
- end
-
- return true
-end
-
--- NOTE: any tree that can be loaded on demand is also eligible for force-loading
--- Checks if the tree rooted at the specified addon can be loaded on demand.
--- @param root The name or index of the root addon.
-function core:CanLoDTree(root)
- root = self:GetAddon(root)
- assert(root)
-
- -- since this will be used recursively, return true if
- -- this is already loaded.
- if root:IsLoaded() then
- return true
- end
-
- -- true if all dependencies are loaded or LoD
-
- if not root:CanLoD() then
- return false
- end
-
- -- now check dependencies recursively
- local dependencies = {root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- local dep = self:GetAddon(depName)
-
- if not dep then
- return false -- missing
- end
-
- if not dep:IsLoaded() then
- if not self:CanLoDTree(depName) then
- return false
- end
- end
- end
-
- return true
-end
-
-
--- Checks if the tree rooted at the specified addon
--- can be loaded if all dependencies are enabled
--- the UI is reloaded.
--- Basically makes sure all dependencies are installed.
-function core:CanReloadTree(root)
- -- convert root to an Addon object
- root = self:GetAddon(root)
- assert(root)
-
- if root:IsLoaded() then
- return true
- -- FIXME: deps may have been disabled
- end
-
- -- TODO: make sure the root isn't incompatible
-
- -- now check dependencies recursively
- -- FIXME: prevent infinite recursion
-
- local dependencies = {root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- local dep = self:GetAddon(depName)
-
- if dep == nil then
- return false -- missing dependency
- end
-
- -- TODO: make sure it's compatible
- end
-
- return true
-end
-
--- Loads the tree rooted at the specified addon.
--- FIXME: load the root too or not?
--- Supports both LoD addons and those that require force-loading.
-function core:LoadTree(addon)
- -- don't check if the tree can actually be loaded.
- -- external code should do that itself to check if it
- -- should even call this at all.
-
- if self:ForceLoadAvailable() then
- -- LoD trees can also be force-loaded
- self:ForceLoadTree(addon)
- else
- self:LoadLoDTree(addon)
- end
-end
-
-
--- load the root too, since it may actually be a leaf
-function core:ForceLoadTree(root)
- root = self:GetAddon(root)
- assert(root)
-
- -- load dependencies
- local dependencies = {root:GetDependencies(addon)}
- for i, depName in pairs(dependencies) do
- self:ForceLoadTree(depName)
- end
-
- -- load embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)}
- for i, embedName in pairs(embeds) do
- if Addon:Exists(embedName) then
- self:ForceLoadTree(embedName)
- end
- end
-
- root:ForceLoad()
-end
-
-
-function core:LoadLoDTree(root)
- root = self:GetAddon(root)
- assert(root)
-
- -- load dependencies
- local dependencies = {root:GetDependencies(addon)}
- for i, depName in pairs(dependencies) do
- self:LoadLoDTree(depName)
- end
-
- -- load embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)}
- for i, embedName in pairs(embeds) do
- if Addon:Exists(embedName) then
- self:LoadLoDTree(embedName)
- end
- end
-
- root:LoD()
-end
-
-
--- I think the problem this solves is a major issue with
--- migrating to separate libs. think about it more and document
--- here and in project description
-function core:PrepareLoDTree(root)
- root = self:GetAddon(root)
- assert(root)
-
- -- assume root is LoD
-
- -- check dependencies
- local dependencies = {root:GetDependencies(addon)}
- for i, depName in pairs(dependencies) do
- local dep = self:GetAddon(depName)
-
- -- assume external code made sure it exists
-
- if dep:CanLoD() then
- -- don't load it now but make sure its dependencies are prepared
- self:PrepareLoDTree(depName)
- else
- -- FIXME: if it's already loaded
- -- force-load it now so we can load the parent on demand
- self:ForceLoadTree(depName)
- end
- end
-
- -- prepare embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)} -- FIXME: addon?
- for i, embedName in pairs(embeds) do
- local embed = self:GetAddon(embedName)
-
- if embed then
- if embed:CanLoD() then
- -- don't load it now but make sure its dependencies are prepared
- self:PrepareLoDTree(embedName)
- else
- -- FIXME: if it's already loaded
- -- force-load it now so we can load the parent on demand
- self:ForceLoadTree(depName)
- end
- end
- end
-end
-
-
-function Core:PrepareReloadTree(addon)
- root = self:GetAddon(root)
- assert(root)
-
- root:Enable()
-
- -- check dependencies
- local dependencies = {root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- self:PrepareReloadTree(depName)
- end
-
- -- prepare embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)}
- for i, embedName in pairs(embeds) do
- local embed = self:GetAddon(embedName)
-
- if embed then
- self:PrepareReloadTree(embedName)
- end
- end
-end
-
-
-function Core:ForceLoadAvailable()
- return true
- -- FIXME: use field and a frame registered for PLAYER_LOGIN
-end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/DependencyLoader_Core.toc
--- a/DependencyLoader_Core/DependencyLoader_Core.toc Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-## Interface: 40000
-
-# TODO: actually explain what DependencyLoader does.
-## Notes: Core module of DependencyLoader
-## Author: mckenziemc
-
-# TODO: figure out some way to allow AddonLoader
-# to work with DependencyLoader
-## Dependencies: DependencyLoader, LibStub, LibPrint-1.0, Ace3
-
-## LoadOnDemand: 1
-
-
-load.xml
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/Tree.lua
--- a/DependencyLoader_Core/Tree.lua Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
--- Tree
--- Represents a recursive "tree" of addon
--- dependencies rooted at a specific addon.
-
-
-local addonName, addonTable = ...
-
-
--- TODO: prevent infinite loops in the recursive functions
-
-
-local Tree, tree = addonTable:NewClass("Tree")
-
-
-Tree.trees = {}
-
--- internal
--- Creates a new tree object
--- @param root Name, index, or Addon object of the root addon.
-function Tree:New(root)
- if type(root) ~= "table" then
- root = addonTable.classes.Addon:Get(root)
- end
-
- local instance = {}
- setmetatable(instance, self.instanceMetatable)
-
- instance.root = root
-
- return instance
-end
-
-
---- Retrieves the tree rooted at the specified addon
--- @param root Name, index, or Addon object of the root.
-function Tree:Get(root)
- if type(root) ~= "table" then
- root = addonTable.classes.Addon:Get(root)
- end
-
- local tree = self.trees[root]
-
- if tree then
- return tree
- else
- tree = self:New(root)
- self.trees[root] = tree
- return tree
- end
-end
-
-
-function tree:GetLoadBitfield()
- local bitfield = self.root:GetLoadBitfield()
-
- local dependencies = {self.root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- local depTree = Tree:Get(depName)
-
- if depTree == nil then
- return 0
- end
-
- bitfield = bit.band(bitfield, depTree:GetLoadBitfield())
- end
-
- return bitfield
-end
-
-
--- Checks if the tree rooted at the specified addon can be force-loaded.
--- @param root The name or index of the root addon.
-function core:CanForceLoadTree(root)
- -- TODO: if some addons have already loaded, we have to check
- -- forceafter for those and forcebefore for the others
- return false
-end
-
-
--- NOTE: any tree that can be loaded on demand is also eligible for force-loading
--- Checks if the tree rooted at the specified addon can be loaded on demand.
--- @param root The name or index of the root addon.
-function core:CanLoDTree(root)
- local bitfield = self:GetLoadBitfield()
- root = self:GetAddon(root)
- assert(root)
-
- -- since this will be used recursively, return true if
- -- this is already loaded.
- if root:IsLoaded() then
- return true
- end
-
- -- true if all dependencies are loaded or LoD
-
- if not root:CanLoD() then
- return false
- end
-
- -- now check dependencies recursively
- local dependencies = {root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- local dep = self:GetAddon(depName)
-
- if not dep then
- return false -- missing
- end
-
- if not dep:IsLoaded() then
- if not self:CanLoDTree(depName) then
- return false
- end
- end
- end
-
- return true
-end
-
-
--- Checks if the tree rooted at the specified addon
--- can be loaded if all dependencies are enabled
--- the UI is reloaded.
--- Basically makes sure all dependencies are installed.
-function core:CanReloadTree(root)
- -- convert root to an Addon object
- root = self:GetAddon(root)
- assert(root)
-
- if root:IsLoaded() then
- return true
- -- FIXME: deps may have been disabled
- end
-
- -- TODO: make sure the root isn't incompatible
-
- -- now check dependencies recursively
- -- FIXME: prevent infinite recursion
-
- local dependencies = {root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- local dep = self:GetAddon(depName)
-
- if dep == nil then
- return false -- missing dependency
- end
-
- -- TODO: make sure it's compatible
- end
-
- return true
-end
-
--- Loads the tree rooted at the specified addon.
--- FIXME: load the root too or not?
--- Supports both LoD addons and those that require force-loading.
-function core:LoadTree(addon)
- -- don't check if the tree can actually be loaded.
- -- external code should do that itself to check if it
- -- should even call this at all.
-
- if self:ForceLoadAvailable() then
- -- LoD trees can also be force-loaded
- self:ForceLoadTree(addon)
- else
- self:LoadLoDTree(addon)
- end
-end
-
-
--- load the root too, since it may actually be a leaf
-function core:ForceLoadTree(root)
- root = self:GetAddon(root)
- assert(root)
-
- -- load dependencies
- local dependencies = {root:GetDependencies(addon)}
- for i, depName in pairs(dependencies) do
- self:ForceLoadTree(depName)
- end
-
- -- load embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)}
- for i, embedName in pairs(embeds) do
- if Addon:Exists(embedName) then
- self:ForceLoadTree(embedName)
- end
- end
-
- root:ForceLoad()
-end
-
-
-function core:LoadLoDTree(root)
- root = self:GetAddon(root)
- assert(root)
-
- -- load dependencies
- local dependencies = {root:GetDependencies(addon)}
- for i, depName in pairs(dependencies) do
- self:LoadLoDTree(depName)
- end
-
- -- load embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)}
- for i, embedName in pairs(embeds) do
- if Addon:Exists(embedName) then
- self:LoadLoDTree(embedName)
- end
- end
-
- root:LoD()
-end
-
-
--- I think the problem this solves is a major issue with
--- migrating to separate libs. think about it more and document
--- here and in project description
-function core:PrepareLoDTree(root)
- root = self:GetAddon(root)
- assert(root)
-
- -- assume root is LoD
-
- -- check dependencies
- local dependencies = {root:GetDependencies(addon)}
- for i, depName in pairs(dependencies) do
- local dep = self:GetAddon(depName)
-
- -- assume external code made sure it exists
-
- if dep:CanLoD() then
- -- don't load it now but make sure its dependencies are prepared
- self:PrepareLoDTree(depName)
- else
- -- FIXME: if it's already loaded
- -- force-load it now so we can load the parent on demand
- self:ForceLoadTree(depName)
- end
- end
-
- -- prepare embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)} -- FIXME: addon?
- for i, embedName in pairs(embeds) do
- local embed = self:GetAddon(embedName)
-
- if embed then
- if embed:CanLoD() then
- -- don't load it now but make sure its dependencies are prepared
- self:PrepareLoDTree(embedName)
- else
- -- FIXME: if it's already loaded
- -- force-load it now so we can load the parent on demand
- self:ForceLoadTree(depName)
- end
- end
- end
-end
-
-
-function Core:PrepareReloadTree(addon)
- root = self:GetAddon(root)
- assert(root)
-
- root:Enable()
-
- -- check dependencies
- local dependencies = {root:GetDependencies()}
- for i, depName in pairs(dependencies) do
- self:PrepareReloadTree(depName)
- end
-
- -- prepare embeds, if they are available separately
- local embeds = {root:GetEmbeds(addon)}
- for i, embedName in pairs(embeds) do
- local embed = self:GetAddon(embedName)
-
- if embed then
- self:PrepareReloadTree(embedName)
- end
- end
-end
-
-
-function Core:ForceLoadAvailable()
- return true
- -- FIXME: use field and a frame registered for PLAYER_LOGIN
-end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/class.lua
--- a/DependencyLoader_Core/class.lua Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
--- class.lua
--- Implements a generic class builder.
-
-
-local addonName, addonTable = ...
-
--- FIXME: prevent duplicate class definitions
-
-print( string.format([[running %s\class.lua]], addonName) )
-
-addonTable.classes = {}
-
-function addonTable:NewClass(name)
- local class, prototype, metatable = {}, {}, {}
-
- class.prototype = prototype
-
- metatable.__index = prototype
- class.instanceMetatable = metatable
-
- self.classes[name] = class
-
- return class, prototype
-end
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/frontend.lua
--- a/DependencyLoader_Core/frontend.lua Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
--- main.lua
---
-
-local addonName, addonTable = ...
-
-
-local DependencyLoader = LibStub("AceAddon-3.0"):NewAddon(addonName)
-_G[addonName] = DependencyLoader
-
-local libPrint = LibStub("LibPrint-1.0")
-DependencyLoader.printStream = libPrint:NewStream("DependencyLoader", "DpLdr", print)
-DependencyLoader.debugStream = libPrint:NewStream("DependencyLoader", "DpLdr", "mcm")
-
--- temp
-DependencyLoader.classes = addonTable.classes
-
-function DependencyLoader:Print(...)
- self.printStream:Print(...)
-end
-
-
-function DependencyLoader:Debug(...)
- self.debugStream:Print(...)
-end
-
-
-function DependencyLoader:OnInitialize()
- self:Debug("Initializing and enabling", addonName)
- self:Enable()
-end
-
-
-function DependencyLoader:OnEnable()
- self.core = addonTable.classes.Core:New()
-
- self:Print("Enabled", addonName)
-
- self:FixCurrentAddons()
-end
-
-function DependencyLoader:OnDisable()
- self:Print("Disabled", addonName)
-end
-
-
--- TODO: move this into core?
-
--- Enables any dependencies needed by the addons
--- that have already been enabled
-function DependencyLoader:FixCurrentAddons()
- local core = self.core
-
- for i=1, GetNumAddOns() do
- local addon = self.core:GetAddon(i)
-
- if addon:IsEnabled() then
- if addon:IsLoaded() then
- -- TODO: it might still help to enable its embeds
- else
- self:Debug("Checking", addon:GetName())
-
- if addonTable.classes.Core:ForceLoadAvailable() then
- if core:CanForceLoadTree(addon:GetName()) then
- core:ForceLoadTree(addon:GetName())
- else
- print("Can't force load", addon:GetName())
- end
- else
- if core:CanLoDTree(addon:GetName()) then
- core:PrepareLoDTree(addon:GetName())
- else
- print("Couldn't load", addon:GetName(), "on demand.")
- end
- end
- end
- end
- end
-end
-
-
-
-
-
\ No newline at end of file
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/load.xml
--- a/DependencyLoader_Core/load.xml Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
\ No newline at end of file
diff -r 930871e163bc -r 5362e308c3eb DependencyLoader_Core/start.lua
--- a/DependencyLoader_Core/start.lua Sat Dec 04 23:05:34 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
--- start.lua
--- Initializes components of DependencyLoader
-
-
-local addonName, addonTable = ...
-
-
-print( string.format([[running %s\start.lua]], addonName) )
-
--- NOTE: We don't have to check if this module's dependencies
--- are available: it lists them normally in its .toc file and
--- the bootstrap module will take care of enabling them first.
-
--- prepare output functions
-local lp = LibStub("LibPrint-1.0")
-local printStream = lp:NewStream("DependencyLoader", "DepLoader", "DepLdr", print)
-local debugStream = lp:NewStream("DependencyLoader", "DepLoader", "DepLdr", "mcm")
-
-addonTable.print = function(...) printStream:Print(...) end
-addonTable.debug = function(...) debugStream:Print(...) end
-