summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/data-tar.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/data-tar.lua')
-rw-r--r--tex/context/base/mkiv/data-tar.lua236
1 files changed, 236 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/data-tar.lua b/tex/context/base/mkiv/data-tar.lua
new file mode 100644
index 000000000..45de749b6
--- /dev/null
+++ b/tex/context/base/mkiv/data-tar.lua
@@ -0,0 +1,236 @@
+if not modules then modules = { } end modules ['data-tar'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, find, match = string.format, string.find, string.match
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_tar = logs.reporter("resolvers","tar")
+
+--[[ldx--
+<p>We use a url syntax for accessing the tar file itself and file in it:</p>
+
+<typing>
+tar:///oeps.tar?name=bla/bla.tex
+tar:///oeps.tar?tree=tex/texmf-local
+</typing>
+--ldx]]--
+
+local resolvers = resolvers
+local findfile = resolvers.findfile
+local registerfile = resolvers.registerfile
+local splitmethod = resolvers.splitmethod
+local starttiming = resolvers.starttiming
+local stoptiming = resolvers.stoptiming
+
+local urlquery = url.query
+
+--- hm, zip sits in the global namespace, but tar doesn't
+
+local tar = utilities.tar or { }
+utilities.tar = tar -- not needed
+
+local archives = tar.archives or { }
+tar.archives = archives
+
+local registeredfiles = tar.registeredfiles or { }
+tar.registeredfiles = registeredfiles
+
+-- foo.tar.xz : done
+-- foo.tar.gz : todo
+-- foo.tar : done
+
+local hashtar, fetchtar, wipetar do
+
+ local suffix = file.suffix -- hassuffix .. no need to split
+
+ local tarfiles = utilities.tar.file
+ local tarstrings = utilities.tar.string
+
+ local hashtarfile = tar.files.hash
+ local fetchtarfile = tar.files.fetch
+
+ local hashtarstring = tar.strings.hash
+ local fetchtarstring = tar.strings.fetch
+
+ local register = resolvers.decompressors.register
+
+ hashtar = function(archive,strip)
+ local a = register(archive)
+ if a then
+ return hashtarstring(a,archive)
+ else
+ return hashtarfile(archive,archive)
+ end
+ end
+
+ fetchtar = function(archive,filename,list)
+ local a = register(archive)
+ if a then
+ return fetchtarstring(a,filename,list)
+ else
+ return fetchtarfile(archive,filename,list)
+ end
+ end
+
+ wipetar = resolvers.decompressors.unregister
+
+end
+
+local function validfile(archive,name)
+ return archive[name]
+end
+
+local function openarchive(name)
+ if not name or name == "" then
+ return nil
+ else
+ local arch = archives[name]
+ if not arch then
+ local full = findfile(name) or ""
+ arch = full ~= "" and hashtar(full,name) or false
+ archives[name] = arch
+ end
+ return arch
+ end
+end
+
+local function closearchive(name)
+ if not name or (name == "" and archives[name]) then
+ archives[name] = nil
+ wipetar(name)
+ end
+end
+
+tar.openarchive = openarchive
+tar.closearchive = closearchive
+
+function resolvers.locators.tar(specification)
+ local archive = specification.filename
+ local tarfile = archive and archive ~= "" and openarchive(archive)
+ if trace_locating then
+ if tarfile then
+ report_tar("locator: archive %a found",archive)
+ else
+ report_tar("locator: archive %a not found",archive)
+ end
+ end
+end
+
+function resolvers.concatinators.tar(tarfile,path,name) -- ok ?
+ if not path or path == "" then
+ return format('%s?name=%s',tarfile,name)
+ else
+ return format('%s?name=%s/%s',tarfile,path,name)
+ end
+end
+
+local finders = resolvers.finders
+local notfound = finders.notfound
+
+function finders.tar(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = urlquery(specification.query)
+ local queryname = query.name
+ if queryname then
+ local tfile = openarchive(archive)
+ if tfile then
+ if trace_locating then
+ report_tar("finder: archive %a found",archive)
+ end
+ if validfile(tfile,queryname) then
+ if trace_locating then
+ report_tar("finder: file %a found",queryname)
+ end
+ return specification.original
+ elseif trace_locating then
+ report_tar("finder: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_tar("finder: unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_tar("finder: %a not found",original)
+ end
+ return notfound()
+end
+
+local openers = resolvers.openers
+local notfound = openers.notfound
+local textopener = openers.helpers.textopener
+
+function openers.tar(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = urlquery(specification.query)
+ local queryname = query.name
+ if queryname then
+ local tfile = openarchive(archive)
+ if tfile then
+ if trace_locating then
+ report_tar("opener; archive %a opened",archive)
+ end
+ local data = fetchtar(archive,queryname,tfile)
+ if data then
+ if trace_locating then
+ report_tar("opener: file %a found",queryname)
+ end
+ return textopener('tar',original,data) -- a string handle
+ elseif trace_locating then
+ report_tar("opener: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_tar("opener: unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_tar("opener: %a not found",original)
+ end
+ return notfound()
+end
+
+loaders = resolvers.loaders
+local notfound = loaders.notfound
+
+function loaders.tar(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = urlquery(specification.query)
+ local queryname = query.name
+ if queryname then
+ local tfile = openarchive(archive)
+ if tfile then
+ if trace_locating then
+ report_tar("loader: archive %a opened",archive)
+ end
+ local data = fetchtar(archive,queryname,tfile)
+ if data then
+ if trace_locating then
+ report_tar("loader; file %a loaded",original)
+ end
+ return true, data, #data
+ elseif trace_locating then
+ report_tar("loader: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_tar("loader; unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_tar("loader: %a not found",original)
+ end
+ return notfound()
+end