[latex3-commits] [git/LaTeX3-latex3-l3build] newzip: Don't rely on external program for zip file generation (ae545a2)

Marcel Fabian Krüger tex at 2krueger.de
Thu Aug 5 19:10:18 CEST 2021


Repository : https://github.com/latex3/l3build
On branch  : newzip
Link       : https://github.com/latex3/l3build/commit/ae545a29b9bd1cebb64a70e7e858c806f283b80c

>---------------------------------------------------------------

commit ae545a29b9bd1cebb64a70e7e858c806f283b80c
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date:   Thu Aug 5 19:10:18 2021 +0200

    Don't rely on external program for zip file generation


>---------------------------------------------------------------

ae545a29b9bd1cebb64a70e7e858c806f283b80c
 l3build-ctan.lua      |  49 +++++++++++----------
 l3build-variables.lua |   1 +
 l3build-zip.lua       | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+), 23 deletions(-)

diff --git a/l3build-ctan.lua b/l3build-ctan.lua
index fd1491d..92d9ad4 100644
--- a/l3build-ctan.lua
+++ b/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 patt:match(name) 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), execfile(src))
+      end
+    end
+    return zip:close()
   end
   local errorlevel
   local standalone = false
diff --git a/l3build-variables.lua b/l3build-variables.lua
index e3ae64e..579dfd1 100644
--- a/l3build-variables.lua
+++ b/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 { }
diff --git a/l3build-zip.lua b/l3build-zip.lua
new file mode 100644
index 0000000..06f37cd
--- /dev/null
+++ b/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





More information about the latex3-commits mailing list.