mirror of
https://github.com/kepler155c/opus
synced 2024-12-29 01:50:27 +00:00
pure lua compatiblity fixes for moonlight, busted, etc
This commit is contained in:
parent
039fa73749
commit
e9580d67eb
25
sys/apps/compat.lua
Normal file
25
sys/apps/compat.lua
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
local Util = require('opus.util')
|
||||||
|
|
||||||
|
-- some programs expect to be run in the global scope
|
||||||
|
-- ie. busted, moonscript
|
||||||
|
|
||||||
|
-- create a new sandbox mimicing pure lua
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
|
local shell = _ENV.shell
|
||||||
|
|
||||||
|
local env = Util.shallowCopy(_G)
|
||||||
|
Util.merge(env, _ENV)
|
||||||
|
env._G = env
|
||||||
|
|
||||||
|
env.arg = { ... }
|
||||||
|
env.arg[0] = shell.resolveProgram(table.remove(env.arg, 1))
|
||||||
|
|
||||||
|
_G.requireInjector(env, fs.getDir(env.arg[0]))
|
||||||
|
|
||||||
|
local s, m = Util.run(env, env.arg[0], table.unpack(env.arg))
|
||||||
|
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
|
|
@ -6,7 +6,7 @@ local fs = _G.fs
|
|||||||
local settings = _G.settings
|
local settings = _G.settings
|
||||||
local shell = _ENV.shell
|
local shell = _ENV.shell
|
||||||
|
|
||||||
_G.requireInjector(_ENV)
|
--_G.requireInjector(_ENV)
|
||||||
|
|
||||||
local trace = require('opus.trace')
|
local trace = require('opus.trace')
|
||||||
local Util = require('opus.util')
|
local Util = require('opus.util')
|
||||||
@ -43,6 +43,11 @@ local function run(...)
|
|||||||
local isUrl = not not command:match("^(https?:)")
|
local isUrl = not not command:match("^(https?:)")
|
||||||
local env = shell.makeEnv(_ENV)
|
local env = shell.makeEnv(_ENV)
|
||||||
|
|
||||||
|
if command:match('(.+)%.moon$') then
|
||||||
|
table.insert(args, 1, command)
|
||||||
|
command = 'moon'
|
||||||
|
end
|
||||||
|
|
||||||
local path, loadFn
|
local path, loadFn
|
||||||
if isUrl then
|
if isUrl then
|
||||||
path = command
|
path = command
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
local fs = _G.fs
|
local fs = _G.fs
|
||||||
|
|
||||||
|
-- override bios function to use the global scope of the current env
|
||||||
|
function _G.loadstring(string, chunkname)
|
||||||
|
return load(string, chunkname, nil, getfenv(2)._G)
|
||||||
|
end
|
||||||
|
|
||||||
-- override bios function to include the actual filename
|
-- override bios function to include the actual filename
|
||||||
function _G.loadfile(filename, mode, env)
|
function _G.loadfile(filename, mode, env)
|
||||||
-- Support the previous `loadfile(filename, env)` form instead.
|
-- Support the previous `loadfile(filename, env)` form instead.
|
||||||
@ -20,12 +25,17 @@ for k,v in pairs(_ENV) do
|
|||||||
sandboxEnv[k] = v
|
sandboxEnv[k] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Install require shim
|
||||||
|
_G.requireInjector = loadfile('sys/modules/opus/injector.lua', _ENV)()
|
||||||
|
|
||||||
local function run(file, ...)
|
local function run(file, ...)
|
||||||
local env = setmetatable({ }, { __index = _G })
|
local env = setmetatable({ }, { __index = _G })
|
||||||
for k,v in pairs(sandboxEnv) do
|
for k,v in pairs(sandboxEnv) do
|
||||||
env[k] = v
|
env[k] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
_G.requireInjector(env)
|
||||||
|
|
||||||
local s, m = loadfile(file, env)
|
local s, m = loadfile(file, env)
|
||||||
if s then
|
if s then
|
||||||
return s(...)
|
return s(...)
|
||||||
@ -36,9 +46,6 @@ end
|
|||||||
_G._syslog = function() end
|
_G._syslog = function() end
|
||||||
_G.OPUS_BRANCH = 'develop-1.8'
|
_G.OPUS_BRANCH = 'develop-1.8'
|
||||||
|
|
||||||
-- Install require shim
|
|
||||||
_G.requireInjector = run('sys/modules/opus/injector.lua')
|
|
||||||
|
|
||||||
local s, m = pcall(run, 'sys/apps/shell.lua', 'sys/kernel.lua', ...)
|
local s, m = pcall(run, 'sys/apps/shell.lua', 'sys/kernel.lua', ...)
|
||||||
|
|
||||||
if not s then
|
if not s then
|
||||||
|
@ -83,6 +83,18 @@ function nativefs.isDir(node, dir)
|
|||||||
return fs.native.isDir(dir)
|
return fs.native.isDir(dir)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function nativefs.attributes(node, path)
|
||||||
|
if node.mountPoint == path then
|
||||||
|
return {
|
||||||
|
created = node.created or os.epoch('utc'),
|
||||||
|
modification = node.modification or os.epoch('utc'),
|
||||||
|
isDir = not not node.nodes,
|
||||||
|
size = node.size or 0,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return fs.native.attributes(path)
|
||||||
|
end
|
||||||
|
|
||||||
function nativefs.exists(node, dir)
|
function nativefs.exists(node, dir)
|
||||||
if node.mountPoint == dir then
|
if node.mountPoint == dir then
|
||||||
return true
|
return true
|
||||||
@ -307,12 +319,16 @@ function fs.mount(path, fstype, ...)
|
|||||||
tp.nodes[d] = Util.shallowCopy(tp)
|
tp.nodes[d] = Util.shallowCopy(tp)
|
||||||
tp.nodes[d].nodes = { }
|
tp.nodes[d].nodes = { }
|
||||||
tp.nodes[d].mountPoint = fs.combine(tp.mountPoint, d)
|
tp.nodes[d].mountPoint = fs.combine(tp.mountPoint, d)
|
||||||
|
tp.nodes[d].created = os.epoch('utc')
|
||||||
|
tp.nodes[d].modification = os.epoch('utc')
|
||||||
end
|
end
|
||||||
tp = tp.nodes[d]
|
tp = tp.nodes[d]
|
||||||
end
|
end
|
||||||
|
|
||||||
node.fs = vfs
|
node.fs = vfs
|
||||||
node.fstype = fstype
|
node.fstype = fstype
|
||||||
|
node.created = node.created or os.epoch('utc')
|
||||||
|
node.modification = node.modification or os.epoch('utc')
|
||||||
if not targetName then
|
if not targetName then
|
||||||
node.mountPoint = ''
|
node.mountPoint = ''
|
||||||
fs.nodes = node
|
fs.nodes = node
|
||||||
|
@ -20,7 +20,7 @@ local w, h = term.getSize()
|
|||||||
kernel.terminal = term.current()
|
kernel.terminal = term.current()
|
||||||
|
|
||||||
kernel.window = Terminal.window(kernel.terminal, 1, 1, w, h, false)
|
kernel.window = Terminal.window(kernel.terminal, 1, 1, w, h, false)
|
||||||
kernel.window.setMaxScroll(100)
|
kernel.window.setMaxScroll(200)
|
||||||
|
|
||||||
local focusedRoutineEvents = Util.transpose {
|
local focusedRoutineEvents = Util.transpose {
|
||||||
'char', 'key', 'key_up',
|
'char', 'key', 'key_up',
|
||||||
|
@ -20,8 +20,8 @@ function urlfs.mount(path, url, force)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function urlfs.attributes(node)
|
function urlfs.attributes(node, path)
|
||||||
return {
|
return path == node.mountPoint and {
|
||||||
created = node.created,
|
created = node.created,
|
||||||
isDir = false,
|
isDir = false,
|
||||||
modification = node.modification,
|
modification = node.modification,
|
||||||
@ -29,16 +29,18 @@ function urlfs.attributes(node)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function urlfs.delete(_, dir)
|
function urlfs.delete(node, path)
|
||||||
fs.unmount(dir)
|
if path == node.mountPoint then
|
||||||
|
fs.unmount(path)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function urlfs.exists()
|
function urlfs.exists(node, path)
|
||||||
return true
|
return path == node.mountPoint
|
||||||
end
|
end
|
||||||
|
|
||||||
function urlfs.getSize(node)
|
function urlfs.getSize(node, path)
|
||||||
return node.size or 0
|
return path == node.mountPoint and node.size or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function urlfs.isReadOnly()
|
function urlfs.isReadOnly()
|
||||||
@ -65,14 +67,6 @@ function urlfs.open(node, fn, fl)
|
|||||||
|
|
||||||
local c = node.cache
|
local c = node.cache
|
||||||
if not c then
|
if not c then
|
||||||
--[[
|
|
||||||
if node.url:match("^(rttps?:)") then
|
|
||||||
local s, response = rttp.get(node.url)
|
|
||||||
c = s and response.statusCode == 200 and response.data
|
|
||||||
else
|
|
||||||
c = Util.httpGet(node.url)
|
|
||||||
end
|
|
||||||
]]--
|
|
||||||
c = Util.httpGet(node.url)
|
c = Util.httpGet(node.url)
|
||||||
if c then
|
if c then
|
||||||
node.cache = c
|
node.cache = c
|
||||||
|
@ -1,73 +1,69 @@
|
|||||||
-- https://www.lua.org/manual/5.1/manual.html#pdf-require
|
-- https://www.lua.org/manual/5.1/manual.html#pdf-require
|
||||||
|
-- https://github.com/LuaDist/lua/blob/d2e7e7d4d43ff9068b279a617c5b2ca2c2771676/src/loadlib.c
|
||||||
|
|
||||||
local function split(str, pattern)
|
local defaultPath = { }
|
||||||
local t = { }
|
|
||||||
local function helper(line) table.insert(t, line) return "" end
|
|
||||||
helper((str:gsub(pattern, helper)))
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
local hasMain
|
do
|
||||||
local luaPaths = package and package.path and split(package.path, '(.-);') or { }
|
local function split(str)
|
||||||
for i = 1, #luaPaths do
|
local t = { }
|
||||||
if luaPaths[i] == '?' or luaPaths[i] == '?.lua' or luaPaths[i] == '?/init.lua' then
|
local function helper(line) table.insert(t, line) return "" end
|
||||||
luaPaths[i] = nil
|
helper((str:gsub('(.-);', helper)))
|
||||||
elseif string.find(luaPaths[i], '/rom/modules/main') then
|
return t
|
||||||
hasMain = true
|
end
|
||||||
|
|
||||||
|
local function insert(p)
|
||||||
|
for _,v in pairs(defaultPath) do
|
||||||
|
if v == p then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(defaultPath, p)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local paths = '?.lua;?/init.lua;'
|
||||||
|
paths = paths .. '/usr/modules/?.lua;/usr/modules/?/init.lua;'
|
||||||
|
paths = paths .. '/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua;'
|
||||||
|
paths = paths .. '/sys/modules/?.lua;/sys/modules/?/init.lua'
|
||||||
|
|
||||||
|
for _,v in pairs(split(paths)) do
|
||||||
|
insert(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
local luaPaths = package and package.path and split(package.path) or { }
|
||||||
|
for _,v in pairs(luaPaths) do
|
||||||
|
if v ~= '?' then
|
||||||
|
insert(v)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(luaPaths, 1, '?.lua')
|
local DEFAULT_PATH = table.concat(defaultPath, ';')
|
||||||
table.insert(luaPaths, 2, '?/init.lua')
|
|
||||||
table.insert(luaPaths, 3, '/usr/modules/?.lua')
|
|
||||||
table.insert(luaPaths, 4, '/usr/modules/?/init.lua')
|
|
||||||
if not hasMain then
|
|
||||||
table.insert(luaPaths, 5, '/rom/modules/main/?')
|
|
||||||
table.insert(luaPaths, 6, '/rom/modules/main/?.lua')
|
|
||||||
table.insert(luaPaths, 7, '/rom/modules/main/?/init.lua')
|
|
||||||
end
|
|
||||||
table.insert(luaPaths, '/sys/modules/?.lua')
|
|
||||||
table.insert(luaPaths, '/sys/modules/?/init.lua')
|
|
||||||
|
|
||||||
local DEFAULT_PATH = table.concat(luaPaths, ';')
|
|
||||||
|
|
||||||
local fs = _G.fs
|
local fs = _G.fs
|
||||||
local os = _G.os
|
local os = _G.os
|
||||||
local string = _G.string
|
local string = _G.string
|
||||||
|
|
||||||
-- Add require and package to the environment
|
-- Add require and package to the environment
|
||||||
return function(env)
|
return function(env, programDir)
|
||||||
local function preloadSearcher(modname)
|
local function preloadSearcher(modname)
|
||||||
if env.package.preload[modname] then
|
if env.package.preload[modname] then
|
||||||
return function()
|
return function()
|
||||||
return env.package.preload[modname](modname, env)
|
return env.package.preload[modname](modname, env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--end
|
|
||||||
|
|
||||||
--local function loadedSearcher(modname)
|
|
||||||
if env.package.loaded[modname] then
|
|
||||||
return function()
|
|
||||||
return env.package.loaded[modname]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local sentinel = { }
|
|
||||||
|
|
||||||
local function pathSearcher(modname)
|
local function pathSearcher(modname)
|
||||||
if env.package.loaded[modname] == sentinel then
|
|
||||||
error("loop or previous error loading module '" .. modname .. "'", 0)
|
|
||||||
end
|
|
||||||
env.package.loaded[modname] = sentinel
|
|
||||||
|
|
||||||
local fname = modname:gsub('%.', '/')
|
local fname = modname:gsub('%.', '/')
|
||||||
|
|
||||||
for pattern in string.gmatch(env.package.path, "[^;]+") do
|
for pattern in string.gmatch(env.package.path, "[^;]+") do
|
||||||
local sPath = string.gsub(pattern, "%?", fname)
|
local sPath = string.gsub(pattern, "%?", fname)
|
||||||
-- TODO: if there's no shell, we should not be checking relative paths below
|
-- TODO: if there's no shell, we should not be checking relative paths below
|
||||||
-- as they will resolve to root directory
|
-- as they will resolve to root directory
|
||||||
if env.shell
|
if programDir and sPath:sub(1, 1) ~= "/" then
|
||||||
|
sPath = fs.combine(programDir, sPath)
|
||||||
|
elseif env.shell
|
||||||
and type(env.shell.getRunningProgram) == 'function'
|
and type(env.shell.getRunningProgram) == 'function'
|
||||||
and sPath:sub(1, 1) ~= "/" then
|
and sPath:sub(1, 1) ~= "/" then
|
||||||
|
|
||||||
@ -81,38 +77,58 @@ return function(env)
|
|||||||
|
|
||||||
-- place package and require function into env
|
-- place package and require function into env
|
||||||
env.package = {
|
env.package = {
|
||||||
path = env.LUA_PATH or _G.LUA_PATH or DEFAULT_PATH,
|
path = env.LUA_PATH or _G.LUA_PATH or DEFAULT_PATH,
|
||||||
config = '/\n:\n?\n!\n-',
|
cpath = '',
|
||||||
|
config = '/\n:\n?\n!\n-',
|
||||||
preload = { },
|
preload = { },
|
||||||
loaded = {
|
loaded = {
|
||||||
|
bit32 = bit32,
|
||||||
coroutine = coroutine,
|
coroutine = coroutine,
|
||||||
|
_G = env._G,
|
||||||
io = io,
|
io = io,
|
||||||
math = math,
|
math = math,
|
||||||
os = os,
|
os = os,
|
||||||
string = string,
|
string = string,
|
||||||
table = table,
|
table = table,
|
||||||
debug = debug,
|
debug = debug,
|
||||||
|
utf8 = utf8,
|
||||||
},
|
},
|
||||||
loaders = {
|
loaders = {
|
||||||
preloadSearcher,
|
preloadSearcher,
|
||||||
--loadedSearcher,
|
|
||||||
pathSearcher,
|
pathSearcher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
env.package.loaded.package = env.package
|
||||||
|
|
||||||
|
local sentinel = { }
|
||||||
|
|
||||||
function env.require(modname)
|
function env.require(modname)
|
||||||
|
if env.package.loaded[modname] then
|
||||||
|
if env.package.loaded[modname] == sentinel then
|
||||||
|
error("loop or previous error loading module '" .. modname .. "'", 0)
|
||||||
|
end
|
||||||
|
return env.package.loaded[modname]
|
||||||
|
end
|
||||||
|
|
||||||
|
local t = { }
|
||||||
for _,searcher in ipairs(env.package.loaders) do
|
for _,searcher in ipairs(env.package.loaders) do
|
||||||
local fn, msg = searcher(modname)
|
local fn, msg = searcher(modname)
|
||||||
if fn then
|
if type(fn) == 'function' then
|
||||||
|
env.package.loaded[modname] = sentinel
|
||||||
|
|
||||||
local module = fn(modname, env) or true
|
local module = fn(modname, env) or true
|
||||||
|
|
||||||
env.package.loaded[modname] = module
|
env.package.loaded[modname] = module
|
||||||
return module
|
return module
|
||||||
end
|
end
|
||||||
if msg then
|
if msg then
|
||||||
error(msg, 2)
|
table.insert(t, msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if #t > 0 then
|
||||||
|
error(table.concat(t, '\n'), 2)
|
||||||
|
end
|
||||||
error('Unable to find module ' .. modname, 2)
|
error('Unable to find module ' .. modname, 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -596,7 +596,6 @@ function Util.loadUrl(url, env) -- loadfile equivalent
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Util.runUrl(env, url, ...) -- os.run equivalent
|
function Util.runUrl(env, url, ...) -- os.run equivalent
|
||||||
setmetatable(env, { __index = _G })
|
|
||||||
local fn, m = Util.loadUrl(url, env)
|
local fn, m = Util.loadUrl(url, env)
|
||||||
if fn then
|
if fn then
|
||||||
return pcall(fn, ...)
|
return pcall(fn, ...)
|
||||||
@ -606,7 +605,6 @@ end
|
|||||||
|
|
||||||
function Util.run(env, path, ...)
|
function Util.run(env, path, ...)
|
||||||
if type(env) ~= 'table' then error('Util.run: env must be a table', 2) end
|
if type(env) ~= 'table' then error('Util.run: env must be a table', 2) end
|
||||||
setmetatable(env, { __index = _G })
|
|
||||||
local fn, m = loadfile(path, env)
|
local fn, m = loadfile(path, env)
|
||||||
if fn then
|
if fn then
|
||||||
return pcall(fn, ...)
|
return pcall(fn, ...)
|
||||||
@ -616,7 +614,6 @@ end
|
|||||||
|
|
||||||
function Util.runFunction(env, fn, ...)
|
function Util.runFunction(env, fn, ...)
|
||||||
setfenv(fn, env)
|
setfenv(fn, env)
|
||||||
setmetatable(env, { __index = _G })
|
|
||||||
return pcall(fn, ...)
|
return pcall(fn, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user