diff options
| -rwxr-xr-x | luaotfload-tool.lua | 232 | 
1 files changed, 217 insertions, 15 deletions
| diff --git a/luaotfload-tool.lua b/luaotfload-tool.lua index 79f1c26..825f888 100755 --- a/luaotfload-tool.lua +++ b/luaotfload-tool.lua @@ -38,16 +38,21 @@ kpse.set_program_name "luatex"  --doc]]-- + +local kpsefind_file   = kpse.find_file  local md5sumhexa      = md5.sumhexa +local next            = next +local osdate          = os.date  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 -local kpsefind_file   = kpse.find_file - +local tonumber        = tonumber +local type            = type  local runtime  if _G.getfenv ~= nil then -- 5.1 or LJ      if _G.jit ~= nil then @@ -120,11 +125,13 @@ end  config.lualibs                  = config.lualibs or { }  config.lualibs.verbose          = false  config.lualibs.prefer_merged    = true -config.lualibs.load_extended    = false +config.lualibs.load_extended    = true  require "lualibs" +--- dofile "util-jsn.lua" --- awaiting fix -local ioloaddata = io.loaddata +local lua_of_json               = utilities.json.tolua +local ioloaddata                = io.loaddata  --[[doc--  \fileent{luatex-basics-gen.lua} calls functions from the @@ -156,7 +163,7 @@ local help_messages = {      ["luaotfload-tool"] = [[  Usage: %s [OPTION]... -     +  Operations on the LuaTeX font database.  This tool is part of the luaotfload package. Valid options are: @@ -217,7 +224,7 @@ The font cache will be written to      mkluatexfontdb = [[  Usage: %s [OPTION]... -     +  Rebuild or update the LuaTeX font database.  Valid options: @@ -470,7 +477,7 @@ local display_general = function (fullinfo)                  val = #fullinfo[key]              end          elseif mode == "d" then -            val = os.date("%F %T", fullinfo[key]) +            val = osdate("%F %T", fullinfo[key])          end          if not val then              val = "<none>" @@ -927,7 +934,7 @@ do      end      local verify_files = function (errcnt) -        out ("Loading file hashes.") +        out "Loading file hashes."          local info   = require (status_file)          local hashes = info.hashes          local notes  = info.notes @@ -975,16 +982,213 @@ do          return errcnt, notes      end +    local check_upstream + +    if kpsefind_file ("https.lua", "lua") == nil then +        check_upstream = function () +            out       [[Github API access requires the luasec library. +                        WARNING: Cannot retrieve repository data. +                        Grab it from <https://github.com/brunoos/luasec> +                        and retry.]] +        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) +            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 + +      actions.diagnose = function (job)          local errcnt = 0 -        errcnt = verify_files (errcnt) +        errcnt, notes = verify_files (errcnt) +        --errcnt = check_upstream (notes.revision) + +        check_upstream (notes.revision)          if errcnt == 0 then --> success              out ("Everything appears to be in order, \z                    you may sleep well.")              return true, false -        else -            out (     [[=============================================== +        end +        out (         [[===============================================                                              WARNING                          =============================================== @@ -1005,10 +1209,8 @@ do                              http://www.tug.org/mailman/listinfo/lualatex-dev                          =============================================== -]], -                errcnt) -        end -        return false, false +]],          errcnt) +        return true, false      end  end | 
