diff options
Diffstat (limited to 'Master/texmf-dist/scripts/l3build/l3build-upload.lua')
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-upload.lua | 185 |
1 files changed, 133 insertions, 52 deletions
diff --git a/Master/texmf-dist/scripts/l3build/l3build-upload.lua b/Master/texmf-dist/scripts/l3build/l3build-upload.lua index 68692b0af4c..4afee06b4ed 100644 --- a/Master/texmf-dist/scripts/l3build/l3build-upload.lua +++ b/Master/texmf-dist/scripts/l3build/l3build-upload.lua @@ -22,6 +22,22 @@ for those people who are interested. --]] +local pairs = pairs +local print = print +local tostring = tostring + +local close = io.close +local flush = io.flush +local open = io.open +local popen = io.popen +local read = io.read +local write = io.write + +local os_type = os.type + +local len = string.len +local lower = string.lower +local match = string.match -- UPLOAD() -- @@ -53,70 +69,83 @@ local curl_debug = curl_debug or false -- to disable posting -- For now, this is undocumented. local ctanupload = ctanupload or "ask" +if options["dry-run"] then + ctanupload = false +end -- if ctanupload is nil or false, only validation is attempted -- if ctanupload is true the ctan upload URL will be used after validation -- if upload is anything else, the user will be prompted whether to upload. -- For now, this is undocumented. I think I would prefer to keep it always set to ask for the time being. -function upload() +function upload(tagnames) local uploadfile = ctanzip..".zip" + -- Keep data local + local uploadconfig = uploadconfig + -- try a sensible default for the package name: uploadconfig.pkg = uploadconfig.pkg or ctanpkg or nil - -- start building the curl command: - ctan_post = curlexe .. " " + -- Get data from command line if appropriate + if options["file"] then + local f = open(options["file"],"r") + uploadconfig.announcement = assert(f:read('*a')) + close(f) + end + uploadconfig.announcement = options["message"] or uploadconfig.announcement + uploadconfig.email = options["email"] or uploadconfig.email - -- build up the curl command field-by-field: + local tagnames = tagnames or { } + uploadconfig.version = tagnames[1] or uploadconfig.version - -- field max desc mandatory multi - -- ---------------------------------------------------------------------------------------------------- - ctan_field("announcement", uploadconfig.announcement, 8192, "Announcement", false, false ) - ctan_field("author", uploadconfig.author, 128, "Author name", true, false ) - ctan_field("bugtracker", uploadconfig.bugtracker, 255, "URL(s) of bug tracker", false, true ) - ctan_field("ctanPath", uploadconfig.ctanPath, 255, "CTAN path", true, false ) - ctan_field("description", uploadconfig.description, 4096, "Short description of package", false, false ) - ctan_field("development", uploadconfig.development, 255, "URL(s) of development channels", false, true ) - ctan_field("email", uploadconfig.email, 255, "Email of uploader", true, false ) - ctan_field("home", uploadconfig.home, 255, "URL(s) of home page", false, true ) - ctan_field("license", uploadconfig.license, 2048, "Package license(s)", true, true ) - ctan_field("note", uploadconfig.note, 4096, "Internal note to ctan", false, false ) - ctan_field("pkg", uploadconfig.pkg, 32, "Package name", true, false ) - ctan_field("repository", uploadconfig.repository, 255, "URL(s) of source repositories", false, true ) - ctan_field("summary", uploadconfig.summary, 128, "One-line summary of package", true, false ) - ctan_field("support", uploadconfig.support, 255, "URL(s) of support channels", false, true ) - ctan_field("topic", uploadconfig.topic, 1024, "Topic(s)", false, true ) - ctan_field("update", uploadconfig.update, 8, "Boolean: true=update, false=new pkg", false, false ) - ctan_field("uploader", uploadconfig.uploader, 255, "Name of uploader", true, false ) - ctan_field("version", uploadconfig.version, 32, "Package version", true, false ) - - -- finish constructing the curl command: - ctan_post = ctan_post .. " --form 'file=@" .. tostring(uploadfile) .. ";filename=" .. tostring(uploadfile) .. "'" - ctan_post = ctan_post .. " https://ctan.org/submit/" + local override_update_check = false + if uploadconfig.update == nil then + uploadconfig.update = true + override_update_check = true + end -- avoid lower level error from post command if zip file missing - local zip=io.open(trim_space(tostring(uploadfile)),"r") + local zip=open(trim_space(tostring(uploadfile)),"r") if zip~=nil then - io.close(zip) + close(zip) else error("Missing zip file '" .. tostring(uploadfile) .. "'") end + ctan_post = construct_ctan_post(uploadfile,options["debug"]) + + if options["debug"] then + fp_return = shell(ctan_post) + print('\n\nCURL COMMAND:') + print(ctan_post) + print("\n\nHTTP RESPONSE:") + print(fp_return) + return 1 + end + -- call post command to validate the upload at CTAN's validate URL local exit_status=0 local fp_return="" -- use popen not execute so get the return body local exit_status=os.execute(ctan_post .. "validate") if (curl_debug==false) then - local fp = assert(io.popen(ctan_post .. "validate", 'r')) - fp_return = assert(fp:read('*a')) - fp:close() + print("Contacting CTAN for validation:") + fp_return = shell(ctan_post .. "validate") else fp_return="WARNING: curl_debug==true: posting disabled" print(ctan_post) + return 1 + end + if override_update_check then + if match(fp_return,"non%-existent%spackage") then + print("Package not found on CTAN; re-validating as new package:") + uploadconfig.update = false + ctan_post = construct_ctan_post(uploadfile) + fp_return = shell(ctan_post .. "validate") + end end - if string.match(fp_return,"WARNING") or string.match(fp_return,"ERROR") then + if match(fp_return,"WARNING") or match(fp_return,"ERROR") then exit_status=1 end @@ -125,22 +154,20 @@ function upload() if (ctanupload ~=nil and ctanupload ~=false and ctanupload ~= true) then print("Validation successful, do you want to upload to CTAN? [y/n]" ) local answer="" - io.write("> ") - io.flush() - answer=io.read() - if(string.lower(answer,1,1)=="y") then + write("> ") + flush() + answer=read() + if(lower(answer,1,1)=="y") then ctanupload=true end end if (ctanupload==true) then - local fp = assert(io.popen(ctan_post .. "upload", 'r')) - fp_return = assert(fp:read('*a')) - fp:close() + fp_return = shell(ctan_post .. "upload") -- this is just html, could save to a file -- or echo a cleaned up version print('Response from CTAN:') print(fp_return) - if string.match(fp_return,"WARNING") or string.match(fp_return,"ERROR") then + if match(fp_return,"WARNING") or match(fp_return,"ERROR") then exit_status=1 end else @@ -158,6 +185,57 @@ function trim_space(s) end +function shell(s) + local h = assert(popen(s, 'r')) + t = assert(h:read('*a')) + h:close() + return t +end + +function construct_ctan_post(uploadfile,debug) + + -- start building the curl command: + ctan_post = curlexe .. " " + + -- build up the curl command field-by-field: + + -- field max desc mandatory multi + -- ---------------------------------------------------------------------------------------------------- + ctan_field("announcement", uploadconfig.announcement, 8192, "Announcement", true, false ) + ctan_field("author", uploadconfig.author, 128, "Author name", true, false ) + ctan_field("bugtracker", uploadconfig.bugtracker, 255, "URL(s) of bug tracker", false, true ) + ctan_field("ctanPath", uploadconfig.ctanPath, 255, "CTAN path", true, false ) + ctan_field("description", uploadconfig.description, 4096, "Short description of package", false, false ) + ctan_field("development", uploadconfig.development, 255, "URL(s) of development channels", false, true ) + ctan_field("email", uploadconfig.email, 255, "Email of uploader", true, false ) + ctan_field("home", uploadconfig.home, 255, "URL(s) of home page", false, true ) + ctan_field("license", uploadconfig.license, 2048, "Package license(s)", true, true ) + ctan_field("note", uploadconfig.note, 4096, "Internal note to ctan", false, false ) + ctan_field("pkg", uploadconfig.pkg, 32, "Package name", true, false ) + ctan_field("repository", uploadconfig.repository, 255, "URL(s) of source repositories", false, true ) + ctan_field("summary", uploadconfig.summary, 128, "One-line summary of package", true, false ) + ctan_field("support", uploadconfig.support, 255, "URL(s) of support channels", false, true ) + ctan_field("topic", uploadconfig.topic, 1024, "Topic(s)", false, true ) + ctan_field("update", uploadconfig.update, 8, "Boolean: true=update, false=new pkg", false, false ) + ctan_field("uploader", uploadconfig.uploader, 255, "Name of uploader", true, false ) + ctan_field("version", uploadconfig.version, 32, "Package version", true, false ) + + -- finish constructing the curl command: + local qq = '"' + if os_type == "windows" then + qq = '\"' + end + ctan_post = ctan_post .. ' --form ' .. qq .. 'file=@' .. tostring(uploadfile) .. ';filename=' .. tostring(uploadfile) .. qq + if debug then + ctan_post = ctan_post .. ' https://httpbin.org/post' + else + ctan_post = ctan_post .. ' https://ctan.org/submit/' + end + + return ctan_post + +end + function ctan_field(fname,fvalue,max,desc,mandatory,multi) if (type(fvalue)=="table" and multi==true) then for i, v in pairs(fvalue) do @@ -170,7 +248,9 @@ end function ctan_single_field(fname,fvalue,max,desc,mandatory) - print('ctan-post: ' .. fname .. ' ' ..tostring(fvalue or '??')) + local fvalueprint = fvalue + if fvalue == nil then fvalueprint = '??' end + print('ctan-upload | ' .. fname .. ': ' ..tostring(fvalueprint)) if ((fvalue==nil and mandatory) or (fvalue == 'ask')) then if (max < 256) then fvalue=input_single_line_field(fname) @@ -183,13 +263,14 @@ function ctan_single_field(fname,fvalue,max,desc,mandatory) if (mandatory==true and (fvalue == nil or vs=="")) then error("The field " .. fname .. " must contain " .. desc) end - if (fvalue ~=nil and string.len(vs) > 0) then - if (max > 0 and string.len(vs) > max) then + if (fvalue ~=nil and len(vs) > 0) then + if (max > 0 and len(vs) > max) then error("The field " .. fname .. " is longer than " .. max) end vs = vs:gsub('"','\\"') vs = vs:gsub('`','\\`') - ctan_post=ctan_post .." --form " .. fname .. '="' .. vs .. '"' + vs = vs:gsub('\n','\\n') + ctan_post=ctan_post .. ' --form "' .. fname .. "=" .. vs .. '"' end else error("The value of the field '" .. fname .."' must be a scalar not a table") @@ -206,9 +287,9 @@ function input_multi_line_field (name) local answer_line local return_count=0 repeat - io.write("> ") - io.flush() - answer_line=io.read() + write("> ") + flush() + answer_line=read() if answer_line=="" then return_count=return_count+1 else @@ -229,9 +310,9 @@ function input_single_line_field(name) local field="" - io.write("> ") - io.flush() - field=io.read() + write("> ") + flush() + field=read() return field end |