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,11 +240,15 @@ 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)
local err = nil
local function onerror(e)
for k, v in pairs(_G) do _G[k] = oldglobal[k] end
err = lume.trim(e)
end
xpcall(function()
package.loaded[modname] = nil package.loaded[modname] = nil
local newmod = require(modname) local newmod = require(modname)
package.loaded[modname] = oldmod
if type(oldmod) == "table" then update(oldmod, newmod) end if type(oldmod) == "table" then update(oldmod, newmod) end
for k, v in pairs(oldglobal) do for k, v in pairs(oldglobal) do
if v ~= _G[k] and type(v) == "table" then if v ~= _G[k] and type(v) == "table" then
@ -251,6 +256,9 @@ function lume.hotswap(modname)
_G[k] = v _G[k] = v
end end
end end
end, onerror)
package.loaded[modname] = oldmod
if err then return nil, err end
return oldmod return oldmod
end end