diff options
-rw-r--r-- | Build/source/texk/texlive/linked_scripts/l3build/l3build.lua | 33 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/l3build/CHANGELOG.md | 21 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/l3build/README.md | 2 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/l3build/l3build.pdf | bin | 708832 -> 740399 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/man/man1/l3build.1 | 2 | ||||
-rw-r--r-- | Master/texmf-dist/doc/man/man1/l3build.man1.pdf | bin | 15724 -> 15624 bytes | |||
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-arguments.lua | 6 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-check.lua | 76 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-ctan.lua | 50 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-file-functions.lua | 46 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-upload.lua | 40 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-variables.lua | 3 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/l3build/l3build-zip.lua | 119 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/l3build/l3build.lua | 33 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3build/l3build.dtx | 39 |
15 files changed, 391 insertions, 79 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/l3build/l3build.lua b/Build/source/texk/texlive/linked_scripts/l3build/l3build.lua index 82994397648..51b7a493e31 100644 --- a/Build/source/texk/texlive/linked_scripts/l3build/l3build.lua +++ b/Build/source/texk/texlive/linked_scripts/l3build/l3build.lua @@ -25,7 +25,7 @@ for those people who are interested. --]] -- Version information -release_date = "2021-05-06" +release_date = "2021-08-28" -- File operations are aided by the LuaFileSystem module local lfs = require("lfs") @@ -43,6 +43,8 @@ local print = print local select = select local tonumber = tonumber local exit = os.exit +local open = io.open +local stdout = io.stdout -- l3build setup and functions kpse.set_program_name("kpsewhich") @@ -160,6 +162,35 @@ if options["target"] == "check" then end print("") end + if options["show-saves"] then + local savecmds, recheckcmds = "", "" + for _,config in ipairs(failed) do + local testdir = testdir + if config ~= "build" then + testdir = testdir .. "-" .. config + end + local f = open(testdir .. "/.savecommands") + if not f then + print("Error: Cannot find save commands for configuration " .. + config) + exit(2) + end + for line in f:lines() do + if line == "" then break end + savecmds = savecmds .. " " .. line .. "\n" + end + for line in f:lines() do + recheckcmds = recheckcmds .. " " .. line .. "\n" + end + f:close() + end + print"To regenerate the test files, run\n" + print(savecmds) + if recheckcmds ~= "" then + print"To detect engine specific differences, run after that\n" + print(recheckcmds) + end + end exit(1) else -- Avoid running the 'main' set of tests twice diff --git a/Master/texmf-dist/doc/latex/l3build/CHANGELOG.md b/Master/texmf-dist/doc/latex/l3build/CHANGELOG.md index e46a935c3f7..f5be81a9372 100644 --- a/Master/texmf-dist/doc/latex/l3build/CHANGELOG.md +++ b/Master/texmf-dist/doc/latex/l3build/CHANGELOG.md @@ -7,6 +7,23 @@ this project uses date-based 'snapshot' version identifiers. ## [Unreleased] +## [2021-08-28] + +### Fixed +- Creation of zip files on Windows +- Only match filename and not full path for `exefiles` + +## [2021-08-27] + +### Added +- Add the `--show-saves` flag for `l3build check` to generate a list of + `l3build save` commands to regenerate all failing tests + +### Changed +- No longer call an external program to generate `zip` files and generate + them directly instead. This disables the options `zipexe` and `zipopts`. +- Copy TDS-style zip files to main dir + ## [2021-05-06] ### Fixed @@ -492,7 +509,9 @@ this project uses date-based 'snapshot' version identifiers. - Rationalise short option names: removed `-d`, `-E`, `-r` - Target `cmdcheck`: specific to LaTeX kernel work -[Unreleased]: https://github.com/latex3/l3build/compare/2021-05-06...HEAD +[Unreleased]: https://github.com/latex3/l3build/compare/2021-08-28...HEAD +[2021-08-28]: https://github.com/latex3/l3build/compare/2021-08-27...2021-08-28 +[2021-08-27]: https://github.com/latex3/l3build/compare/2021-05-06...2021-08-27 [2021-05-06]: https://github.com/latex3/l3build/compare/2021-05-05...2021-05-06 [2021-05-05]: https://github.com/latex3/l3build/compare/2020-06-04...2021-05-05 [2020-06-04]: https://github.com/latex3/l3build/compare/2020-03-25...2020-06-04 diff --git a/Master/texmf-dist/doc/latex/l3build/README.md b/Master/texmf-dist/doc/latex/l3build/README.md index 219b1ad36c2..635693ae9ff 100644 --- a/Master/texmf-dist/doc/latex/l3build/README.md +++ b/Master/texmf-dist/doc/latex/l3build/README.md @@ -1,7 +1,7 @@ l3build: a testing and building system for LaTeX ================================================= -Release 2021-05-06 +Release 2021-08-28 Overview -------- diff --git a/Master/texmf-dist/doc/latex/l3build/l3build.pdf b/Master/texmf-dist/doc/latex/l3build/l3build.pdf Binary files differindex 447ba668a8c..fe2778114f0 100644 --- a/Master/texmf-dist/doc/latex/l3build/l3build.pdf +++ b/Master/texmf-dist/doc/latex/l3build/l3build.pdf diff --git a/Master/texmf-dist/doc/man/man1/l3build.1 b/Master/texmf-dist/doc/man/man1/l3build.1 index 8e21697dabe..6c2f071a46a 100644 --- a/Master/texmf-dist/doc/man/man1/l3build.1 +++ b/Master/texmf-dist/doc/man/man1/l3build.1 @@ -1,4 +1,4 @@ -.TH l3build 1 "2021-05-06" +.TH l3build 1 "2021-08-28" .SH NAME l3build \- Checking and building packages .SH SYNOPSIS diff --git a/Master/texmf-dist/doc/man/man1/l3build.man1.pdf b/Master/texmf-dist/doc/man/man1/l3build.man1.pdf Binary files differindex 7d9af7120ac..ecb6a8a15cd 100644 --- a/Master/texmf-dist/doc/man/man1/l3build.man1.pdf +++ b/Master/texmf-dist/doc/man/man1/l3build.man1.pdf diff --git a/Master/texmf-dist/scripts/l3build/l3build-arguments.lua b/Master/texmf-dist/scripts/l3build/l3build-arguments.lua index 80f19d66ad5..8f62e8b433f 100644 --- a/Master/texmf-dist/scripts/l3build/l3build-arguments.lua +++ b/Master/texmf-dist/scripts/l3build/l3build-arguments.lua @@ -139,6 +139,12 @@ option_list = desc = "If 'halt-on-error' stops, show the full log of the failure", type = "boolean" }, + ["show-saves"] = + { + desc = "If tests fail, show the l3build save invocation to regenerate the tests", + short = "S", + type = "boolean" + }, shuffle = { desc = "Shuffle order of tests", diff --git a/Master/texmf-dist/scripts/l3build/l3build-check.lua b/Master/texmf-dist/scripts/l3build/l3build-check.lua index 47ab19ced60..f83dee4e448 100644 --- a/Master/texmf-dist/scripts/l3build/l3build-check.lua +++ b/Master/texmf-dist/scripts/l3build/l3build-check.lua @@ -574,14 +574,16 @@ function runcheck(name, hide) if options["engine"] then checkengines = options["engine"] end + local failedengines = {} -- Used for both .lvt and .pvt tests local test_type = test_types[kind] local function check_and_diff(engine) - runtest(name, engine, hide, test_type.test, test_type, true) + runtest(name, engine, hide, test_type.test, test_type, not forcecheckruns) local errorlevel = base_compare(test_type,name,engine) if errorlevel == 0 then return errorlevel end + failedengines[#failedengines + 1] = engine if options["show-log-on-error"] then showfailedlog(name) end @@ -595,14 +597,20 @@ function runcheck(name, hide) setup_check(name,engine) local errlevel = check_and_diff(engine) if errlevel ~= 0 and options["halt-on-error"] then - return 1 + return 1, failedengines end if errlevel > errorlevel then errorlevel = errlevel end end + for i=1, #failedengines do + if failedengines[i] == stdengine then + failedengines = {stdengine} + break + end + end -- Return everything - return errorlevel + return errorlevel, failedengines end function setup_check(name, engine) @@ -845,11 +853,57 @@ function testexists(test) end end +-- A short auxiliary to print the list of differences for check +local function showsavecommands(failurelist) + local savecmds = {} + local checkcmd = "l3build check --show-saves" + local prefix = "l3build save" + if options.config and options.config[1] ~= 'build' then + local config = " -c " .. options.config[1] + prefix = prefix .. config + checkcmd = checkcmd .. config + end + for name, engines in pairs(failurelist) do + for i = 1, #engines do + local engine = engines[i] + local cmd = savecmds[engine] + if not cmd then + if engine == stdengine then + cmd = prefix + else + cmd = prefix .. " -e " .. engine + end + end + savecmds[engine] = cmd .. " " .. name + if engine == stdengine then + checkcmd = checkcmd .. " " .. name + end + end + end + print(" To regenerate the test files, run\n") + local f = open(testdir .. "/.savecommands", "w") + for _, cmds in pairs(savecmds) do + print(" " .. cmds) + f:write(cmds, "\n") + end + f:write"\n" + if savecmds[stdengine] then + print("\n Afterwards test for engine specific changes using\n") + print(" " .. checkcmd) + f:write(checkcmd) + end + f:close() + print("") +end + function check(names) local errorlevel = 0 if testfiledir ~= "" and direxists(testfiledir) then if not options["rerun"] then - checkinit() + errorlevel = checkinit() + if errorlevel ~= 0 then + return errorlevel + end end local hide = true if names and next(names) then @@ -933,11 +987,13 @@ function check(names) end -- Actually run the tests print("Running checks on") + local failurelist = {} for i, name in ipairs(names) do print(" " .. name .. " (" .. i .. "/" .. #names ..")") - local errlevel = runcheck(name, hide) + local errlevel, failedengines = runcheck(name, hide) -- Return value must be 1 not errlevel if errlevel ~= 0 then + failurelist[name] = failedengines if options["halt-on-error"] then return 1 else @@ -949,6 +1005,9 @@ function check(names) end if errorlevel ~= 0 then checkdiff() + if options["show-saves"] then + showsavecommands(failurelist) + end else print("\n All checks passed\n") end @@ -994,7 +1053,12 @@ function showfaileddiff() end function save(names) - checkinit() + do + local errorlevel = checkinit() + if errorlevel ~= 0 then + return errorlevel + end + end local engines = options["engine"] or {stdengine} if names == nil then print("Arguments are required for the save command") diff --git a/Master/texmf-dist/scripts/l3build/l3build-ctan.lua b/Master/texmf-dist/scripts/l3build/l3build-ctan.lua index fd1491dd584..e5b3b7e8f84 100644 --- a/Master/texmf-dist/scripts/l3build/l3build-ctan.lua +++ b/Master/texmf-dist/scripts/l3build/l3build-ctan.lua @@ -25,9 +25,12 @@ for those people who are interested. local pairs = pairs local print = print +local attributes = lfs.attributes local lower = string.lower local match = string.match +local newzip = require"l3build-zip" + -- Copy files to the main CTAN release directory function copyctan() mkdir(ctandir .. "/" .. ctanpkg) @@ -68,33 +71,33 @@ end function ctan() -- Always run tests for all engines options["engine"] = nil - local function dirzip(dir, name) - local zipname = name .. ".zip" - local function tab_to_str(table) - local string = "" - for _,i in ipairs(table) do - string = string .. " " .. "\"" .. i .. "\"" + local function dirzip(dir, zipname) + zipname = zipname .. ".zip" + local zip = newzip(dir .. '/' .. zipname) + local function tab_to_check(table) + local patterns = {} + for n,i in ipairs(table) do + patterns[n] = glob_to_pattern(i) + end + return function(name) + for n, patt in ipairs(patterns) do + if name:match"([^/]*)$":match(patt) then return true end + end + return false end - return string end -- Convert the tables of files to quoted strings - local binfiles = tab_to_str(binaryfiles) - local exclude = tab_to_str(excludefiles) + local binfile = tab_to_check(binaryfiles) + local exclude = tab_to_check(excludefiles) + local exefile = tab_to_check(exefiles) -- First, zip up all of the text files - run( - dir, - zipexe .. " " .. zipopts .. " -ll ".. zipname .. " " .. "." - .. ( - (binfiles or exclude) and (" -x" .. binfiles .. " " .. exclude) - or "" - ) - ) - -- Then add the binary ones - run( - dir, - zipexe .. " " .. zipopts .. " -g ".. zipname .. " " .. ". -i" .. - binfiles .. (exclude and (" -x" .. exclude) or "") - ) + for _, p in ipairs(tree(dir, "**")) do + local src = p.src:sub(3) -- Strip ./ + if not (attributes(p.cwd, "mode") == "directory" or exclude(src) or src == zipname) then + zip:add(p.cwd, src, binfile(src), exefile(src)) + end + end + return zip:close() end local errorlevel local standalone = false @@ -146,6 +149,7 @@ function ctan() dirzip(tdsdir, ctanpkg .. ".tds") if packtdszip then cp(ctanpkg .. ".tds.zip", tdsdir, ctandir) + cp(ctanpkg .. ".tds.zip", tdsdir, currentdir) end dirzip(ctandir, ctanzip) cp(ctanzip .. ".zip", ctandir, currentdir) diff --git a/Master/texmf-dist/scripts/l3build/l3build-file-functions.lua b/Master/texmf-dist/scripts/l3build/l3build-file-functions.lua index 6ca1cc60111..53364bd3010 100644 --- a/Master/texmf-dist/scripts/l3build/l3build-file-functions.lua +++ b/Master/texmf-dist/scripts/l3build/l3build-file-functions.lua @@ -211,6 +211,20 @@ function cleandir(dir) return rm(dir, "**") end +function direxists(dir) + return attributes(dir, "mode") == "directory" +end + +function fileexists(file) + local f = open(file, "r") + if f ~= nil then + f:close() + return true + else + return false -- also file exits and is not readable + end +end + -- Copy files 'quietly' function cp(glob, source, dest) local errorlevel @@ -218,7 +232,7 @@ function cp(glob, source, dest) -- p_src is a path relative to `source` whereas -- p_cwd is the counterpart relative to the current working directory if os_type == "windows" then - if attributes(p.cwd, "mode") == "directory" then + if direxists(p.cwd) then errorlevel = execute( 'xcopy /y /e /i "' .. unix_to_win(p.cwd) .. '" "' .. unix_to_win(dest .. '/' .. p.src) .. '" > nul' @@ -241,31 +255,6 @@ function cp(glob, source, dest) return 0 end --- OS-dependent test for a directory -function direxists(dir) - local errorlevel - if os_type == "windows" then - errorlevel = - execute("if not exist \"" .. unix_to_win(dir) .. "\" exit 1") - else - errorlevel = execute("[ -d '" .. dir .. "' ]") - end - if errorlevel ~= 0 then - return false - end - return true -end - -function fileexists(file) - local f = open(file, "r") - if f ~= nil then - f:close() - return true - else - return false -- also file exits and is not readable - end -end - -- Generate a table containing all file names of the given glob or all files -- if absent function filelist(path, glob) @@ -309,16 +298,13 @@ function tree(src_path, glob) local function always_true() return true end - local function is_dir(file) - return attributes(file, "mode") == "directory" - end ---@type table<integer,tree_entry_t> local result = { { src = ".", cwd = src_path, } } for glob_part, sep in glob:gmatch("([^/]+)(/?)/*") do - local accept = sep == "/" and is_dir or always_true + local accept = sep == "/" and direxists or always_true ---Feeds the given table according to `glob_part` ---@param p tree_entry_t path counterpart relative to the current working directory ---@param table table diff --git a/Master/texmf-dist/scripts/l3build/l3build-upload.lua b/Master/texmf-dist/scripts/l3build/l3build-upload.lua index 629d2ee7c77..47268f5b6a9 100644 --- a/Master/texmf-dist/scripts/l3build/l3build-upload.lua +++ b/Master/texmf-dist/scripts/l3build/l3build-upload.lua @@ -116,11 +116,24 @@ function upload(tagnames) end -- avoid lower level error from post command if zip file missing - local zip=open(trim_space(tostring(uploadfile)),"r") - if zip~=nil then - close(zip) - else - error("Missing zip file '" .. tostring(uploadfile) .. "'") + local ziptime = lfs.attributes(trim_space(tostring(uploadfile)), 'modification') + if not ziptime then + error("Missing zip file '" .. tostring(uploadfile) .. "'. \z + Maybe you forgot to run 'l3build ctan' first?") + end + local age = os.time() - ziptime + if age >= 86400 then + print(string.format("------------------------------------------\n\z + | The local archive is older than %3i days. |\n\z + | Are you sure that you executed 'l3build ctan' first? |\n\z + --------------------------------------------------------", + age // 86400)) + print("Are you sure you want to continue? [y/n]" ) + io.stdout:write("> "):flush() + if lower(read(),1,1) ~= "y" then + print'Aborting' + return 1 + end end ctan_post = construct_ctan_post(uploadfile,options["debug"]) @@ -174,12 +187,23 @@ end end -- if upload requested and validation succeeded repost to the upload URL - if (exit_status==0 or exit_status==nil) then + if (exit_status==0 or exit_status==nil) then if (ctanupload ~=nil and ctanupload ~=false and ctanupload ~= true) then if (match(fp_return,"WARNING")) then - print("Warnings from CTAN package validation:" .. fp_return:gsub("%[","\n["):gsub("%]%]","]\n]")) + print("Warnings from CTAN package validation:" .. fp_return:gsub("%[","\n["):gsub("%]%]","]\n]")) else - print("Validation successful." ) + print("Validation successful." ) + end + print("" ) + if age < 86400 and age >= 60 then + if age >= 3600 then + print("----------------------------------------------------" ) + print(string.format("| The local archive is older than %2i hours. |", age//3600 )) + print("| Have you executed l3build ctan first? If so ... |" ) + print("----------------------------------------------------" ) + else + print(string.format("The local archive is %i minutes old.", age//60 )) + end end print("Do you want to upload to CTAN? [y/n]" ) local answer="" diff --git a/Master/texmf-dist/scripts/l3build/l3build-variables.lua b/Master/texmf-dist/scripts/l3build/l3build-variables.lua index e3ae64e13be..f1032004b60 100644 --- a/Master/texmf-dist/scripts/l3build/l3build-variables.lua +++ b/Master/texmf-dist/scripts/l3build/l3build-variables.lua @@ -84,6 +84,7 @@ demofiles = demofiles or { } docfiles = docfiles or { } dynamicfiles = dynamicfiles or { } excludefiles = excludefiles or {"*~"} +exefiles = exefiles or { } installfiles = installfiles or {"*.sty","*.cls"} makeindexfiles = makeindexfiles or {"*.ist"} scriptfiles = scriptfiles or { } @@ -106,12 +107,10 @@ unpackdeps = unpackdeps or { } -- Executable names plus following options typesetexe = typesetexe or "pdflatex" unpackexe = unpackexe or "pdftex" -zipexe = zipexe or "zip" checkopts = checkopts or "-interaction=nonstopmode" typesetopts = typesetopts or "-interaction=nonstopmode" unpackopts = unpackopts or "" -zipopts = zipopts or "-v -r -X" -- Engines for testing checkengines = checkengines or {"pdftex", "xetex", "luatex"} diff --git a/Master/texmf-dist/scripts/l3build/l3build-zip.lua b/Master/texmf-dist/scripts/l3build/l3build-zip.lua new file mode 100644 index 00000000000..06f37cd8b3c --- /dev/null +++ b/Master/texmf-dist/scripts/l3build/l3build-zip.lua @@ -0,0 +1,119 @@ +--[[ + +File l3build-zip.lua Copyright (C) 2021 The LaTeX Project + +It may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this +license or (at your option) any later version. The latest version +of this license is in the file + + http://www.latex-project.org/lppl.txt + +This file is part of the "l3build bundle" (The Work in LPPL) +and all files in that bundle must be distributed together. + +----------------------------------------------------------------------- + +The development version of the bundle can be found at + + https://github.com/latex3/l3build + +for those people who are interested. + +--]] + +local concat = table.concat +local open = io.open +local osdate = os.date +local pack = string.pack +local setmetatable = setmetatable +local iotype = io.type + +local compress = zlib.compress +local crc32 = zlib.crc32 + +local function encode_time(unix) + local t = osdate('*t', unix) + local date = t.day | (t.month << 5) | ((t.year-1980) << 9) + local time = (t.sec//2) | (t.min << 5) | (t.hour << 11) + return date, time +end + +local meta = {__index = { + add = function(z, filename, innername, binary, executable) + innername = innername or filename + + local offset = z.f:seek'cur' + + local content do + local f = iotype(filename) and filename or assert(open(filename, binary and 'rb' or 'r')) + content = f:read'*a' + f:close() + end + local crc32 = crc32(crc32(), content) + local compressed = compress(content, nil, nil, -15) + if #compressed >= #content then + compressed = nil + end + local date, time = encode_time(nil) + z.f:write(pack("<c4I2I2I2I2I2I4I4I4I2I2", + 'PK\3\4', + compressed and 20 or 10, -- ZIP 2.0 to allow deflate + 0, -- We never set flags + compressed and 8 or 0, -- Always use deflate + time, + date, + crc32, + compressed and #compressed or #content, + #content, + #innername, + 0), + innername, + compressed or content) + local central = pack("<c4I2I2I2I2I2I2I4I4I4I2I2I2I2I2I4I4", + 'PK\1\2', + (3 << 8) | 63, -- Use UNIX attributes, written against ZIP 6.3 + compressed and 20 or 10, -- ZIP 2.0 to allow deflate + 0, -- We never set flags + compressed and 8 or 0, -- Always use deflate + time, + date, + crc32, + compressed and #compressed or #content, + #content, + #innername, + 0, -- no extra data + 0, -- no comment + 0, -- Disc 0 + binary and 0 or 1, + (executable and 0x81ED--[[0100755]] or 0x81A4--[[0100644]]) << 16, + offset) + z.central[#z.central+1] = central .. innername + end, + close = function(z, comment) + comment = comment or '' + + local offset = z.f:seek'cur' + local central = concat(z.central) + z.f:write(central, pack("<c4I2I2I2I2I4I4I2", + 'PK\5\6', + 0, -- This is disc 0 + 0, -- central dictionary started on disc 0 + #z.central, -- Central disctionary entries on this disc + #z.central, -- Central disctionary entries on all discs + #central, + offset, + #comment), comment) + return z.f:close() + end, +}} + +return function(filename) + local f, msg = open(filename, 'wb') + if not f then return f, msg end + return setmetatable({ + f = f, + offset = 1, + central = {}, + }, meta) +end diff --git a/Master/texmf-dist/scripts/l3build/l3build.lua b/Master/texmf-dist/scripts/l3build/l3build.lua index 82994397648..51b7a493e31 100755 --- a/Master/texmf-dist/scripts/l3build/l3build.lua +++ b/Master/texmf-dist/scripts/l3build/l3build.lua @@ -25,7 +25,7 @@ for those people who are interested. --]] -- Version information -release_date = "2021-05-06" +release_date = "2021-08-28" -- File operations are aided by the LuaFileSystem module local lfs = require("lfs") @@ -43,6 +43,8 @@ local print = print local select = select local tonumber = tonumber local exit = os.exit +local open = io.open +local stdout = io.stdout -- l3build setup and functions kpse.set_program_name("kpsewhich") @@ -160,6 +162,35 @@ if options["target"] == "check" then end print("") end + if options["show-saves"] then + local savecmds, recheckcmds = "", "" + for _,config in ipairs(failed) do + local testdir = testdir + if config ~= "build" then + testdir = testdir .. "-" .. config + end + local f = open(testdir .. "/.savecommands") + if not f then + print("Error: Cannot find save commands for configuration " .. + config) + exit(2) + end + for line in f:lines() do + if line == "" then break end + savecmds = savecmds .. " " .. line .. "\n" + end + for line in f:lines() do + recheckcmds = recheckcmds .. " " .. line .. "\n" + end + f:close() + end + print"To regenerate the test files, run\n" + print(savecmds) + if recheckcmds ~= "" then + print"To detect engine specific differences, run after that\n" + print(recheckcmds) + end + end exit(1) else -- Avoid running the 'main' set of tests twice diff --git a/Master/texmf-dist/source/latex/l3build/l3build.dtx b/Master/texmf-dist/source/latex/l3build/l3build.dtx index 5171f109720..8d340552275 100644 --- a/Master/texmf-dist/source/latex/l3build/l3build.dtx +++ b/Master/texmf-dist/source/latex/l3build/l3build.dtx @@ -121,7 +121,6 @@ \luavarseparator \luavarset{typesetexe} {"pdflatex"} {Executable for compiling \texttt{doc(s)}} \luavarset{unpackexe} {"pdftex"} {Executable for running \texttt{unpack}} -\luavarset{zipexe} {"zip"} {Executable for creating archive with \texttt{ctan}} \luavarset{biberexe} {"biber"} {Biber executable} \luavarset{bibtexexe} {"bibtex8"} {\BibTeX{} executable} \luavarset{makeindexexe} {"makeindex"}{MakeIndex executable} @@ -130,7 +129,6 @@ \luavarset{checkopts} {"-interaction=nonstopmode"}{Options passed to engine when running checks} \luavarset{typesetopts}{"-interaction=nonstopmode"}{Options passed to engine when typesetting} \luavarset{unpackopts} {""} {Options passed to engine when unpacking} -\luavarset{zipopts} {"-v -r -X"} {Options passed to zip program} \luavarset{biberopts} {""} {Biber options} \luavarset{bibtexopts} {"-W"} {\BibTeX{} options} \luavarset{makeindexopts}{""} {MakeIndex options} @@ -148,6 +146,7 @@ \luavarseparator \luavarset{asciiengines}{\{"pdftex"\}}{Engines which should log as pure ASCII} \luavarset{checkruns} {1} {Number of runs to complete for a test before comparing the log} +\luavarset{forcecheckruns}{false} {Always run \texttt{checkruns} runs and never stop early} \luavarset{ctanreadme}{"README.md"} {Name of the file to send to CTAN as \texttt{README.\meta{ext}}} \luavarset{ctanzip}{ctanpkg ... "-ctan"}{Name of the zip file (without extension) created for upload to CTAN} \luavarset{epoch} {1463734800} {Epoch (Unix date) to set for test runs} @@ -237,7 +236,7 @@ % }^^A % } % -% \date{Released 2021-05-06} +% \date{Released 2021-08-28} % % \maketitle % \tableofcontents @@ -314,7 +313,7 @@ % % When the build system runs, it creates a directory |build/| for various unpacking, compilation, and testing purposes. % For a module, this build folder can be in the main directory of the package itself, but for a bundle it should be common for the bundle itself and for all modules within that bundle. -% A |build/| folder can be safety deleted; all material within is re-generated for each command of the \pkg{l3build} system. +% A |build/| folder can be safely deleted; all material within is re-generated for each command of the \pkg{l3build} system. % % \subsection{The \texttt{build.lua} file} % @@ -379,6 +378,8 @@ % \item |--rerun| Run tests without unpacking/set up % \item |--show-log-on-error| To be used in addition to \texttt{--halt-on-error} and results % in the full \texttt{.log} file of a failed test to be shown on the console +% \item |--show-saves| (|-S|) When tests fail, print the \texttt{l3build save} commands needed +% to regenerate the tests assuming that the failures were false negatives. % \item |--shuffle| Shuffle the order in which tests run % \item |--texmfhome| Sets the location of the user tree for installing % \end{itemize} @@ -495,7 +496,7 @@ % % Binary files should be specified with the \var{binaryfiles} variable (default \luavar{binaryfiles}); these are added to the zip archive without normalising line endings (text files are automatically converted to Unix-style line endings). % -% To create the archive, by default the binary \var{zipexe} is used (\luavar{zipexe}) with options \var{zipopts} (|-v -r -X|). The intermediate build directories \var{ctandir} and \var{tdsdir} are used to construct the archive. +% The intermediate build directories \var{ctandir} and \var{tdsdir} are used to construct the archive. % \end{buildcmd} % % @@ -1117,6 +1118,34 @@ % \label{fig:test-tasks} % \end{figure} % +% \subsection{Instructions for rebuilding test output} +% +% Sometimes changes to fundamental parts of the code can cause a lot of tests +% to fail even though the actually tested systems are still working correctly. +% This is especially common when the logging and error reporting systems +% changes and therefore all log file based tests using the component fail with +% these changes. +% +% In these cases, the option |--show-saves| can be passed to +% |l3build check| in order to generate a list of |l3build save| commands which +% can be executed to regenerate the expected output of all tests which fail. +% Additionally it sometimes prints a list of |l3build check| commands for tests +% which might still fail due to engine differences after running the |save| +% commands. After running all these |l3build check| commands and all +% |l3build save| commands listed by them, all tests will succeed. +% +% When bundles are used |l3build check --show-saves| has to be executed +% separately for every module in the bundle. +% +% This option is potentially dangerous and therefore should only be used with +% care. It can easily hide valid test failures between a bunch of spurious +% changes. Therefore you should always take a close look at the difference +% files generated by |l3build check| before running the generated +% |l3build save| commands. Additionally it should only be used when you are +% aware of the reason why a large number of tests failed and the change +% causing the failures has been tested separately to have no unintended +% side effects. +% % \subsection{Epoch setting} % % To produce predictable output when using dates, the test system offers the |