Mercurial > wow > cyborg-mmo7
comparison support/casc/platform.lua @ 65:8b8b0bade520
Fixed support for mounts using the new MountJournal and mount IDs (no conversion of old profiles at the moment).
| author | Jerome Vuarand <jerome.vuarand@gmail.com> | 
|---|---|
| date | Thu, 23 Oct 2014 13:44:59 +0100 | 
| parents | |
| children | 
   comparison
  equal
  deleted
  inserted
  replaced
| 64:49ae7191821f | 65:8b8b0bade520 | 
|---|---|
| 1 local M, assert, getenv = {}, assert, os.getenv | |
| 2 | |
| 3 local function maybe(m) | |
| 4 local ok, v = pcall(require, m) | |
| 5 return ok and v | |
| 6 end | |
| 7 local lfs = maybe("lfs") -- LuaFileSystem; http://keplerproject.github.io/luafilesystem/ | |
| 8 local zlib = maybe("zlib") -- lzlib; https://github.com/LuaDist/lzlib | |
| 9 local bit = maybe("bit") -- Lua BitOp; http://bitop.luajit.org | |
| 10 local socket = maybe("socket.http") -- LuaSocket; http://w3.impa.br/~diego/software/luasocket/home.html | |
| 11 | |
| 12 local function shellEscape(s) | |
| 13 return '"' .. s:gsub('"', '"\\\\""') .. '"' | |
| 14 end | |
| 15 local function readAndDeleteFile(path) | |
| 16 local h, err = io.open(path, "rb") | |
| 17 if h then | |
| 18 local c = h:read("*a") | |
| 19 h:close() | |
| 20 h, err = c, nil | |
| 21 end | |
| 22 os.remove(path) | |
| 23 return h, err | |
| 24 end | |
| 25 | |
| 26 local dir_sep = package and package.config and package.config:sub(1,1) or "/" | |
| 27 do -- M.path(a, b, ...) | |
| 28 M.path = function(a, b, ...) | |
| 29 if a and b then | |
| 30 return M.path(a .. (a:sub(-1) ~= dir_sep and dir_sep or "") .. b, ...) | |
| 31 end | |
| 32 return a | |
| 33 end | |
| 34 end | |
| 35 M.url = function(a, b, ...) | |
| 36 if a and b then | |
| 37 return M.url(a .. ((a:sub(-1) == "/" or b:sub(1,1) == "/") and "" or "/") .. b, ...) | |
| 38 end | |
| 39 return a | |
| 40 end | |
| 41 | |
| 42 M.commands = | |
| 43 dir_sep == '/' and {toDevNull=' 2>/dev/null', ls='ls %s', mkdir='mkdir -p %s', gzip='gzip -dcq %s'} or | |
| 44 dir_sep == '\\' and {toDevNull=' 2>NUL', ls='(for %%a in (%s) do @echo %%~fa)', mkdir='mkdir %s', gzip='gzip -dcq %s', TMP=os.getenv('TMP') or os.getenv('TEMP')} | |
| 45 | |
| 46 M.tmpname = function() | |
| 47 local tn = os.tmpname() | |
| 48 return (M.commands and M.commands.TMP or "") .. tn | |
| 49 end | |
| 50 | |
| 51 M.decompress = zlib and zlib.decompress or function(compressed) | |
| 52 assert(type(compressed) == "string", 'Syntax: casc.platform.decompress("compressed")') | |
| 53 assert(M.commands and M.commands.gzip and M.commands.toDevNull, 'unsupported platform') | |
| 54 | |
| 55 local f, f2 = M.tmpname(), M.tmpname() | |
| 56 local h = io.open(f, "wb") | |
| 57 h:write('\31\139\8\0\0\0\0\0') | |
| 58 h:write(compressed) | |
| 59 h:close() | |
| 60 | |
| 61 os.execute(M.commands.gzip:format(shellEscape(f)) .. " 1>" .. f2 .. " " .. M.commands.toDevNull) | |
| 62 os.remove(f) | |
| 63 | |
| 64 return readAndDeleteFile(f2) | |
| 65 end | |
| 66 | |
| 67 M.mkdir = lfs and lfs.mkdir or function(path) | |
| 68 assert(type(path) == 'string', 'Syntax: casc.platform.mkdir("path")') | |
| 69 assert(M.commands and M.commands.mkdir, 'unsupported platform') | |
| 70 | |
| 71 return os.execute(M.commands.mkdir:format(shellEscape(path))) | |
| 72 end | |
| 73 | |
| 74 M.files = lfs and function(dir, glob) | |
| 75 assert(type(dir) == "string" and type(glob) == 'string', 'Syntax: casc.platform.files("dir", "glob")') | |
| 76 local pat = "^" .. glob:gsub("%.%-%+", "%%%0"):gsub("%*", ".*") .. "$" | |
| 77 local t, ni = {}, 1 | |
| 78 for f in lfs.dir(dir) do | |
| 79 if f ~= "." and f ~= ".." and f:match(pat) then | |
| 80 t[ni], ni = M.path(dir, f), ni + 1 | |
| 81 end | |
| 82 end | |
| 83 return pairs(t) | |
| 84 end or function(dir, glob) | |
| 85 assert(type(dir) == "string" and type(glob) == 'string', 'Syntax: casc.platform.files("dir", "glob")') | |
| 86 assert(M.commands and M.commands.ls, 'unsupported platform') | |
| 87 | |
| 88 local dir, files = glob:match("^(.-)([^" .. dir_sep .. "]+)$") | |
| 89 local t, ni, h = {}, 1, io.popen(M.commands.ls:format(shellEscape(dir) .. files), "r") | |
| 90 for l in h:lines() do | |
| 91 t[ni], ni = l, ni + 1 | |
| 92 end | |
| 93 h:close() | |
| 94 return pairs(t) | |
| 95 end | |
| 96 | |
| 97 local floor = math.floor | |
| 98 M.rol = bit and bit.rol or function(n, b) | |
| 99 local n, e2 = n % 2^32, 2^(32-b) | |
| 100 return ((n % e2) * 2^b + floor(n/e2)) % 2^32 | |
| 101 end | |
| 102 | |
| 103 M.bxor = bit and bit.bxor or function(a, b) | |
| 104 local out, m, lm = 0, 1 | |
| 105 for i=1,32 do | |
| 106 m, lm = m+m, m | |
| 107 local am, bm = a % m, b % m | |
| 108 out, a, b = out + (am == bm and 0 or lm), a-am, b-bm | |
| 109 if a == 0 or b == 0 then | |
| 110 return (out + b + a) % 2^32 | |
| 111 end | |
| 112 end | |
| 113 return out | |
| 114 end | |
| 115 | |
| 116 if socket then | |
| 117 socket.USERAGENT, socket.TIMEOUT = "lcasc/1.1", 5 | |
| 118 local ltn12, RETRIES = require("ltn12"), 3 | |
| 119 M.http = function(url, h) | |
| 120 for i=1,RETRIES do | |
| 121 local sink = {} | |
| 122 local ok, status, head = socket.request({url=url, sink=ltn12.sink.table(sink), headers=h}) | |
| 123 if ok then | |
| 124 local cnt = table.concat(sink, "") | |
| 125 return status >= 200 and status < 300 and cnt, status, head, cnt | |
| 126 elseif i == RETRIES then | |
| 127 error("HTTP request failed: " .. tostring(status) .. "\nURL: " .. tostring(url)) | |
| 128 end | |
| 129 end | |
| 130 end | |
| 131 else | |
| 132 M.http = function(url, h) | |
| 133 local c, of = "curl -s -S -A 'luacasc/1.1+curl'", M.tmpname() | |
| 134 if type(h) == "table" then | |
| 135 for k,v in pairs(h) do | |
| 136 c = c .. ' -H ' .. shellEscape(k .. ": " .. v) | |
| 137 end | |
| 138 end | |
| 139 c = c .. ' -o ' .. shellEscape(of) | |
| 140 c = c .. ' ' .. shellEscape(url) | |
| 141 if os.execute(c) == 0 then | |
| 142 return readAndDeleteFile(of) | |
| 143 end | |
| 144 os.remove(of) | |
| 145 end | |
| 146 end | |
| 147 | |
| 148 return M | 
