diff options
| author | Philipp Gesang <phg42.2a@gmail.com> | 2014-12-09 00:33:39 +0100 | 
|---|---|---|
| committer | Philipp Gesang <phg42.2a@gmail.com> | 2014-12-09 00:33:39 +0100 | 
| commit | 56d99fef8a1ec03daa1921aab018ebf104c64c99 (patch) | |
| tree | 212b066f1af6d66288614e3ad14163378abb96ac | |
| parent | 3cf2dcca26bee734bc2ba867ff5709af712c8df0 (diff) | |
| download | luaotfload-56d99fef8a1ec03daa1921aab018ebf104c64c99.tar.gz | |
[scripts] add early draft of import helper
| -rw-r--r-- | scripts/mkimport | 321 | 
1 files changed, 321 insertions, 0 deletions
diff --git a/scripts/mkimport b/scripts/mkimport new file mode 100644 index 0000000..f0e7410 --- /dev/null +++ b/scripts/mkimport @@ -0,0 +1,321 @@ +#!/usr/bin/env texlua +------------------------------------------------------------------------------- +--         FILE:  mkimport.lua +--        USAGE:  ./mkimport.lua +--  DESCRIPTION:  check luaotfload imports against Context +-- REQUIREMENTS:  luatex, the lualibs package, Context MkIV +--       AUTHOR:  Philipp Gesang (Phg), <phg@phi-gamma.net> +--      VERSION:  42 +--      CREATED:  2014-12-08 22:36:15+0100 +------------------------------------------------------------------------------- +-- + +------------------------------------------------------------------------------- +--- PURPOSE +---  +---  - Facilitate detecting changes in the fontloader source. +---  - Assist in updating source code and (partially) automate importing. +---  - Account for files in the plain fontloader distribution, alert in case of +---    additions or deletions. +---     +------------------------------------------------------------------------------- + +kpse.set_program_name "luatex" + +local lfs = require "lfs" +local md5 = require "md5" + +require "lualibs" + +local ioloaddata   = io.loaddata +local iowrite      = io.write +local md5sumhexa   = md5.sumhexa +local stringformat = string.format + +------------------------------------------------------------------------------- +-- config +------------------------------------------------------------------------------- + +local context_root      = "/home/phg/context/tex/texmf-context" +local our_prefix        = "fontloader" +local fontloader_subdir = "src/fontloader" + +local paths = { +  context    = "tex/context/base", +  fontloader = "tex/generic/context/luatex", +} + +local prefixes = { +  context    = nil, +  fontloader = "luatex", +} + +------------------------------------------------------------------------------- +-- helpers +------------------------------------------------------------------------------- + +local die = function (...) +  io.stderr:write "[fatal error]: " +  io.stderr:write (stringformat (...)) +  io.stderr:write "\naborting.\n" +  os.exit (1) +end + +local emphasis = function (txt) +  return stringformat("\x1b[1m%s\x1b[0m", txt) +end + +local msg = function (...) +  iowrite (stringformat (...)) +  iowrite "\n" +end + +local good_tag   = stringformat("[\x1b[1;30;%dmgood\x1b[0m]  · ", 42) +local bad_tag    = stringformat("[\x1b[1;30;%dmBAD\x1b[0m]   · ", 41) +local alert_tag  = stringformat("[\x1b[1;%dmalert\x1b[0m] · "   , 36) + +local good = function (...) +  local msg = (stringformat (...)) +  iowrite (good_tag) +  iowrite (msg) +  iowrite "\n" +end + +local bad = function (...) +  local msg = (stringformat (...)) +  iowrite (bad_tag) +  iowrite (msg) +  iowrite "\n" +end + +local attention = function (...) +  local msg = (stringformat (...)) +  iowrite (alert_tag) +  iowrite (msg) +  iowrite "\n" +end + +------------------------------------------------------------------------------- +-- definitions +------------------------------------------------------------------------------- + +--- Accounting of upstream files. There are different categories: +--- +---   · *essential*: Files required at runtime. +---   · *merged*:    Files merged into the fontloader package. +---   · *ignored*:   Lua files not merged, but part of the format. +---   · *tex*:       TeX code, i.e. format and examples. +---   · *lualibs*:   Files merged, but also provided by the Lualibs package. + +local imports = { +  fontloader = { +    { name = "basics-gen"        , ours = nil          , kind = "essential" }, +    { name = "basics-nod"        , ours = nil          , kind = "merged"    }, +    { name = "basics"            , ours = nil          , kind = "tex"       }, +    { name = "fonts-cbk"         , ours = nil          , kind = "merged"    }, +    { name = "fonts-def"         , ours = nil          , kind = "merged"    }, +    { name = "fonts-demo-vf-1"   , ours = nil          , kind = "ignored"   }, +    { name = "fonts-enc"         , ours = nil          , kind = "merged"    }, +    { name = "fonts-ext"         , ours = nil          , kind = "merged"    }, +    { name = "fonts-inj"         , ours = nil          , kind = "merged"    }, +    { name = "fonts-lua"         , ours = nil          , kind = "merged"    }, +    { name = "fonts-merged"      , ours = "fontloader" , kind = "essential" }, +    { name = "fonts-ota"         , ours = nil          , kind = "merged"    }, +    { name = "fonts-otn"         , ours = nil          , kind = "merged"    }, +    { name = "fonts"             , ours = nil          , kind = "merged"    }, +    { name = "fonts"             , ours = nil          , kind = "tex"       }, +    { name = "fonts-syn"         , ours = nil          , kind = "ignored"   }, +    { name = "fonts-tfm"         , ours = nil          , kind = "merged"    }, +    { name = "languages"         , ours = nil          , kind = "ignored"   }, +    { name = "languages"         , ours = nil          , kind = "tex"       }, +    { name = "math"              , ours = nil          , kind = "ignored"   }, +    { name = "math"              , ours = nil          , kind = "tex"       }, +    { name = "mplib"             , ours = nil          , kind = "ignored"   }, +    { name = "mplib"             , ours = nil          , kind = "tex"       }, +    { name = "plain"             , ours = nil          , kind = "tex"       }, +    { name = "preprocessor"      , ours = nil          , kind = "ignored"   }, +    { name = "preprocessor"      , ours = nil          , kind = "tex"       }, +    { name = "preprocessor-test" , ours = nil          , kind = "tex"       }, +    { name = "swiglib"           , ours = nil          , kind = "ignored"   }, +    { name = "swiglib"           , ours = nil          , kind = "tex"       }, +    { name = "swiglib-test"      , ours = nil          , kind = "ignored"   }, +    { name = "swiglib-test"      , ours = nil          , kind = "tex"       }, +    { name = "test"              , ours = nil          , kind = "tex"       }, +  }, --[[ [fontloader] ]] +  context = { --=> all merged +    { name = "data-con"          , ours = "data-con"          , kind = "merged"    }, +    { name = "font-afk"          , ours = "font-afk"          , kind = "merged"    }, +    { name = "font-afm"          , ours = "font-afm"          , kind = "merged"    }, +    { name = "font-cid"          , ours = "font-cid"          , kind = "merged"    }, +    { name = "font-con"          , ours = "font-con"          , kind = "merged"    }, +    { name = "font-def"          , ours = "font-def"          , kind = "merged"    }, +    { name = "font-ini"          , ours = "font-ini"          , kind = "merged"    }, +    { name = "font-map"          , ours = "font-map"          , kind = "merged"    }, +    { name = "font-otb"          , ours = "font-otb"          , kind = "merged"    }, +    { name = "font-otf"          , ours = "font-otf"          , kind = "merged"    }, +    { name = "font-oti"          , ours = "font-oti"          , kind = "merged"    }, +    { name = "font-otp"          , ours = "font-otp"          , kind = "merged"    }, +    { name = "font-tfm"          , ours = "font-tfm"          , kind = "merged"    }, +    { name = "l-boolean"         , ours = "l-boolean"         , kind = "lualibs"   }, +    { name = "l-file"            , ours = "l-file"            , kind = "lualibs"   }, +    { name = "l-function"        , ours = "l-function"        , kind = "lualibs"   }, +    { name = "l-io"              , ours = "l-io"              , kind = "lualibs"   }, +    { name = "l-lpeg"            , ours = "l-lpeg"            , kind = "lualibs"   }, +    { name = "l-lua"             , ours = "l-lua"             , kind = "lualibs"   }, +    { name = "l-math"            , ours = "l-math"            , kind = "lualibs"   }, +    { name = "l-string"          , ours = "l-string"          , kind = "lualibs"   }, +    { name = "l-table"           , ours = "l-table"           , kind = "lualibs"   }, +    { name = "util-str"          , ours = "util-str"          , kind = "lualibs"   }, +  }, --[[ [context] ]] +} --[[ [imports] ]] + +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 derive_category_path = function (cat) +  local subpath  = paths[cat] or die ("category " .. cat .. " unknown") +  local location = file.join (context_root, subpath) +  if not lfs.isdir (location) then +    die ("invalid base path defined for category " +         .. cat .. " at " .. location) +  end +  return location +end + +local derive_fullname = function (cat, name, kind) +  local tmp = prefixes[cat] +  tmp = tmp and tmp .. "-" .. name or name +  return tmp .. (kind == "tex" and ".tex" or ".lua") +end + +local derive_ourname = function (name) +  return our_prefix .. "-" .. name .. ".lua" +end + +local is_readable = function (f) +  local fh = io.open (f, "r") +  if fh then +    fh:close() +    return true +  end +  return false +end + +local summarize_news = function (status) +  local ni = #status.import +  local nc = #status.create +  local ng = #status.good +  local nm = #status.missing + +  msg "-----------------------------------------------------------------" +  msg ("Summary: Inspected %d files.", ni + nc + ng + nm) +  msg "-----------------------------------------------------------------" +  if ng > 0 then good      ("%d are up to date", ng) end +  if ni > 0 then attention ("%d changed"       , ni) end +  if nc > 0 then attention ("%d new"           , nc) end +  if nm > 0 then bad       ("%d missing"       , nm) end +  msg "-----------------------------------------------------------------" + +  if nm == 0 and nc == 0 and ni == 0 then +    return 0 +  end + +  return -1 +end + +local news = function () +  local status = { +    import  = { }, +    good    = { }, +    create  = { }, +    missing = { }, +  } + +  for cat, entries in next, imports do +    local location = derive_category_path (cat) +    local nfiles = #entries + +    for i = 1, nfiles do +      local def  = entries[i] +      local name = def.name +      local ours = def.ours +      local kind = def.kind +      local fullname = derive_fullname (cat, name, kind) +      local fullpath = file.join (location, fullname) +      local ourname  = derive_ourname (ours or name) +      local ourpath  = file.join (fontloader_subdir, ourname) -- relative +      local imported = false + +      if not is_readable (fullpath) then +        bad ("source for file %s not found at %s", +             emphasis (ourname), +             emphasis (fullpath)) +        status.missing[#status.missing + 1] = ourname +      else +        --- Source file exists and is readable. +        if not lfs.isdir (fontloader_subdir) then +          die ("path for fontloader tree (" +              .. fontloader_subdir .. ") is not a directory") +        end +        if is_readable (ourpath) then imported = true end +        local src_hash = hash_file (fullpath) +        local dst_hash = imported and hash_file (ourpath) +        local same     = src_hash == dst_hash -- same! + +        if same then +          good ("file %s unchanged", emphasis (ourname)) +          status.good[#status.good + 1] = ourname +        elseif not dst_hash then +          attention ("new file %s requires import from %s", +                    emphasis (ourname), +                    emphasis (fullpath)) +          status.create[#status.create + 1] = ourname +        else --- src and dst exist but differ +          attention ("file %s requires import", emphasis (ourname)) +          status.import[#status.import + 1] = ourname +        end +      end + +    end +  end + +  return summarize_news (status) +end + +local job_kind = table.mirrored { +  news   = news, +  import = function () end, +  tell   = function () end, +} + +------------------------------------------------------------------------------- +-- functionality +------------------------------------------------------------------------------- + +--- job_kind -> bool +local check_job = function (j) +  return job_kind[j] +end + +------------------------------------------------------------------------------- +-- entry point +------------------------------------------------------------------------------- + +local main = function () +  local job = arg[1] or "news" +  local runner = check_job (job) +  if not runner then die ("invalid job type “" .. job .. "”.") end +  return runner(arg) +end + +os.exit (main ()) + +--- vim:ft=lua:ts=2:et:sw=2  | 
