diff --git a/commands/update.lua b/commands/update.lua index 90a126a..3a6944f 100644 --- a/commands/update.lua +++ b/commands/update.lua @@ -1,3 +1,4 @@ + return function () local log = require('log').log local core = require('core')() @@ -20,6 +21,13 @@ return function () return body end + local isWindows + if _G.jit then + isWindows = _G.jit.os == "Windows" + else + isWindows = not not package.path:match("\\") + end + -- Returns current version, latest version and latest compat version. local function checkUpdate() -- Read the current lit version @@ -63,7 +71,7 @@ return function () local stdout = exec(target, "-v") if not stdout:match("^lit version:") then target = pathJoin(target, "..", "lit") - if jit.os == "Windows" then + if isWindows then target = target .. ".exe" end end @@ -107,7 +115,7 @@ return function () do local luvitPath = pathJoin(uv.exepath(), "..", "luvit") - if jit.os == "Windows" then + if isWindows then luvitPath = luvitPath .. ".exe" end if uv.fs_stat(luvitPath) then @@ -123,14 +131,14 @@ return function () do local target = pathJoin(uv.exepath(), "..", "luvi") - if jit.os == "Windows" then + if isWindows then target = target .. ".exe" end local new, old local toupdate = require('luvi').version if uv.fs_stat(target) then local stdout = exec(target, "-v") - if jit.os == "Windows" then + if isWindows then stdout = stdout:gsub("luvi.exe ","luvi ") end local version = stdout:match("luvi (v[^ \r\n]+)") diff --git a/deps/coro-channel.lua b/deps/coro-channel.lua index 647b539..13efa2d 100644 --- a/deps/coro-channel.lua +++ b/deps/coro-channel.lua @@ -1,6 +1,6 @@ --[[lit-meta name = "luvit/coro-channel" - version = "3.0.4" + version = "3.0.5" homepage = "https://github.com/luvit/lit/blob/master/deps/coro-channel.lua" description = "An adapter for wrapping uv streams as coro-streams." tags = {"coro", "adapter"} @@ -8,7 +8,7 @@ author = { name = "Tim Caswell" } ]] --- local p = require('pretty-print').prettyPrint +local unpack = unpack or table.unpack local function assertResume(thread, ...) local success, err = coroutine.resume(thread, ...) diff --git a/deps/coro-http.lua b/deps/coro-http.lua index 454dda0..b4cd785 100644 --- a/deps/coro-http.lua +++ b/deps/coro-http.lua @@ -1,6 +1,6 @@ --[[lit-meta name = "luvit/coro-http" - version = "3.2.3" + version = "3.2.4" dependencies = { "luvit/coro-net@3.3.0", "luvit/http-codec@3.0.0" @@ -14,6 +14,7 @@ local httpCodec = require('http-codec') local net = require('coro-net') +local unpack = unpack or table.unpack local function createServer(host, port, onConnect) return net.createServer({ diff --git a/deps/coro-split.lua b/deps/coro-split.lua index 0c6058c..61c69b4 100644 --- a/deps/coro-split.lua +++ b/deps/coro-split.lua @@ -1,6 +1,6 @@ --[[lit-meta name = "luvit/coro-split" - version = "2.0.2" + version = "2.0.3" homepage = "https://github.com/luvit/lit/blob/master/deps/coro-split.lua" description = "An coro style helper for running tasks concurrently." tags = {"coro", "split"} @@ -11,6 +11,7 @@ -- Split takes several functions as input and runs them in concurrent coroutines. -- The split function will itself block and wait for all three to finish. -- The results of the functions will be returned from split. +local unpack = unpack or table.unpack local function assertResume(thread, ...) local success, err = coroutine.resume(thread, ...) diff --git a/deps/http-codec.lua b/deps/http-codec.lua index cb3a181..a1bb061 100644 --- a/deps/http-codec.lua +++ b/deps/http-codec.lua @@ -18,7 +18,7 @@ limitations under the License. --[[lit-meta name = "luvit/http-codec" - version = "3.0.7" + version = "3.0.8" homepage = "https://github.com/luvit/luvit/blob/master/deps/http-codec.lua" description = "A simple pair of functions for converting between hex and raw strings." tags = {"codec", "http"} @@ -33,6 +33,7 @@ local find = string.find local format = string.format local concat = table.concat local match = string.match +local unpack = unpack or table.unpack local STATUS_CODES = { [100] = 'Continue', diff --git a/deps/readline.lua b/deps/readline.lua index 3061fe9..b11c64c 100644 --- a/deps/readline.lua +++ b/deps/readline.lua @@ -17,7 +17,7 @@ limitations under the License. --]] --[[lit-meta name = "luvit/readline" - version = "2.2.0" + version = "2.2.1" dependencies = { "luvit/ustring@2.0.0", } @@ -29,6 +29,7 @@ limitations under the License. ]] -- Heavily inspired by ljlinenoise : +local unpack = unpack or table.unpack local ustring = require "ustring" local emptyline = ustring.new() diff --git a/deps/weblit-auto-headers.lua b/deps/weblit-auto-headers.lua index d62899d..56030b7 100644 --- a/deps/weblit-auto-headers.lua +++ b/deps/weblit-auto-headers.lua @@ -28,6 +28,7 @@ Response automatic values: ]] local date = require('os').date +local unpack = unpack or table.unpack local success, parent = pcall(require, '../package') local serverName = success and (parent.name .. " v" .. parent.version) diff --git a/deps/weblit-server.lua b/deps/weblit-server.lua index 6a07895..47d28eb 100644 --- a/deps/weblit-server.lua +++ b/deps/weblit-server.lua @@ -15,6 +15,7 @@ local uv = require('uv') local createServer = require('coro-net').createServer local httpCodec = require('http-codec') +local unpack = unpack or table.unpack -- Provide a nice case insensitive interface to headers. local headerMeta = {} diff --git a/deps/websocket-codec.lua b/deps/websocket-codec.lua index 6a2c492..6348f8c 100644 --- a/deps/websocket-codec.lua +++ b/deps/websocket-codec.lua @@ -1,7 +1,7 @@ --[[lit-meta name = "luvit/websocket-codec" description = "A codec implementing websocket framing and helpers for handshakeing" - version = "3.0.2" + version = "3.0.3" dependencies = { "luvit/base64@2.0.0", "luvit/sha1@1.0.0", @@ -30,6 +30,7 @@ local gsub = string.gsub local concat = table.concat local floor = math.floor local random = math.random +local unpack = unpack or table.unpack local function rand4() -- Generate 32 bits of pseudo random data diff --git a/libs/api.lua b/libs/api.lua index 938ac11..03736e9 100644 --- a/libs/api.lua +++ b/libs/api.lua @@ -84,6 +84,7 @@ local ffi = require('ffi') local fs = require('coro-fs') local metrics = require('metrics') local uv = require('uv') +local unpack = unpack or table.unpack local function hex_to_char(x) return string.char(tonumber(x, 16)) @@ -173,19 +174,15 @@ local function collectStats() return entries end - local howToDetermineFDs = { - Linux = function() return countFDs("/proc/self/fd") end, - OSX = function() return countFDs("/dev/fd") end, - Other = function() return -1 end - } - - local os = ffi.os - if howToDetermineFDs[os] == nil then - os = "Other" + local numFDs = -1 + if fs.exists("/proc/self/fd") then + numFDs = countFDs("/proc/self/fd") + elseif fs.exists("/dev/fd") then + numFDs = countFDs("/dev/fd") end metrics.set("lua.mem.used", memoryUsed) - metrics.set("lua.fds.used", howToDetermineFDs[os]()) + metrics.set("lua.fds.used", numFDs) return metrics.all() end diff --git a/libs/autoconfig.lua b/libs/autoconfig.lua index e4be0db..69aad64 100644 --- a/libs/autoconfig.lua +++ b/libs/autoconfig.lua @@ -21,7 +21,7 @@ local fs = require('coro-fs') local env = require('env') local prefix -if require('ffi').os == "Windows" then +if package.config:sub(1,1) == '\\' and env.get('APPDATA') then prefix = env.get("APPDATA") .. "\\" else prefix = env.get("HOME") .. "/." diff --git a/libs/core.lua b/libs/core.lua index 7fecd12..73ccba1 100644 --- a/libs/core.lua +++ b/libs/core.lua @@ -54,6 +54,7 @@ local exportZip = require('export-zip') local digest = require('openssl').digest.digest local request = require('coro-http').request local makeAutoConfig = require('autoconfig') +local unpack = unpack or table.unpack local quotepattern = '(['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..'])' local function escape(str) @@ -69,6 +70,13 @@ local function run(...) end end +local isWindows +if _G.jit then + isWindows = _G.jit.os == "Windows" +else + isWindows = not not package.path:match("\\") +end + -- Takes a time struct with a date and time in UTC and converts it into -- seconds since Unix epoch (0:00 1 Jan 1970 UTC). -- Trickier than you'd think because os.time assumes the struct is in local time. @@ -181,11 +189,16 @@ local function makeCore(config) local version = semver.normalize(meta and meta.version or luvi.version) local template = meta and meta.url or defaultTemplate local arch - if jit.os == "Windows" then - if jit.arch == "x64" then + if isWindows then + local info = uv.os_uname() + if info.machine == 'amd64' then arch = "Windows-amd64.exe" else - arch = "Windows-ia32.exe" + if semver.gte(version, '2.15.0') then + arch = "Windows-x86.exe" -- the new name scheme + else + arch = "Windows-ia32.exe" + end end else arch = run("uname", "-s") .. "_" .. run("uname", "-m") @@ -202,7 +215,7 @@ local function makeCore(config) if template == defaultTemplate and flavor == "regular" and version == semver.normalize(luvi.version) then local exe = uv.exepath() local stdout = exec(exe, "-v") - if jit.os == "Windows" then + if isWindows then stdout = stdout:gsub('.exe','') end local iversion = stdout:match("luvi version: v(%d+%.%d+%.%d+)") @@ -367,7 +380,7 @@ local function makeCore(config) end local function makeZip(rootHash, target, luvi_source) - if jit.os == "Windows" and (not target:match('%.exe$')) then + if isWindows and (not target:match('%.exe$')) then target = target..'.exe' end @@ -401,7 +414,7 @@ local function makeCore(config) local function defaultTarget(meta) local target = meta.target or meta.name:match("[^/]+$") - if jit.os == "Windows" then + if isWindows then target = target .. ".exe" end return target diff --git a/libs/db-fs.lua b/libs/db-fs.lua index a7fd9cf..a3214be 100644 --- a/libs/db-fs.lua +++ b/libs/db-fs.lua @@ -20,6 +20,7 @@ local git = require('git') local listToMap = git.listToMap local modeToType = git.modes.toType local modes = git.modes +local unpack = unpack or table.unpack return function (db, root) local cache = {} diff --git a/libs/export-zip.lua b/libs/export-zip.lua index 4ab20eb..a9cbb18 100644 --- a/libs/export-zip.lua +++ b/libs/export-zip.lua @@ -19,6 +19,7 @@ limitations under the License. local miniz = require('miniz') local modes = require('git').modes local log = require('log').log +local loadstring = loadstring or load -- Create a zip from a hash optionally compiling lua files to bytecode. return function (db, rootHash, compileLua) diff --git a/libs/handlers.lua b/libs/handlers.lua index bae87a3..eaa7569 100644 --- a/libs/handlers.lua +++ b/libs/handlers.lua @@ -22,6 +22,7 @@ local digest = require('openssl').digest.digest local githubQuery = require('github-request') local jsonParse = require('json').parse local verifySignature = require('verify-signature') +local unpack = unpack or table.unpack local function split(line) local args = {} diff --git a/libs/import.lua b/libs/import.lua index db61742..cb80101 100644 --- a/libs/import.lua +++ b/libs/import.lua @@ -20,6 +20,7 @@ local pathJoin = require('luvi').path.join local isAllowed = require('rules').isAllowed local compileFilter = require('rules').compileFilter local modes = require('git').modes +local loadstring = loadstring or load -- Import a fs path into the database return function (db, fs, rootpath, rules, nativeOnly) diff --git a/libs/pkg.lua b/libs/pkg.lua index 8081bfe..894586c 100644 --- a/libs/pkg.lua +++ b/libs/pkg.lua @@ -32,6 +32,15 @@ local semver = require('semver') local pathJoin = require('luvi').path.join local listToMap = require('git').listToMap local jsonParse = require('json').parse +local load = load +if not load then + function load(code, name, mode, env) + local fn, err = loadstring(code, name) + if not fn then return fn, err end + if env then setfenv(fn, env) end + return fn + end +end local function evalModule(data, name) -- Match multiline lua comments that start with `lit-meta` @@ -40,21 +49,19 @@ local function evalModule(data, name) local term = "]" .. data:sub(a + 3, b - 9) .."]" local c = data:find(term, b + 1, true) if c then - local fn, err = loadstring(data:sub(b + 1, c - 1), name) - assert(not err, err) local env = {} - setfenv(fn, env) + local fn, err = load(data:sub(b + 1, c - 1), name, "t", env) + assert(not err, err) assert(pcall(fn)) return env end end - local fn, err = loadstring(data, name) - if not fn then return nil, err end local exports = {} local module = { exports = exports } - setfenv(fn, { + local fn, err = load(data, name, 't', { exports = exports, }) + if not fn then return nil, err end local success, ret = pcall(fn) local meta = success and type(ret) == "table" and ret or module.exports diff --git a/libs/rules.lua b/libs/rules.lua index 92cebb5..f914157 100644 --- a/libs/rules.lua +++ b/libs/rules.lua @@ -16,21 +16,29 @@ limitations under the License. --]] -local ffi = require('ffi') local log = require('log').log local pathJoin = require('luvi').path.join local modes = require('git').modes local colorize = require('pretty-print').colorize +local unpack = unpack or table.unpack +local loadstring = loadstring or load local quotepattern = '['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..']' +local native_os, native_arch +do + local info = require('luv').os_uname() + native_os = info.sysname + native_arch = info.machine +end + -- When importing into the db to publish, we want to include binaries for all -- platforms, but when installing to disk or zip app bundle, we want native only. local patterns = { -- Rough translation of (Linux|Windows|OSX|BSD) and (x86|x64|arm) -- This is more liberal than it needs to be, but works mostly in practice. all = {"[LWOB][iS][nXD][uxdows]*", "[xa][86r][64m]"}, - native = {ffi.os, ffi.arch}, + native = {native_os, native_arch}, } local function compileFilter(rootPath, rules, nativeOnly) diff --git a/libs/stats.lua b/libs/stats.lua index 2deb540..1934533 100644 --- a/libs/stats.lua +++ b/libs/stats.lua @@ -1,7 +1,7 @@ local jsonStringify = require('json').stringify local uv = require('uv') local scandir = require('coro-fs').scandir -local ffi = require('ffi') +local exists = require('coro-fs').exists return function (_, res) local handles = {} @@ -22,10 +22,10 @@ return function (_, res) local memoryUsed = 1024 * collectgarbage("count") -- Count file descriptors - local path = ({ - Linux = "/proc/self/fd", - OSX = "/dev/fd" - })[ffi.os] + local path = "/proc/self/fd" + if not exists(path) then + path = "/dev/fd" + end local entries = 0 local iter = scandir(path) for _ in iter do diff --git a/luvit-loader.lua b/luvit-loader.lua index c5a9d6b..10b820b 100644 --- a/luvit-loader.lua +++ b/luvit-loader.lua @@ -27,6 +27,7 @@ else end local getenv = require('os').getenv +local loadstring = loadstring or load local isWindows if _G.jit then @@ -139,10 +140,51 @@ local function pathJoin(...) return path end -local function loader(dir, path, bundleOnly) +local function loader(path, fullPath) + local useBundle = fullPath:sub(1, 7) == "bundle:" + if useBundle then + fullPath = fullPath:sub(8) + end + if useBundle then + local key = "bundle:" .. fullPath + if package.loaded[key] then + return package.loaded[key] + end + local code = bundle.readfile(fullPath) + local module = loadstring(code, key)(key) + package.loaded[key] = module + return module + end + fullPath = uv.fs_realpath(fullPath) + if package.loaded[fullPath] then + return package.loaded[fullPath] + end + local module = assert(loadfile(fullPath))(fullPath) + package.loaded[fullPath] = module + return module +end + +local cwd = uv.cwd() +local function searcher(path) + local level, caller = 3 + -- Loop past any C functions to get to the real caller + -- This avoids pcall(require, "path") getting "=C" as the source + repeat + caller = debug.getinfo(level, "S").source + level = level + 1 + until caller ~= "=[C]" + + local dir local errors = {} local fullPath - local useBundle = bundleOnly + local useBundle = false + if string.sub(caller, 1, 1) == "@" then + dir = pathJoin(cwd, caller:sub(2), "..") + elseif string.sub(caller, 1, 7) == "bundle:" then + useBundle = true + dir = pathJoin(caller:sub(8), "..") + end + local function try(tryPath) local prefix = useBundle and "bundle:" or "" local fileStat = useBundle and bundle.stat or uv.fs_stat @@ -191,47 +233,26 @@ local function loader(dir, path, bundleOnly) -- Module require end if useBundle then - local key = "bundle:" .. fullPath - return function () - if package.loaded[key] then - return package.loaded[key] - end - local code = bundle.readfile(fullPath) - local module = loadstring(code, key)(key) - package.loaded[key] = module - return module - end, key - end - fullPath = uv.fs_realpath(fullPath) - return function () - if package.loaded[fullPath] then - return package.loaded[fullPath] + if bundle.stat(fullPath) then + return loader, 'bundle:' .. fullPath + end + else + if uv.fs_access(fullPath) then + return loader, fullPath end - local module = assert(loadfile(fullPath))(fullPath) - package.loaded[fullPath] = module - return module end end -- Register as a normal lua package loader. -local cwd = uv.cwd() -table.insert(package.loaders, 1, function (path) - - -- Ignore built-in libraries with this loader. - if path:match("^[a-z]+$") and package.preload[path] then - return - end +if package.loaders then + table.insert(package.loaders, 1, function (path) + local loader_fn, loader_data = searcher(path) + if not loader_fn then + return nil + end - local level, caller = 3 - -- Loop past any C functions to get to the real caller - -- This avoids pcall(require, "path") getting "=C" as the source - repeat - caller = debug.getinfo(level, "S").source - level = level + 1 - until caller ~= "=[C]" - if string.sub(caller, 1, 1) == "@" then - return loader(pathJoin(cwd, caller:sub(2), ".."), path) - elseif string.sub(caller, 1, 7) == "bundle:" then - return loader(pathJoin(caller:sub(8), ".."), path, true) - end -end) + return loader(path, loader_data) + end) +else + table.insert(package.searchers, 1, searcher) +end \ No newline at end of file diff --git a/main.lua b/main.lua index 2fb04b3..4abcaf2 100644 --- a/main.lua +++ b/main.lua @@ -16,6 +16,8 @@ limitations under the License. --]] +local loadstring = loadstring or load + local bundle = require("luvi").bundle loadstring(bundle.readfile("luvit-loader.lua"), "bundle:luvit-loader.lua")() diff --git a/tests/main.lua b/tests/main.lua index 6a2618e..e7aea9f 100644 --- a/tests/main.lua +++ b/tests/main.lua @@ -1,7 +1,10 @@ +local loadstring = loadstring or load + local bundle = require('luvi').bundle loadstring(bundle.readfile("../luvit-loader.lua"), "bundle:luvit-loader.lua")() local uv = require('uv') +local unpack = unpack or table.unpack coroutine.wrap(function () local success, err = xpcall(function ()