This is an important refactor of the way documentation generation works

* Installs luarocks WITH it's executable (easy to install other rocks if necessary)
* Use Lua supplied with luarocks
* Create Utils/luadocumentor.bat, which works with RELATIVE PATH ! -> Everybody can generate the doc
* Updated launch files accordingly
This commit is contained in:
Grey-Echo
2017-04-05 01:26:39 +02:00
parent 513a103947
commit 3b69cf992e
313 changed files with 16547 additions and 36807 deletions

View File

@@ -0,0 +1,284 @@
local api = {}
local cfg = require("luarocks.cfg")
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local persist = require("luarocks.persist")
local multipart = require("luarocks.upload.multipart")
local Api = {}
local function upload_config_file()
local conf = cfg.which_config()
if not conf.user.file then
return nil
end
return (conf.user.file:gsub("/[^/]+$", "/upload_config.lua"))
end
function Api:load_config()
local upload_conf = upload_config_file()
if not upload_conf then return nil end
local cfg, err = persist.load_into_table(upload_conf)
return cfg
end
function Api:save_config()
-- Test configuration before saving it.
local res, err = self:raw_method("status")
if not res then
return nil, err
end
if res.errors then
util.printerr("Server says: " .. tostring(res.errors[1]))
return
end
local upload_conf = upload_config_file()
if not upload_conf then return nil end
persist.save_from_table(upload_conf, self.config)
fs.chmod(upload_conf, "0600")
end
function Api:check_version()
if not self._server_tool_version then
local tool_version = cfg.upload.tool_version
local res, err = self:request(tostring(self.config.server) .. "/api/tool_version", {
current = tool_version
})
if not res then
return nil, err
end
if not res.version then
return nil, "failed to fetch tool version"
end
self._server_tool_version = res.version
if res.force_update then
return nil, "Your upload client is too out of date to continue, please upgrade LuaRocks."
end
if res.version ~= tool_version then
util.printerr("Warning: Your LuaRocks is out of date, consider upgrading.")
end
end
return true
end
function Api:method(...)
local res, err = self:raw_method(...)
if not res then
return nil, err
end
if res.errors then
if res.errors[1] == "Invalid key" then
return nil, res.errors[1] .. " (use the --api-key flag to change)"
end
local msg = table.concat(res.errors, ", ")
return nil, "API Failed: " .. msg
end
return res
end
function Api:raw_method(path, ...)
self:check_version()
local url = tostring(self.config.server) .. "/api/" .. tostring(cfg.upload.api_version) .. "/" .. tostring(self.config.key) .. "/" .. tostring(path)
return self:request(url, ...)
end
local function encode_query_string(t, sep)
if sep == nil then
sep = "&"
end
local i = 0
local buf = { }
for k, v in pairs(t) do
if type(k) == "number" and type(v) == "table" then
k, v = v[1], v[2]
end
buf[i + 1] = multipart.url_escape(k)
buf[i + 2] = "="
buf[i + 3] = multipart.url_escape(v)
buf[i + 4] = sep
i = i + 4
end
buf[i] = nil
return table.concat(buf)
end
-- An ode to the multitude of JSON libraries out there...
local function require_json()
local list = { "cjson", "dkjson", "json" }
for _, lib in ipairs(list) do
local json_ok, json = pcall(require, lib)
if json_ok then
pcall(json.use_lpeg) -- optional feature in dkjson
return json_ok, json
end
end
local errmsg = "Failed loading "
for i, name in ipairs(list) do
if i == #list then
errmsg = errmsg .."and '"..name.."'. Use 'luarocks search <partial-name>' to search for a library and 'luarocks install <name>' to install one."
else
errmsg = errmsg .."'"..name.."', "
end
end
return nil, errmsg
end
local function redact_api_url(url)
url = tostring(url)
return (url:gsub(".*/api/[^/]+/[^/]+", "")) or ""
end
local ltn12_ok, ltn12 = pcall(require, "ltn12")
if not ltn12_ok then -- If not using LuaSocket and/or LuaSec...
function Api:request(url, params, post_params)
local vars = cfg.variables
local json_ok, json = require_json()
if not json_ok then return nil, "A JSON library is required for this command. "..json end
if cfg.downloader == "wget" then
local curl_ok, err = fs.is_tool_available(vars.CURL, "curl")
if not curl_ok then
return nil, err
end
end
if not self.config.key then
return nil, "Must have API key before performing any actions."
end
if params and next(params) then
url = url .. ("?" .. encode_query_string(params))
end
local method = "GET"
local out
local tmpfile = fs.tmpname()
if post_params then
method = "POST"
local curl_cmd = fs.Q(vars.CURL).." -f -k -L --silent --user-agent \""..cfg.user_agent.." via curl\" "
for k,v in pairs(post_params) do
local var = v
if type(v) == "table" then
var = "@"..v.fname
end
curl_cmd = curl_cmd .. "--form \""..k.."="..var.."\" "
end
if cfg.connection_timeout and cfg.connection_timeout > 0 then
curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
end
local ok = fs.execute_string(curl_cmd..fs.Q(url).." -o "..fs.Q(tmpfile))
if not ok then
return nil, "API failure: " .. redact_api_url(url)
end
else
local ok, err = fs.download(url, tmpfile)
if not ok then
return nil, "API failure: " .. tostring(err) .. " - " .. redact_api_url(url)
end
end
local tmpfd = io.open(tmpfile)
if not tmpfd then
os.remove(tmpfile)
return nil, "API failure reading temporary file - " .. redact_api_url(url)
end
out = tmpfd:read("*a")
tmpfd:close()
os.remove(tmpfile)
if self.debug then
util.printout("[" .. tostring(method) .. " via curl] " .. redact_api_url(url) .. " ... ")
end
return json.decode(out)
end
else -- use LuaSocket and LuaSec
local warned_luasec = false
function Api:request(url, params, post_params)
local json_ok, json = require_json()
if not json_ok then return nil, "A JSON library is required for this command. "..json end
local server = tostring(self.config.server)
local http_ok, http
local via = "luasocket"
if server:match("^https://") then
http_ok, http = pcall(require, "ssl.https")
if http_ok then
via = "luasec"
else
if not warned_luasec then
util.printerr("LuaSec is not available; using plain HTTP. Install 'luasec' to enable HTTPS.")
warned_luasec = true
end
http_ok, http = pcall(require, "socket.http")
url = url:gsub("^https", "http")
via = "luasocket"
end
else
http_ok, http = pcall(require, "socket.http")
end
if not http_ok then
return nil, "Failed loading socket library!"
end
if not self.config.key then
return nil, "Must have API key before performing any actions."
end
local body
local headers = {}
if params and next(params) then
url = url .. ("?" .. encode_query_string(params))
end
if post_params then
local boundary
body, boundary = multipart.encode(post_params)
headers["Content-length"] = #body
headers["Content-type"] = "multipart/form-data; boundary=" .. tostring(boundary)
end
local method = post_params and "POST" or "GET"
if self.debug then
util.printout("[" .. tostring(method) .. " via "..via.."] " .. redact_api_url(url) .. " ... ")
end
local out = {}
local _, status = http.request({
url = url,
headers = headers,
method = method,
sink = ltn12.sink.table(out),
source = body and ltn12.source.string(body)
})
if self.debug then
util.printout(tostring(status))
end
if status ~= 200 then
return nil, "API returned " .. tostring(status) .. " - " .. redact_api_url(url)
end
return json.decode(table.concat(out))
end
end
function api.new(flags)
local self = {}
setmetatable(self, { __index = Api })
self.config = self:load_config() or {}
self.config.server = flags["server"] or self.config.server or cfg.upload.server
self.config.version = self.config.version or cfg.upload.version
self.config.key = flags["api-key"] or self.config.key
self.debug = flags["debug"]
if not self.config.key then
return nil, "You need an API key to upload rocks.\n" ..
"Navigate to "..self.config.server.."/settings to get a key\n" ..
"and then pass it through the --api-key=<key> flag."
end
if flags["api-key"] then
self:save_config()
end
return self
end
return api

View File

@@ -0,0 +1,111 @@
local multipart = {}
local File = {}
local unpack = unpack or table.unpack
math.randomseed(os.time())
-- socket.url.escape(s) from LuaSocket 3.0rc1
function multipart.url_escape(s)
return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
return string.format("%%%02x", string.byte(c))
end))
end
function File:mime()
if not self.mimetype then
local mimetypes_ok, mimetypes = pcall(require, "mimetypes")
if mimetypes_ok then
self.mimetype = mimetypes.guess(self.fname)
end
self.mimetype = self.mimetype or "application/octet-stream"
end
return self.mimetype
end
function File:content()
local fd = io.open(self.fname, "rb")
if not fd then
return nil, "Failed to open file: "..self.fname
end
local data = fd:read("*a")
fd:close()
return data
end
local function rand_string(len)
local shuffled = {}
for i = 1, len do
local r = math.random(97, 122)
if math.random() >= 0.5 then
r = r - 32
end
shuffled[i] = r
end
return string.char(unpack(shuffled))
end
-- multipart encodes params
-- returns encoded string,boundary
-- params is an a table of tuple tables:
-- params = {
-- {key1, value2},
-- {key2, value2},
-- key3: value3
-- }
function multipart.encode(params)
local tuples = { }
for i = 1, #params do
tuples[i] = params[i]
end
for k,v in pairs(params) do
if type(k) == "string" then
table.insert(tuples, {k, v})
end
end
local chunks = {}
for _, tuple in ipairs(tuples) do
local k,v = unpack(tuple)
k = multipart.url_escape(k)
local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' }
local content
if type(v) == "table" and v.__class == File then
buffer[1] = buffer[1] .. ('; filename="' .. v.fname:gsub(".*/", "") .. '"')
table.insert(buffer, "Content-type: " .. v:mime())
content = v:content()
else
content = v
end
table.insert(buffer, "")
table.insert(buffer, content)
table.insert(chunks, table.concat(buffer, "\r\n"))
end
local boundary
while not boundary do
boundary = "Boundary" .. rand_string(16)
for _, chunk in ipairs(chunks) do
if chunk:find(boundary) then
boundary = nil
break
end
end
end
local inner = "\r\n--" .. boundary .. "\r\n"
return table.concat({ "--", boundary, "\r\n",
table.concat(chunks, inner),
"\r\n", "--", boundary, "--", "\r\n" }), boundary
end
function multipart.new_file(fname, mime)
local self = {}
setmetatable(self, { __index = File })
self.__class = File
self.fname = fname
self.mimetype = mime
return self
end
return multipart