From dc9d2daf9deaf867b6caaf88ab1bb088e2b4622d Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Mon, 26 May 2014 19:41:17 -0300 Subject: Transition to MoonRocks. Add `luarocks upload` command for uploading into MoonRocks. --- src/bin/luarocks | 1 + src/luarocks/cfg.lua | 15 +++--- src/luarocks/pack.lua | 4 +- src/luarocks/upload.lua | 88 +++++++++++++++++++++++++++++++ src/luarocks/upload/multipart.lua | 107 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+), 8 deletions(-) create mode 100644 src/luarocks/upload.lua create mode 100644 src/luarocks/upload/multipart.lua (limited to 'src') diff --git a/src/bin/luarocks b/src/bin/luarocks index b85fbc7c..3c9e1b74 100755 --- a/src/bin/luarocks +++ b/src/bin/luarocks @@ -23,6 +23,7 @@ commands = { write_rockspec = "luarocks.write_rockspec", purge = "luarocks.purge", doc = "luarocks.doc", + upload = "luarocks.upload", } command_line.run_command(...) diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua index 59a17754..a96d610f 100644 --- a/src/luarocks/cfg.lua +++ b/src/luarocks/cfg.lua @@ -32,7 +32,7 @@ end cfg.site_config = site_config -cfg.program_version = "2.1.2" +cfg.program_version = "2.2.0beta1" cfg.major_version = cfg.program_version:match("([^.]%.[^.])") local persist = require("luarocks.persist") @@ -214,14 +214,17 @@ local defaults = { rocks_servers = { { - "http://www.luarocks.org/repositories/rocks", - "http://luarocks.giga.puc-rio.br/", - "http://luafr.org/luarocks/rocks", - "http://liblua.so/luarocks/repositories/rocks", - "http://luarocks.logiceditor.com/rocks", + "http://rocks.moonscript.org", + "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/", } }, disabled_servers = {}, + + upload = { + server = "rocks.moonscript.org", + tool_version = "0.0.1", + api_version = "1", + }, lua_extension = "lua", lua_interpreter = site_config.LUA_INTERPRETER or "lua", diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua index d8b3ad9b..c73d66ab 100644 --- a/src/luarocks/pack.lua +++ b/src/luarocks/pack.lua @@ -33,7 +33,7 @@ argument. -- @param rockspec_file string: An URL or pathname for a rockspec file. -- @return string or (nil, string): The filename of the resulting -- .src.rock file; or nil and an error message. -local function pack_source_rock(rockspec_file) +function pack.pack_source_rock(rockspec_file) assert(type(rockspec_file) == "string") local rockspec, err = fetch.load_rockspec(rockspec_file) @@ -201,7 +201,7 @@ function pack.run(...) local file, err if arg:match(".*%.rockspec") then - file, err = pack_source_rock(arg) + file, err = pack.pack_source_rock(arg) else file, err = do_pack_binary_rock(arg, version) end diff --git a/src/luarocks/upload.lua b/src/luarocks/upload.lua new file mode 100644 index 00000000..018e702d --- /dev/null +++ b/src/luarocks/upload.lua @@ -0,0 +1,88 @@ + +local upload = {} + +local util = require("luarocks.util") +local fetch = require("luarocks.fetch") +local pack = require("luarocks.pack") +local Api = require("luarocks.upload.api") + +upload.help_summary = "Upload a rockspec to the public rocks repository." +upload.help_arguments = "[--skip-pack] [--api-key=] [--force] " +upload.help = [[ + Pack a source rock file (.src.rock extension), + upload rockspec and source rock to server. +--skip-pack Do not pack and send source rock. +--api-key= Give it an API key. It will be stored for subsequent uses. +--force Replace existing rockspec if the same revision of + a module already exists. This should be used only + in case of upload mistakes: when updating a rockspec, + increment the revision number instead. +]] + +function upload.run(...) + local flags, fname = util.parse_flags(...) + if not fname then + return nil, "Missing rockspec. "..util.see_help("upload") + end + + local api, err = Api.new(flags) + if not api then + return nil, err + end + + local rockspec, err, errcode = fetch.load_rockspec(fname) + if err then + return nil, err, errcode + end + + util.printout("Sending " .. tostring(fname) .. " ...") + local res, err = api:method("check_rockspec", { + package = rockspec.package, + version = rockspec.version + }) + if not res then return nil, err end + + if not res.module then + util.printout("Will create new module (" .. tostring(rockspec.package) .. ")") + end + if res.version and not flags["force"] then + return nil, "Revision "..rockspec.version.." already exists on the server. "..util.see_help("upload") + end + + local rock_fname + if not flags["skip-pack"] then + util.printout("Packing " .. tostring(rockspec.package)) + rock_fname, err = pack.pack_source_rock(fname) + if not rock_fname then + return nil, err + end + end + + local multipart = require("luarocks.upload.multipart") + + res, err = api:method("upload", nil, { + rockspec_file = multipart.new_file(fname) + }) + if not res then return nil, err end + + if res.is_new and #res.manifests == 0 then + util.printerr("Warning: module not added to root manifest due to name taken.") + end + + local module_url = res.module_url + + if rock_fname then + util.printout(("Sending " .. tostring(rock_fname) .. " ...")) + res, err = api:method("upload_rock/" .. tostring(res.version.id), nil, { + rock_file = multipart.new_file(rock_fname) + }) + if not res then return nil, err end + end + + util.printout() + util.printout("Done: " .. tostring(module_url)) + util.printout() + return true +end + +return upload diff --git a/src/luarocks/upload/multipart.lua b/src/luarocks/upload/multipart.lua new file mode 100644 index 00000000..95afe1b3 --- /dev/null +++ b/src/luarocks/upload/multipart.lua @@ -0,0 +1,107 @@ + +local multipart = {} + +local url = require("socket.url") + +local File = {} + +local unpack = unpack or table.unpack + +math.randomseed(os.time()) + +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) + else + self.mimetype = "application/octet-stream" + end + end + return self.mimetype +end + +function File:content() + local fd = io.open(self.fname) + 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 = 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 + -- cgit v1.2.3-55-g6feb