summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/l3build/l3build-upload.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/scripts/l3build/l3build-upload.lua')
-rw-r--r--Master/texmf-dist/scripts/l3build/l3build-upload.lua185
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