diff options
Diffstat (limited to 'Master/texmf-dist/scripts/context/lua/mtx-update.lua')
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-update.lua | 431 |
1 files changed, 303 insertions, 128 deletions
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-update.lua b/Master/texmf-dist/scripts/context/lua/mtx-update.lua index 581774f1ea0..bc6ca402639 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-update.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-update.lua @@ -1,5 +1,5 @@ if not modules then modules = { } end modules ['mtx-update'] = { - version = 1.001, + version = 1.002, comment = "companion to mtxrun.lua", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", @@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['mtx-update'] = { -- Together with Arthur Reutenauer she made sure that it worked well on all -- platforms that matter. -texmf.instance = instance -- we need to get rid of this / maybe current instance in global table +local format, concat, gmatch = string.format, table.concat, string.gmatch scripts = scripts or { } scripts.update = scripts.update or { } @@ -19,9 +19,12 @@ scripts.update = scripts.update or { } minimals = minimals or { } minimals.config = minimals.config or { } +-- this is needed under windows +-- else rsync fails to set the right chmod flags to files + os.setenv("CYGWIN","nontsec") -scripts.update.formats = { +scripts.update.texformats = { "cont-en", "cont-nl", "cont-cz", @@ -30,109 +33,114 @@ scripts.update.formats = { "cont-it", "cont-ro", "cont-uk", - "metafun", + "cont-pe", + "cont-xp", "mptopdf", "plain" } +scripts.update.mpformats = { + "metafun", + "mpost", +} + +-- experimental is not functional at the moment + scripts.update.repositories = { "current", "experimental" } +-- more options than just these two are available (no idea why this is here) + scripts.update.versions = { "current", "latest" } +-- list of basic folders that are needed to make a functional distribution + +scripts.update.base = { + { "base/tex/", "texmf" }, + { "base/metapost/", "texmf" }, + { "fonts/common/", "texmf" }, + { "fonts/other/", "texmf" }, -- not *really* needed, but helpful + { "context/<version>/", "texmf-context" }, + { "context/img/", "texmf-context" }, + { "misc/setuptex/", "." }, + { "misc/web2c", "texmf" }, + { "bin/common/<platform>/", "texmf-<platform>" }, + { "bin/context/<platform>/", "texmf-<platform>" }, + { "bin/metapost/<platform>/", "texmf-<platform>" }, + { "bin/man/", "texmf-<platform>" }, +} + +-- binaries and font-related files +-- for pdftex we don't need OpenType fonts, for LuaTeX/XeTeX we don't need TFM files + scripts.update.engines = { ["luatex"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, { "fonts/new/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/<version>/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "context/config/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/<platform>/", "texmf-<platform>" }, - { "bin/context/<platform>/", "texmf-<platform>" }, - { "bin/metapost/<platform>/", "texmf-<platform>" }, { "bin/luatex/<platform>/", "texmf-<platform>" }, - { "bin/man/", "texmf-<platform>" } }, ["xetex"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, { "base/xetex/", "texmf" }, { "fonts/new/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/<version>/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "context/config/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/<platform>/", "texmf-<platform>" }, - { "bin/context/<platform>/", "texmf-<platform>" }, - { "bin/metapost/<platform>/", "texmf-<platform>" }, { "bin/xetex/<platform>/", "texmf-<platform>" }, - { "bin/man/", "texmf-<platform>" } }, ["pdftex"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, { "fonts/old/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/<version>/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "context/config/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/<platform>/", "texmf-<platform>" }, - { "bin/context/<platform>/", "texmf-<platform>" }, - { "bin/metapost/<platform>/", "texmf-<platform>" }, { "bin/pdftex/<platform>/", "texmf-<platform>" }, - { "bin/man/", "texmf-<platform>" } }, ["all"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, - { "base/xetex/", "texmf" }, - { "fonts/old/", "texmf" }, { "fonts/new/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/<version>/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "context/config/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/<platform>/", "texmf-<platform>" }, - { "bin/context/<platform>/", "texmf-<platform>" }, - { "bin/metapost/<platform>/", "texmf-<platform>" }, + { "fonts/old/", "texmf" }, + { "base/xetex/", "texmf" }, { "bin/luatex/<platform>/", "texmf-<platform>" }, { "bin/xetex/<platform>/", "texmf-<platform>" }, { "bin/pdftex/<platform>/", "texmf-<platform>" }, - { "bin/man/", "texmf-<platform>" } + }, +} + +scripts.update.goodies = { + ["scite"] = { + { "bin/<platform>/scite/", "texmf-<platform>" }, + }, + ["texworks"] = { + { "bin/<platform>/texworks/", "texmf-<platform>" }, }, } scripts.update.platforms = { - ["mswin"] = "mswin", - ["windows"] = "mswin", - ["win32"] = "mswin", - ["win"] = "mswin", - ["linux"] = "linux", - ["freebsd"] = "freebsd", - ["linux-32"] = "linux", - ["linux-64"] = "linux-64", - ["osx"] = "osx-intel", - ["osx-intel"] = "osx-intel", - ["osx-ppc"] = "osx-ppc", + ["mswin"] = "mswin", + ["windows"] = "mswin", + ["win32"] = "mswin", + ["win"] = "mswin", + ["linux"] = "linux", + ["freebsd"] = "freebsd", + ["freebsd-amd64"] = "freebsd-amd64", + ["linux-32"] = "linux", + ["linux-64"] = "linux-64", + ["linux32"] = "linux", + ["linux64"] = "linux-64", + ["linux-ppc"] = "linux-ppc", + ["ppc"] = "linux-ppc", + ["osx"] = "osx-intel", + ["macosx"] = "osx-intel", + ["osx-intel"] = "osx-intel", + ["osx-ppc"] = "osx-ppc", + ["osx-powerpc"] = "osx-ppc", + ["osxintel"] = "osx-intel", + ["osxppc"] = "osx-ppc", + ["osxpowerpc"] = "osx-ppc", + ["solaris-intel"] = "solaris-intel", + ["solaris-sparc"] = "solaris-sparc", + ["solaris"] = "solaris-sparc", +} + +-- the list is filled up later (when we know what modules to download) + +scripts.update.modules = { } function scripts.update.run(str) @@ -146,7 +154,7 @@ function scripts.update.run(str) end function scripts.update.fullpath(path) - if input.aux.rootbased_path(path) then + if file.is_rootbased_path(path) then return path else return lfs.currentdir() .. "/" .. path @@ -154,46 +162,147 @@ function scripts.update.fullpath(path) end function scripts.update.synchronize() + logs.report("update","start") + local texroot = scripts.update.fullpath(states.get("paths.root")) - local engines = states.get('engines') - local platforms = states.get('platforms') - local repositories = states.get('repositories') - local bin = states.get("rsync.program") - local url = states.get("rsync.server") - local version = states.get("context.version") + local engines = states.get('engines') or { } + local platforms = states.get('platforms') or { } + local repositories = states.get('repositories') -- minimals + local bin = states.get("rsync.program") -- rsync + local url = states.get("rsync.server") -- contextgarden.net + local version = states.get("context.version") -- current (or beta) + local extras = states.get("extras") -- extras (like modules) + local goodies = states.get("goodies") -- goodies (like editors) local force = environment.argument("force") + + bin = string.gsub(bin,"\\","/") + if not url:find("::$") then url = url .. "::" end local ok = lfs.attributes(texroot,"mode") == "directory" if not ok and force then dir.mkdirs(texroot) ok = lfs.attributes(texroot,"mode") == "directory" end + + if force then + dir.mkdirs(format("%s/%s", texroot, "texmf-cache")) + dir.mkdirs(format("%s/%s", texroot, "texmf-local")) + end + if ok or not force then - if force then - dir.mkdirs(string.format("%s/%s", texroot, "texmf-cache")) + + local fetched, individual, osplatform = { }, { }, os.currentplatform() + + -- takes a collection as argument and returns a list of folders + + local function collection_to_list_of_folders(collection, platform) + local archives = {} + for _, c in ipairs(collection) do + local archive = c[1] + archive = archive:gsub("<platform>", platform) + archive = archive:gsub("<version>", version) + archives[#archives+1] = archive + end + return archives end - local fetched, individual = { }, { } - for engine, _ in pairs(engines) do - local collections = scripts.update.engines[engine] - if collections then - for _, collection in ipairs(collections) do - for platform, _ in pairs(platforms) do - platform = scripts.update.platforms[platform] - if platform then - local archive = collection[1]:gsub("<platform>", platform) - local destination = string.format("%s/%s", texroot, collection[2]:gsub("<platform>", platform)) - destination = destination:gsub("\\","/") - archive = archive:gsub("<version>",version) - if platform == "windows" or platform == "mswin" then - destination = destination:gsub("([a-zA-Z]):/", "/cygdrive/%1/") - end - individual[#individual+1] = { archive, destination } + + -- takes a list of folders as argument and returns a string for rsync + -- sample input: + -- {'bin/common', 'bin/context'} + -- output: + -- 'minimals/current/bin/common minimals/current/bin/context' + + local function list_of_folders_to_rsync_string(list_of_folders) + local repository = 'current' + local prefix = format("%s/%s/", states.get('rsync.module'), repository) -- minimals/current/ + + return prefix .. concat(list_of_folders, format(" %s", prefix)) + end + + -- example of usage: print(list_of_folders_to_rsync_string(collection_to_list_of_folders(scripts.update.base, os.currentplatform))) + + -- rename function and add some more functionality: + -- * recursive/non-recursive (default: non-recursive) + -- * filter folders or regular files only (default: no filter) + -- * grep for size of included files (with --stats switch) + + local function get_list_of_files_from_rsync(list_of_folders) + -- temporary file to store the output of rsync (could be a more random name; watch for overwrites) + local temp_file = "rsync.tmp.txt" + -- a set of folders + local folders = {} + local command = format("%s %s'%s' > %s", bin, url, list_of_folders_to_rsync_string(list_of_folders), temp_file) + os.execute(command) + -- read output of rsync + local data = io.loaddata(temp_file) or "" + -- for every line extract the filename + for chmod, s in data:gmatch("([d%-][rwx%-]+).-(%S+)[\n\r]") do + -- skip "current" folder + if s ~= '.' and chmod:len() == 10 then + folders[#folders+1] = s + end + end + -- delete the file to which we have put output of rsync + os.remove(temp_file) + return folders + end + + -- rsync://contextgarden.net/minimals/current/modules/ + + if extras and type(extras) == "table" then + -- fetch the list of available modules from rsync server + local available_modules = get_list_of_files_from_rsync({"modules/"}) + -- hash of requested modules + -- local h = table.tohash(extras:split(",")) + for _, s in ipairs(available_modules) do + -- if extras == "all" or h[s] then + if extras.all or extras[s] then + scripts.update.modules[#scripts.update.modules+1] = { format("modules/%s/",s), "texmf-context" } + end + end + -- TODO: check if every module from the list has been added and issue warning otherwise + -- one idea to do it: remove every value from h once added and then check if anything is left in h + end + + local function add_collection(collection,platform) + if collection and platform then + platform = scripts.update.platforms[platform] + if platform then + for _, c in ipairs(collection) do + local archive = c[1]:gsub("<platform>", platform) + local destination = format("%s/%s", texroot, c[2]:gsub("<platform>", platform)) + destination = destination:gsub("\\","/") + archive = archive:gsub("<version>",version) + if osplatform == "windows" or osplatform == "mswin" then + destination = destination:gsub("([a-zA-Z]):/", "/cygdrive/%1/") end + individual[#individual+1] = { archive, destination } end end end end + + for platform, _ in pairs(platforms) do + add_collection(scripts.update.base,platform) + end + for platform, _ in pairs(platforms) do + add_collection(scripts.update.modules,platform) + end + for engine, _ in pairs(engines) do + for platform, _ in pairs(platforms) do + add_collection(scripts.update.engines[engine],platform) + end + end + + if goodies and type(goodies) == "table" then + for goodie, _ in pairs(goodies) do + for platform, _ in pairs(platforms) do + add_collection(scripts.update.goodies[goodie],platform) + end + end + end + local combined = { } for _, repository in ipairs(scripts.update.repositories) do if repositories[repository] then @@ -204,11 +313,11 @@ function scripts.update.synchronize() cd = { } combined[destination] = cd end - cd[#cd+1] = string.format("%s/%s/%s",states.get('rsync.module'),repository,archive) + cd[#cd+1] = format("%s/%s/%s",states.get('rsync.module'),repository,archive) end end end - if input.verbose then + if logs.verbose then for k, v in pairs(combined) do logs.report("update", k) for k,v in ipairs(v) do @@ -217,24 +326,53 @@ function scripts.update.synchronize() end end for destination, archive in pairs(combined) do - local archives, command = table.concat(archive," "), "" - local normalflags, deleteflags = states.get("rsync.flags.normal"), states.get("rsync.flags.delete") - if true then -- environment.argument("keep") or destination:find("%.$") then - command = string.format("%s %s %s'%s' '%s'", bin, normalflags, url, archives, destination) - else - command = string.format("%s %s %s %s'%s' '%s'", bin, normalflags, deleteflags, url, archives, destination) + local archives, command = concat(archive," "), "" + -- local normalflags, deleteflags = states.get("rsync.flags.normal"), states.get("rsync.flags.delete") + -- if environment.argument("keep") or destination:find("%.$") then + -- command = format("%s %s %s'%s' '%s'", bin, normalflags, url, archives, destination) + -- else + -- command = format("%s %s %s %s'%s' '%s'", bin, normalflags, deleteflags, url, archives, destination) + -- end + local normalflags, deleteflags = states.get("rsync.flags.normal"), "" + if (destination:find("texmf$") or destination:find("texmf%-context$")) and (not environment.argument("keep")) then + deleteflags = states.get("rsync.flags.delete") end - logs.report("mtx update", string.format("running command: %s",command)) + command = format("%s %s %s %s'%s' '%s'", bin, normalflags, deleteflags, url, archives, destination) + logs.report("mtx update", format("running command: %s",command)) if not fetched[command] then scripts.update.run(command) fetched[command] = command end end + + local function update_script(script, platform) + local bin = bin:gsub("\\","/") + local texroot = texroot:gsub("\\","/") + platform = scripts.update.platforms[platform] + if platform then + local command + if platform == 'mswin' then + bin = bin:gsub("([a-zA-Z]):/", "/cygdrive/%1/") + texroot = texroot:gsub("([a-zA-Z]):/", "/cygdrive/%1/") + command = string.format("%s -t %s/texmf-context/scripts/context/lua/%s.lua %s/texmf-mswin/bin/", bin, texroot, script, texroot) + else + command = string.format("%s -tgo --chmod=a+x %s/texmf-context/scripts/context/lua/%s.lua %s/texmf-%s/bin/%s", bin, texroot, script, texroot, platform, script) + end + logs.report("mtx update", format("updating %s for %s: %s", script, platform, command)) + scripts.update.run(command) + end + end + + for platform, _ in pairs(platforms) do + update_script('luatools',platform) + update_script('mtxrun',platform) + end + else - logs.report("mtx update", string.format("no valid texroot: %s",texroot)) + logs.report("mtx update", format("no valid texroot: %s",texroot)) end if not force then - logs.report("update", "use --force to really update") + logs.report("update", "use --force to really update files") end logs.report("update","done") end @@ -247,42 +385,72 @@ function table.fromhash(t) return h end - +-- make the ConTeXt formats function scripts.update.make() + logs.report("make","start") + local force = environment.argument("force") local texroot = scripts.update.fullpath(states.get("paths.root")) local engines = states.get('engines') + local goodies = states.get('goodies') local platforms = states.get('platforms') local formats = states.get('formats') - input.load_tree(texroot) + + resolvers.load_tree(texroot) + -- update filename database for pdftex/xetex scripts.update.run("mktexlsr") + -- update filename database for luatex scripts.update.run("luatools --generate") - local formatlist = table.concat(table.fromhash(formats), " ") + local askedformats = formats + local texformats = table.tohash(scripts.update.texformats) + local mpformats = table.tohash(scripts.update.mpformats) + for k,v in pairs(texformats) do + if not askedformats[k] then + texformats[k] = nil + end + end + for k,v in pairs(mpformats) do + if not askedformats[k] then + mpformats[k] = nil + end + end + local formatlist = concat(table.fromhash(texformats), " ") if formatlist ~= "" then for engine in pairs(engines) do - -- todo: just handle make here or in mtxrun --script context --make ---~ os.execute("set") - scripts.update.run(string.format("texexec --make --all --fast --%s %s",engine,formatlist)) + if engine == "luatex" then + scripts.update.run(format("context --make")) -- maybe also formatlist + else + -- todo: just handle make here or in mtxrun --script context --make + scripts.update.run(format("texexec --make --all --fast --%s %s",engine,formatlist)) + end end end + local formatlist = concat(table.fromhash(mpformats), " ") + if formatlist ~= "" then + scripts.update.run(format("texexec --make --all --fast %s",formatlist)) + end if not force then - logs.report("make", "use --force to really make") + logs.report("make", "use --force to really make formats") end + scripts.update.run("mktexlsr") + scripts.update.run("luatools --generate") logs.report("make","done") end -banner = banner .. " | download tools " +logs.extendbanner("Download Tools 0.20",true) messages.help = [[ ---platform=string platform (windows, linux, linux-64, osx-intel, osx-ppc) +--platform=string platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc) --server=string repository url (rsync://contextgarden.net) --module=string repository url (minimals) --repository=string specify version (current, experimental) --context=string specify version (current, latest, yyyy.mm.dd) --rsync=string rsync binary (rsync) ---texroot installation directory (not guessed for the moment) ---engine tex engine (luatex, pdftex, xetex) +--texroot=string installation directory (not guessed for the moment) +--engine=string tex engine (luatex, pdftex, xetex) +--extras=string extra modules (can be list or 'all') +--goodies=string extra binaries (like scite and texworks) --force instead of a dryrun, do the real thing --update update minimal tree --make also make formats and generate file databases @@ -290,8 +458,6 @@ messages.help = [[ --state update tree using saved state ]] -input.verbose = true - scripts.savestate = true if scripts.savestate then @@ -300,7 +466,7 @@ if scripts.savestate then -- tag, value, default, persistent - input.starttiming(states) + statistics.starttiming(states) states.set("info.version",0.1) -- ok states.set("info.count",(states.get("info.count") or 0) + 1,1,false) -- ok @@ -318,11 +484,11 @@ if scripts.savestate then states.set("context.version", environment.argument("context"), "current", true) -- ok local valid = table.tohash(scripts.update.repositories) - for r in string.gmatch(environment.argument("repository") or "current","([^, ]+)") do + for r in gmatch(environment.argument("repository") or "current","([^, ]+)") do if valid[r] then states.set("repositories." .. r, true) end end local valid = scripts.update.engines - for r in string.gmatch(environment.argument("engine") or "all","([^, ]+)") do + for r in gmatch(environment.argument("engine") or "all","([^, ]+)") do if r == "all" then for k, v in pairs(valid) do if k ~= "all" then @@ -334,12 +500,16 @@ if scripts.savestate then end end local valid = scripts.update.platforms - for r in string.gmatch(environment.argument("platform") or os.currentplatform(),"([^, ]+)") do + for r in gmatch(environment.argument("platform") or os.currentplatform(),"([^, ]+)") do if valid[r] then states.set("platforms." .. r, true) end end - local valid = table.tohash(scripts.update.formats) - for r in string.gmatch(environment.argument("formats") or "","([^, ]+)") do + local valid = table.tohash(scripts.update.texformats) + for r in gmatch(environment.argument("formats") or "","([^, ]+)") do + if valid[r] then states.set("formats." .. r, true) end + end + local valid = table.tohash(scripts.update.mpformats) + for r in gmatch(environment.argument("formats") or "","([^, ]+)") do if valid[r] then states.set("formats." .. r, true) end end @@ -347,7 +517,12 @@ if scripts.savestate then states.set("formats.cont-nl", true) states.set("formats.metafun", true) - -- modules + for r in gmatch(environment.argument("extras") or "","([^, ]+)") do + states.set("extras." .. r, true) + end + for r in gmatch(environment.argument("goodies") or "","([^, ]+)") do + states.set("goodies." .. r, true) + end logs.report("state","loaded") @@ -367,12 +542,12 @@ if environment.argument("update") then elseif environment.argument("make") then scripts.update.make() else - input.help(banner,messages.help) + logs.help(messages.help) end if scripts.savestate then - input.stoptiming(states) - states.set("info.runtime",tonumber(input.elapsedtime(states))) + statistics.stoptiming(states) + states.set("info.runtime",tonumber(statistics.elapsedtime(states))) if environment.argument("force") then states.save() logs.report("state","saved") |