#!/usr/bin/env texlua
-----------------------------------------------------------------------
-- FILE: mkstatus.lua
-- USAGE: ./mkstatus.lua
-- DESCRIPTION: writes the repository state
-- REQUIREMENTS: luatex, the lualibs package
-- AUTHOR: Philipp Gesang (Phg), <phg42.2a@gmail.com>
-- VERSION: 1.0
-- CREATED: 2013-07-07 14:01:12+0200
-----------------------------------------------------------------------
--
-- This script generates a list of hashes that serves as the input
-- for the file integrity check (option --diagnose). md5 is all we can
-- assume in Luatex, so it’s really only a superficial test.
--
-- Not that this file also incorporates the Git revision information.
-- Of this, only the actual commit hash is authoritative. The latest
-- tag is included for reference only. Besides that, it’s meaningless.
-- Do not rely on it: Two distinct versions of Luaotfload might very
-- well share the same tag.
kpse.set_program_name "luatex"
local md5 = require "md5"
require "lualibs"
local stringformat = string.format
local md5sumhexa = md5.sumhexa
local ioloaddata = io.loaddata
local iosavedata = io.savedata
local iopopen = io.popen
local iowrite = io.write
local lfsisdir = lfs.isdir
local stringmatch = string.match
-----------------------------------------------------------------------
-- settings
-----------------------------------------------------------------------
local verbose = false
local filelist = "./build/luaotfload-status.lua" --- result
local srcdir = "src"
local builddir = "build"
local scriptdir = "scripts"
local loaderdir = "src/fontloader"
local rtdir = "src/fontloader/runtime"
local miscdir = "src/fontloader/misc"
local names = {
--- Luaotfload runtime files
{ srcdir, "luaotfload-auxiliary.lua", },
{ srcdir, "luaotfload-colors.lua", },
{ srcdir, "luaotfload-configuration.lua", },
{ srcdir, "luaotfload-database.lua", },
{ srcdir, "luaotfload-diagnostics.lua", },
{ srcdir, "luaotfload-features.lua", },
{ srcdir, "luaotfload-init.lua", },
{ srcdir, "luaotfload-letterspace.lua", },
{ srcdir, "luaotfload-loaders.lua", },
{ srcdir, "luaotfload-log.lua", },
{ srcdir, "luaotfload-main.lua", },
{ srcdir, "luaotfload-parsers.lua", },
{ srcdir, "luaotfload-resolvers.lua", },
{ srcdir, "luaotfload-tool.lua", },
--- generated files
{ builddir, "luaotfload-characters.lua", },
{ builddir, "luaotfload-glyphlist.lua", },
--- scripts
{ scriptdir, "mkcharacters", },
{ scriptdir, "mkglyphlist", },
{ scriptdir, "mkimport", },
{ scriptdir, "mkstatus", },
{ scriptdir, "mktests", },
--- fontloader runtimes
{ rtdir, "fontloader-basics-gen.lua", },
{ rtdir, "fontloader-reference.lua", },
{ rtdir, "fontloader-tl2014.lua", },
--- fontloader constituents
{ miscdir, "fontloader-basics-nod.lua", },
{ miscdir, "fontloader-data-con.lua", },
{ miscdir, "fontloader-font-afk.lua", },
{ miscdir, "fontloader-font-afm.lua", },
{ miscdir, "fontloader-font-cid.lua", },
{ miscdir, "fontloader-font-con.lua", },
{ miscdir, "fontloader-font-def.lua", },
{ miscdir, "fontloader-font-ini.lua", },
{ miscdir, "fontloader-font-map.lua", },
{ miscdir, "fontloader-font-oti.lua", },
{ miscdir, "fontloader-font-gbn.lua", },
{ miscdir, "fontloader-font-def.lua", },
{ miscdir, "fontloader-fonts-demo-vf-1.lua", },
{ miscdir, "fontloader-fonts-enc.lua", },
{ miscdir, "fontloader-fonts-ext.lua", },
{ miscdir, "fontloader-fonts.lua", },
{ miscdir, "fontloader-font-lua.lua", },
{ miscdir, "fontloader-fonts-syn.lua", },
{ miscdir, "fontloader-font-tfm.lua", },
{ miscdir, "fontloader-font-tfm.lua", },
{ miscdir, "fontloader-font-otr.lua", },
{ miscdir, "fontloader-font-cff.lua", },
{ miscdir, "fontloader-font-ttf.lua", },
{ miscdir, "fontloader-font-dsp.lua", },
{ miscdir, "fontloader-font-oup.lua", },
{ miscdir, "fontloader-font-otl.lua", },
{ miscdir, "fontloader-font-oto.lua", },
{ miscdir, "fontloader-font-otj.lua", },
{ miscdir, "fontloader-font-ota.lua", },
{ miscdir, "fontloader-font-ots.lua", },
{ miscdir, "fontloader-font-osd.lua", },
--- lua libraries
{ miscdir, "fontloader-languages.lua", },
{ miscdir, "fontloader-l-boolean.lua", },
{ miscdir, "fontloader-l-file.lua", },
{ miscdir, "fontloader-l-function.lua", },
{ miscdir, "fontloader-l-io.lua", },
{ miscdir, "fontloader-l-lpeg.lua", },
{ miscdir, "fontloader-l-lua.lua", },
{ miscdir, "fontloader-l-math.lua", },
{ miscdir, "fontloader-l-string.lua", },
{ miscdir, "fontloader-l-table.lua", },
{ miscdir, "fontloader-math.lua", },
{ miscdir, "fontloader-mplib.lua", },
{ miscdir, "fontloader-preprocessor.lua", },
{ miscdir, "fontloader-swiglib.lua", },
{ miscdir, "fontloader-swiglib-test.lua", },
{ miscdir, "fontloader-util-str.lua", },
{ miscdir, "fontloader-util-fil.lua", },
} --[[local names]]
-----------------------------------------------------------------------
-- helpers
-----------------------------------------------------------------------
local die = function (...)
io.stderr:write "[fatal error]: "
io.stderr:write (stringformat (...))
io.stderr:write "\naborting.\n"
os.exit (1)
end
local logcmd = "git log -1 \z
--format=\"return {\z
%n revision = [[%H]],\z
%n timestamp = [[%cd]],\z
%n committer = [[%cn <%ce>]],\z
%n}\" \z
--date=iso"
local describecmd = "git describe --all"
local readpipe = function (cmd)
local chan = iopopen (cmd)
if not chan then
die ("this script needs to be run inside \z
the luaotfload git repository")
end
local data = chan:read "*all"
chan:close ()
return data
end
local git_info = function ()
--io.write (logcmd)
--io.write "\n"
local desc = readpipe (describecmd)
if not desc then die "cannot parse git information" end
desc = string.fullstrip (desc)
local desc = string.explode (desc, "/")[2] or desc
if not desc then die "cannot parse sanitized git information" end
local data = readpipe (logcmd)
if data and type (data) == "string" and data ~= "" then
data = load (data)
if not data then
die "cannot parse git information"
end
data = data ()
data.description = desc
return data
end
die "cannot read from pipe"
end
-----------------------------------------------------------------------
-- functionality
-----------------------------------------------------------------------
local hash_file = function (fname)
if not lfs.isfile (fname) then
die ("cannot find %s.", fname)
end
local raw = ioloaddata (fname)
if not raw then
die ("cannot read from %s.", fname)
end
return md5sumhexa (raw)
end
local hash_all
hash_all = function (list, acc)
if acc == nil then
local base = table.fastcopy (names)
return hash_all (table.append (base, list), { })
end
local finfo = list[#list]
list[#list] = nil
if finfo then
local fpath, fname
if type (finfo) == "table" then
local d, f = finfo [1], finfo [2]
if lfs.isdir (d) then
fpath = file.join (d, f)
else
fpath = f
end
fname = f
else
fpath = finfo
end
if verbose then
iowrite "· md5("
iowrite (fpath)
end
local sum = hash_file (fpath)
if verbose then
iowrite ") = \""
iowrite (sum)
iowrite "\"\n"
end
acc[#acc+1] = { fname, sum }
return hash_all (list, acc)
end
return acc
end
local handle_argv = function (argv)
local ret = { files = { }, loader = nil }
local argc = #argv
if argc < 1 then return ret end
local argoff = 1
if argv [1] == "-v" then
verbose = true
if argc == 1 then return ret end
argoff = 2
end
local aux aux = function (acc, i)
if i > argc then return acc else
local cur = argv[i]
if type (cur) == "string" then
local loader = stringmatch (cur, "--fontloader=(.+)$")
if loader then
cur = loader
acc.loader = file.basename (cur)
end
if lfs.isfile (cur) then
local files = acc.files
files[#files + 1] = cur
end
else
die ("file not found: %s", tostring (cur))
end
return aux (acc, i + 1)
end
end
return aux (ret, argoff)
end
local add_files
add_files = function (lst, acc)
if lst == nil then return end
if acc == nil then return add_files (lst, { }) end
local len = #lst
if len == 0 then return acc end
local cur = lst[len]
local fname = file.basename (cur)
local path = file.dirname (cur)
acc[#acc + 1] = { path, fname }
lst[len] = nil
return add_files (lst, acc)
end
local main = function ()
local raw_extra = handle_argv (arg)
local cuit_extra = add_files (raw_extra.files)
local hashes = hash_all (cuit_extra)
local notes = git_info ()
notes.loader = raw_extra.loader
local serialized = table.serialize ({ notes = notes,
hashes = hashes }, true)
local success = io.savedata (filelist, serialized)
if success == false then
die ("could not write to %s.", filelist)
end
return 0
end
return main ()
--- vim:ft=lua:ts=2:et:sw=2