diff options
| -rwxr-xr-x | luaotfload-tool.lua | 637 | ||||
| -rwxr-xr-x | mkstatus | 1 | 
2 files changed, 33 insertions, 605 deletions
diff --git a/luaotfload-tool.lua b/luaotfload-tool.lua index cd64a75..92483d6 100755 --- a/luaotfload-tool.lua +++ b/luaotfload-tool.lua @@ -4,11 +4,13 @@  --  DESCRIPTION:  database functionality  -- REQUIREMENTS:  luaotfload 2.2  --       AUTHOR:  Khaled Hosny, Élie Roux, Philipp Gesang ---      VERSION:  2.3b +--      VERSION:  2.4  --      LICENSE:  GPL v2 ---     MODIFIED:  2013-06-02 19:23:54+0200 +--     MODIFIED:  2013-07-28 13:12:04+0200  ----------------------------------------------------------------------- +local version = "2.4" --- <int: major>.<int: minor><alpha: fixes> +  --[[doc--  This file was originally written (as \fileent{mkluatexfontdb.lua}) by @@ -42,23 +44,12 @@ kpse.set_program_name "luatex"  local ioopen          = io.open  local iowrite         = io.write  local kpsefind_file   = kpse.find_file -local kpseexpand_var  = kpse.expand_var -local kpseexpand_path = kpse.expand_path -local lfsattributes   = lfs.attributes -local lfsisfile       = lfs.isfile -local lfsreadlink     = lfs.readlink -local md5sumhexa      = md5.sumhexa  local next            = next  local osdate          = os.date -local osgetenv        = os.getenv -local osremove        = os.remove -local osname          = os.name -local ostype          = os.type  local stringexplode   = string.explode  local stringformat    = string.format  local stringlower     = string.lower  local stringrep       = string.rep -local stringsub       = string.sub  local tableconcat     = table.concat  local texiowrite_nl   = texio.write_nl  local texiowrite      = texio.write @@ -79,7 +70,7 @@ else -- 5.2  end -local C, Cg, Ct, P, S  = lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S +local C, Ct, P, S  = lpeg.C, lpeg.Ct, lpeg.P, lpeg.S  local lpegmatch    = lpeg.match  local loader_file = "luatexbase.loader.lua" @@ -111,6 +102,7 @@ to be the more appropriate.  config                        = config or { }  local config                  = config  config.luaotfload             = config.luaotfload or { } +config.luaotfload.version     = config.luaotfload.version   or version  config.luaotfload.names_dir   = config.luaotfload.names_dir or "names"  config.luaotfload.cache_dir   = config.luaotfload.cache_dir or "fonts"  config.luaotfload.index_file  = config.luaotfload.index_file @@ -140,26 +132,33 @@ config.lualibs.prefer_merged    = true  config.lualibs.load_extended    = true  require "lualibs" - -local fileisreadable            = file.isreadable -local fileiswritable            = file.iswritable -local filesplitpath             = file.splitpath -local ioloaddata                = io.loaddata -local lua_of_json               = utilities.json.tolua  local tabletohash               = table.tohash  --[[doc--  \fileent{luatex-basics-gen.lua} calls functions from the  \luafunction{texio.*} library; too much for our taste.  We intercept them with dummies. + +Also, it sets up dummies in place of the tables created by the Context +libraries. Since we have loaded the lualibs already this would cause +collateral damage for some libraries whose namespace would be +overridden. We employ our usual backup-restore strategy to work around +this. (Postponing the loading of the lualibs code is not an option +because the functionality is needed by basics-gen itself.)  --doc]]--  local dummy_function = function ( ) end -local backup_write, backup_write_nl  = texio.write, texio.write_nl +local backup = { +    write     = texio.write, +    write_nl  = texio.write_nl, +    utilities = utilities, +}  texio.write, texio.write_nl          = dummy_function, dummy_function  require"luaotfload-basics-gen.lua" -texio.write, texio.write_nl          = backup_write, backup_write_nl + +texio.write, texio.write_nl          = backup.write, backup.write_nl +utilities                            = backup.utilities  require"luaotfload-override.lua"  --- this populates the logs.* namespace  require"luaotfload-database" @@ -167,12 +166,11 @@ require"alt_getopt"  local names = fonts.names -local status_file = "luaotfload-status" -local status      = require (status_file) - -local version  = "2.3b" +local status_file                    = "luaotfload-status" +local status                         = require (status_file) +config.luaotfload.status             = status -local sanitize_string = names.sanitize_string +local sanitize_string                = names.sanitize_string  local pathdata      = names.path  local names_plain   = pathdata.index.lua @@ -830,10 +828,6 @@ local get_fields get_fields = function (entry, fields, acc, n)      return acc  end -local comma       = P"," -local noncomma    = 1-comma -local split_comma = Ct((C(noncomma^1) + comma)^1) -  local separator = "\t" --- could be “,” for csv  local format_fields format_fields = function (fields, acc, n) @@ -869,12 +863,14 @@ set_primary_field = function (fields, addme, acc, n)      return acc  end +local splitcomma = names.patterns.splitcomma +  actions.list = function (job)      local criterion     = job.criterion      local asked_fields  = job.asked_fields      if asked_fields then -        asked_fields = lpegmatch(split_comma, asked_fields) +        asked_fields = lpegmatch(splitcomma, asked_fields)      else          --- some defaults          asked_fields = { "fullname", "version", } @@ -959,579 +955,10 @@ actions.list = function (job)      return true, true  end -do -    local out = function (...) -        logs.names_report (false, 0, "diagnose", ...) -    end - -    local verify_files = function (errcnt, status) -        out "================ verify files =================" -        local hashes = status.hashes -        local notes  = status.notes -        if not hashes or #hashes == 0 then -            out ("FAILED: cannot read checksums from %s.", status_file) -            return 1/0 -        elseif not notes then -            out ("FAILED: cannot read commit metadata from %s.", -                 status_file) -            return 1/0 -        end - -        out ("Luaotfload revision %s.", notes.revision) -        out ("Committed by %s.",        notes.committer) -        out ("Timestamp %s.",           notes.timestamp) - -        local nhashes = #hashes -        out ("Testing %d files for integrity.", nhashes) -        for i = 1, nhashes do -            local fname, canonicalsum = unpack (hashes[i]) -            local location = kpsefind_file (fname) -                          or kpsefind_file (fname, "texmfscripts") -            if not location then -                errcnt = errcnt + 1 -                out ("FAILED: file %s missing.", fname) -            else -                out ("File: %s.", location) -                local raw = ioloaddata (location) -                if not raw then -                    errcnt = errcnt + 1 -                    out ("FAILED: file %d not readable.", fname) -                else -                    local sum = md5sumhexa (raw) -                    if sum ~= canonicalsum then -                        errcnt = errcnt + 1 -                        out ("FAILED: checksum mismatch for file %s.", -                             fname) -                        out ("Expected %s.", canonicalsum) -                        out ("Got      %s.", sum) -                    else -                        out ("Ok, %s passed.", fname) -                    end -                end -            end -        end -        return errcnt -    end - -    local get_tentative_attributes = function (file) -        if not lfsisfile (file) then -            local chan = ioopen (file, "w") -            if chan then -                chan:close () -                local attributes = lfsattributes (file) -                os.remove (file) -                return attributes -            end -        end -    end - -    local p_permissions = Ct(Cg(Ct(C(1) * C(1) * C(1)), "u") -                           * Cg(Ct(C(1) * C(1) * C(1)), "g") -                           * Cg(Ct(C(1) * C(1) * C(1)), "o")) - -    local analyze_permissions = function (raw) -        return lpegmatch (p_permissions, raw) -    end - -    local stripslashes = names.patterns.stripslashes - -    local get_permissions = function (t, location) -        if stringsub (location, #location) == "/" then -            --- strip trailing slashes (lfs idiosyncrasy on Win) -            location = lpegmatch (stripslashes, location) -        end -        local attributes = lfsattributes (location) - -        if not attributes and t == "f" then -            attributes = get_tentative_attributes (location) -            if not attributes then -                return false -            end -        end - -        local permissions - -        if fileisreadable (location) then -            --- link handling appears to be unnecessary because -            --- lfs.attributes() will return the information on -            --- the link target. -            if mode == "link" then --follow and repeat -                location = lfsreadlink (location) -                attributes = lfsattributes (location) -            end -        end - -        permissions = analyze_permissions (attributes.permissions) - -        return { -            location    = location, -            mode        = attributes.mode, -            owner       = attributes.uid, --- useless on windows -            permissions = permissions, -            attributes  = attributes, -        } -    end - -    local check_conformance = function (spec, permissions, errcnt) -        local uid = permissions.attributes.uid -        local gid = permissions.attributes.gid -        local raw = permissions.attributes.permissions - -        out ("Owner: %d, group %d, permissions %s.", uid, gid, raw) -        if ostype == "unix" then -            if uid == 0 or gid == 0 then -                out "Owned by the superuser, permission conflict likely." -                errcnt = errcnt + 1 -            end -        end - -        local user = permissions.permissions.u -        if spec.r == true then -            if user[1] == "r" then -                out "Readable: ok." -            else -                out "Not readable: permissions need fixing." -                errcnt = errcnt + 1 -            end -        end - -        if spec.w == true then -            if user[2] == "w" -            or  fileiswritable (permissions.location) then -                out "Writable: ok." -            else -                out "Not writable: permissions need fixing." -                errcnt = errcnt + 1 -            end -        end - -        return errcnt -    end - -    local path = names.path - -    local desired_permissions = { -        { "d", {"r","w"}, function () return caches.getwritablepath () end }, -        { "d", {"r","w"}, path.globals.prefix }, -        { "f", {"r","w"}, path.index.lua }, -        { "f", {"r","w"}, path.index.luc }, -        { "f", {"r","w"}, path.lookups.lua }, -        { "f", {"r","w"}, path.lookups.luc }, -    } - -    local check_permissions = function (errcnt) -        out [[=============== file permissions ==============]] -        for i = 1, #desired_permissions do -            local t, spec, path = unpack (desired_permissions[i]) -            if type (path) == "function" then -                path = path () -            end - -            spec = tabletohash (spec) - -            out ("Checking permissions of %s.", path) - -            local permissions = get_permissions (t, path) -            if permissions then -                --inspect (permissions) -                errcnt = check_conformance (spec, permissions, errcnt) -            else -                errcnt = errcnt + 1 -            end -        end -        return errcnt -    end - -    local check_upstream - -    if kpsefind_file ("https.lua", "lua") == nil then -        check_upstream = function (errcnt) -            out       [[============= upstream repository ============= -                        WARNING: Cannot retrieve repository data. -                        Github API access requires the luasec library. -                        Grab it from <https://github.com/brunoos/luasec> -                        and retry.]] -            return errcnt -        end -    else -    --- github api stuff begin -        local https = require "ssl.https" - -        local gh_api_root     = [[https://api.github.com]] -        local release_url     = [[https://github.com/lualatex/luaotfload/releases]] -        local luaotfload_repo = [[lualatex/luaotfload]] -        local user_agent      = [[lualatex/luaotfload integrity check]] -        local shortbytes = 8 - -        local gh_shortrevision = function (rev) -            return stringsub (rev, 1, shortbytes) -        end - -        local gh_encode_parameters = function (parameters) -            local acc = {} -            for field, value in next, parameters do -                --- unsafe, non-urlencoded coz it’s all ascii chars -                acc[#acc+1] = field .. "=" .. value -            end -            return "?" .. tableconcat (acc, "&") -        end - -        local gh_make_url = function (components, parameters) -            local url = tableconcat ({ gh_api_root, -                                       unpack (components) }, -                                     "/") -            if parameters then -                url = url .. gh_encode_parameters (parameters) -            end -            return url -        end - -        local alright = [[HTTP/1.1 200 OK]] - -        local gh_api_request = function (...) -            local args    = {...} -            local nargs   = #args -            local final   = args[nargs] -            local request = { -                url     = "", -                headers = { ["user-agent"] = user_agent }, -            } -            if type (final) == "table" then -                args[nargs] = nil -                request = gh_make_url (args, final) -            else -                request = gh_make_url (args) -            end - -            out ("Requesting <%s>.", request) -            local response, code, headers, status -                = https.request (request) -            if status ~= alright then -                out "Request failed!" -                return false -            end -            return response -        end - -        local gh_api_checklimit = function (headers) -            local rawlimit  = gh_api_request "rate_limit" -            local limitdata = lua_of_json (rawlimit) -            if not limitdata and limitdata.rate then -                out "Cannot parse API rate limit." -                return false -            end -            limitdata = limitdata.rate - -            local limit = tonumber (limitdata.limit) -            local left  = tonumber (limitdata.remaining) -            local reset = tonumber (limitdata.reset) - -            out ("%d of %d Github API requests left.", left, limit) -            if left == 0 then -                out ("Cannot make any more API requests.") -                out ("Try again later at %s.", osdate ("%F %T", reset)) -            end -            return true -        end - -        local gh_tags = function () -            out "Fetching tags from repository, please stand by." -            local rawtags = gh_api_request ("repos", -                                            luaotfload_repo, -                                            "tags") -            local taglist = lua_of_json (rawtags) -            if not taglist or #taglist == 0 then -                out "Cannot parse response." -                return false -            end - -            local ntags = #taglist -            out ("Repository contains %d tags.", ntags) -            local _idx, latest = next (taglist) -            out ("The most recent release is %s (revision %s).", -                 latest.name, -            gh_shortrevision (latest.commit.sha)) -            return latest -        end - -        local gh_compare = function (head, base) -            if base == nil then -                base = "HEAD" -            end -            out ("Fetching comparison between %s and %s, \z -                  please stand by.", -                 gh_shortrevision (head), -                 gh_shortrevision (base)) -            local comparison = base .. "..." .. head -            local rawstatus = gh_api_request ("repos", -                                              luaotfload_repo, -                                              "compare", -                                              comparison) -            local status = lua_of_json (rawstatus) -            if not status then -                out "Cannot parse response for status request." -                return false -            end -            return status -        end - -        local gh_news = function (since) -            local compared  = gh_compare (since) -            if not compared then -                return false -            end -            local behind_by = compared.behind_by -            local ahead_by  = compared.ahead_by -            local status    = compared.status -            out ("Comparison state: %s.", status) -            if behind_by > 0 then -                out ("Your Luaotfload is %d \z -                      revisions behind upstream.", -                     behind_by) -                return behind_by -            elseif status == "ahead" then -                out "Since you are obviously from the future \z -                     I assume you already know the repository state." -            else -                out "Everything up to date. \z -                     Luaotfload is in sync with upstream." -            end -            return false -        end - -        local gh_catchup = function (current, latest) -            local compared = gh_compare (latest, current) -            local ahead_by = tonumber (compared.ahead_by) -            if ahead_by > 0 then -                local permalink_url = compared.permalink_url -                out ("Your Luaotfload is %d revisions \z -                      behind the most recent release.", -                     ahead_by) -                out ("To view the commit log, visit <%s>.", -                     permalink_url) -                out ("You can grab an up to date tarball at <%s>.", -                     release_url) -                return true -            else -                out "There weren't any new releases in the meantime." -                out "Luaotfload is up to date." -            end -            return false -        end - -        check_upstream = function (current) -            out "============= upstream repository =============" -            local _succ  = gh_api_checklimit () -            local behind = gh_news (current) -            if behind then -                local latest  = gh_tags () -                local _behind = gh_catchup (current, -                                            latest.commit.sha, -                                            latest.name) -            end -        end - -        --- trivium: diff since the first revision as pushed by Élie -        --- in 2009 -        --- local firstrevision = "c3ccb3ee07e0a67171c24960966ae974e0dd8e98" -        --- check_upstream (firstrevision) -    end -    --- github api stuff end - -    local print_envvar = function (var) -        local val = osgetenv (var) -        if val then -            out ("%20s: %q", stringformat ("$%s", var), val) -            return val -        else -            out ("%20s: <unset>", stringformat ("$%s", var)) -        end -    end - -    local print_path = function (var) -        local val = osgetenv (var) -        if val then -            local paths = filesplitpath (val) -            if paths then -                local npaths = #paths -                if npaths == 1 then -                    out ("%20s: %q", stringformat ("$%s", var), val) -                elseif npaths > 1 then -                    out ("%20s: <%d items>", stringformat ("$%s", var), npaths) -                    for i = 1, npaths do -                        out ("                   +: %q", paths[i]) -                    end -                else -                    out ("%20s: <empty>") -                end -            end -        else -            out ("%20s: <unset>", stringformat ("$%s", var)) -        end -    end - -    local print_kpsevar = function (var) -        var = "$" .. var -        local val = kpseexpand_var (var) -        if val and val ~= var then -            out ("%20s: %q", var, val) -            return val -        else -            out ("%20s: <empty or unset>", var) -        end -    end - -    local print_kpsepath = function (var) -        var = "$" .. var -        local val = kpseexpand_path (var) -        if val and val ~= "" then -            local paths = filesplitpath (val) -            if paths then -                local npaths = #paths -                if npaths == 1 then -                    out ("%20s: %q", var, paths[1]) -                elseif npaths > 1 then -                    out ("%20s: <%d items>", var, npaths) -                    for i = 1, npaths do -                        out ("                   +: %q", paths[i]) -                    end -                else -                    out ("%20s: <empty>") -                end -            end -        else -            out ("%20s: <empty or unset>", var) -        end -    end - -    --- this test first if a variable is set and then expands the -    --- paths; this is necessitated by the fact that expand-path will -    --- return the empty string both if the variable is unset and if -    --- the directory does not exist - -    local print_kpsepathvar = function (var) -        local vvar = "$" .. var -        local val = kpseexpand_var (vvar) -        if val and val ~= vvar then -            out ("%20s: %q", vvar, val) -            print_kpsepath (var) -        else -            out ("%20s: <empty or unset>", var) -        end -    end - -    local check_environment = function (errcnt) -        out "============ environment settings =============" -        out ("system: %s/%s", ostype, osname) -        if ostype == "unix" and io.popen then -            local chan = io.popen ("uname -a", "r") -            if chan then -                out ("info: %s", chan:read "*all") -                chan:close () -            end -        end - -        out "1) *shell environment*" -        print_envvar "SHELL" -        print_path "PATH" -        print_path "OSFONTDIR" -        print_envvar "USER" -        if ostype == "windows" then -            print_envvar "WINDIR" -            print_envvar "CD" -            print_path "TEMP" -        elseif ostype == "unix" then -            print_envvar "HOME" -            print_envvar "PWD" -            print_path "TMPDIR" -        end - -        out "2) *kpathsea*" -        print_kpsepathvar "OPENTYPEFONTS" -        print_kpsepathvar "TTFONTS" - -        print_kpsepathvar "TEXMFCACHE" -        print_kpsepathvar "TEXMFVAR" - -        --- the expansion of these can be quite large; as they aren’t -        --- usually essential to luaotfload, we won’t dump every single -        --- path -        print_kpsevar "LUAINPUTS" -        print_kpsevar "CLUAINPUTS" - -        return errcnt -    end - -    local anamneses   = { -        "environment", -        "files", -        "repository", -        "permissions" -    } - -    actions.diagnose = function (job) -        local errcnt = 0 -        local asked  = job.asked_diagnostics -        if asked == "all" or asked == "thorough" then -            asked = tabletohash (anamneses, true) -        else -            asked = lpegmatch(split_comma, asked) -            asked = tabletohash (asked, true) -        end - -        if asked.environment == true then -            errcnt = check_environment (errcnt) -            asked.environment = nil -        end - -        if asked.files == true then -            errcnt = verify_files (errcnt, status) -            asked.files = nil -        end - -        if asked.permissions == true then -            errcnt = check_permissions (errcnt) -            asked.permissions = nil -        end - -        if asked.repository == true then -            check_upstream (status.notes.revision) -            asked.repository = nil -        end - -        local rest = next (asked) -        if rest ~= nil then --> something unknown -            out ("Unknown diagnostic %q.", rest) -        end -        if errcnt == 0 then --> success -            out ("Everything appears to be in order, \z -                  you may sleep well.") -            return true, false -        end -        out (         [[=============================================== -                                            WARNING -                        =============================================== - -                        The diagnostic detected %d errors. - -                        This version of luaotfload may have been -                        tampered with. Modified versions of the -                        luaotfload source are unsupported. Read the log -                        carefully and get a clean version from CTAN or -                        github: - -                            × http://ctan.org/tex-archive/macros/luatex/generic/luaotfload -                            × https://github.com/lualatex/luaotfload/releases - -                        If you are uncertain as to how to proceed, then -                        ask on the lualatex mailing list: - -                            http://www.tug.org/mailman/listinfo/lualatex-dev - -                        =============================================== -]],          errcnt) -        return true, false -    end +actions.diagnose = function (job) +    --- diagnostics are loaded on demand +    local diagnose = require "luaotfload-diagnostics.lua" +    return diagnose (job)  end  --- stuff to be carried out prior to exit @@ -39,6 +39,7 @@ local names = {    "luaotfload-characters.lua",    "luaotfload-colors.lua",    "luaotfload-database.lua", +  "luaotfload-diagnostics.lua",    "luaotfload-extralibs.lua",    "luaotfload-features.lua",    "luaotfload-fonts-cbk.lua",  | 
