Added error handling to lume.hotswap()

Changed lume.hotswap() to return an error and restore the global
environment if an error occurs when requiring the new package
This commit is contained in:
rxi
2014-03-02 17:13:18 +00:00
parent b3773ee57d
commit 3324bb013c
2 changed files with 26 additions and 16 deletions

View File

@@ -5,8 +5,8 @@ A collection of functions for Lua, geared towards game development.
## Installation ## Installation
The [lume.lua](lume.lua?raw=1) file should be dropped into an existing project and The [lume.lua](lume.lua?raw=1) file should be dropped into an existing project
required by it: and required by it:
```lua ```lua
lume = require "lume" lume = require "lume"
@@ -205,12 +205,14 @@ lume.dostring("print('Hello!')") -- Prints "Hello!"
``` ```
### lume.hotswap(modname) ### lume.hotswap(modname)
Reloads an already loaded module in place; `modname` should be the same string Reloads an already loaded module in place, allowing you to immediatly see the
used when loading the module with require(). This function can be used to effects of code changes without having to restart the program. `modname` should
immediatly see the effects of code changes without having to restart the be the same string used when loading the module with require(). In the case of
program. an error the global environment is restored and `nil` plus an error message is
returned.
```lua ```lua
lume.hotswap("lume") -- Reloads the lume module lume.hotswap("lume") -- Reloads the lume module
assert(lume.hotswap("inexistant_module")) -- Raises an error
``` ```
### lume.rgba(color) ### lume.rgba(color)

View File

@@ -229,6 +229,7 @@ end
function lume.hotswap(modname) function lume.hotswap(modname)
local oldglobal = lume.clone(_G)
local updated = {} local updated = {}
local function update(old, new) local function update(old, new)
if updated[old] then return end if updated[old] then return end
@@ -239,18 +240,25 @@ function lume.hotswap(modname)
if type(v) == "table" then update(old[k], v) else old[k] = v end if type(v) == "table" then update(old[k], v) else old[k] = v end
end end
end end
local oldglobal = lume.clone(_G)
local oldmod = require(modname) local oldmod = require(modname)
package.loaded[modname] = nil local err = nil
local newmod = require(modname) local function onerror(e)
package.loaded[modname] = oldmod for k, v in pairs(_G) do _G[k] = oldglobal[k] end
if type(oldmod) == "table" then update(oldmod, newmod) end err = lume.trim(e)
for k, v in pairs(oldglobal) do
if v ~= _G[k] and type(v) == "table" then
update(v, _G[k])
_G[k] = v
end
end end
xpcall(function()
package.loaded[modname] = nil
local newmod = require(modname)
if type(oldmod) == "table" then update(oldmod, newmod) end
for k, v in pairs(oldglobal) do
if v ~= _G[k] and type(v) == "table" then
update(v, _G[k])
_G[k] = v
end
end
end, onerror)
package.loaded[modname] = oldmod
if err then return nil, err end
return oldmod return oldmod
end end